Display queries properly in UHN implementation

This commit is contained in:
James Agnew 2014-07-07 15:37:23 -04:00
parent b1a602d88b
commit 0484c6509f
15 changed files with 198 additions and 111 deletions

View File

@ -401,7 +401,7 @@ public class IdDt extends BasePrimitive<String> {
}
/**
* @deprecated Use {@link #getIdPartAsBigDecimal()} instead
* @deprecated Use {@link #getIdPartAsBigDecimal()} instead (this method was deprocated because its name is ambiguous)
*/
public BigDecimal asBigDecimal() {
return getIdPartAsBigDecimal();

View File

@ -23,6 +23,8 @@ package ca.uhn.fhir.rest.param;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
@ -45,6 +47,11 @@ final class QueryParameterTypeBinder implements IParamBinder {
@Override
public Object parse(List<QualifiedParamList> theParams) throws InternalErrorException, InvalidRequestException {
String value = theParams.get(0).get(0);
if (StringUtils.isBlank(value)) {
return null;
}
IQueryParameterType dt;
try {
dt = myType.newInstance();
@ -55,7 +62,7 @@ final class QueryParameterTypeBinder implements IParamBinder {
throw new InvalidRequestException("Multiple values detected");
}
dt.setValueAsQueryToken(theParams.get(0).getQualifier(), theParams.get(0).get(0));
dt.setValueAsQueryToken(theParams.get(0).getQualifier(), value);
} catch (InstantiationException e) {
throw new InternalErrorException(e);
} catch (IllegalAccessException e) {

View File

@ -54,6 +54,22 @@ public class SearchTest {
assertEquals("IDAAA (identifier123)", bundle.getEntries().get(0).getTitle().getValue());
}
@Test
public void testOmitEmptyOptionalParam() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_id=");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.getEntries().size());
Patient p = bundle.getResources(Patient.class).get(0);
assertEquals(null, p.getNameFirstRep().getFamilyFirstRep().getValue());
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
@ -95,7 +111,9 @@ public class SearchTest {
Patient patient = new Patient();
patient.setId("1");
patient.addIdentifier("system", "identifier123");
patient.addName().addFamily("id"+theParam.getValue());
if (theParam!=null) {
patient.addName().addFamily("id"+theParam.getValue());
}
retVal.add(patient);
return retVal;
}

View File

@ -71,50 +71,16 @@ public class Controller {
private TemplateEngine myTemplateEngine;
@RequestMapping(value = { "/about" })
public String about( final HomeRequest theRequest, final ModelMap theModel) {
public String actionAbout(final HomeRequest theRequest, final ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
loadAndAddConformance(theRequest, theModel, client);
theModel.put("notHome", true);
theModel.put("extraBreadcrumb", "About");
return "about";
}
@RequestMapping(value = { "/transaction" })
public String actionTransaction(final TransactionRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
loadAndAddConformance(theRequest, theModel, client);
String body = preProcessMessageBody(theRequest.getTransactionBody());
Bundle bundle;
try {
if (body.startsWith("{")) {
bundle = myCtx.newJsonParser().parseBundle(body);
} else if (body.startsWith("<")) {
bundle = myCtx.newXmlParser().parseBundle(body);
} else {
theModel.put("errorMsg", "Message body does not appear to be a valid FHIR resource instance document. Body should start with '<' (for XML encoding) or '{' (for JSON encoding).");
return "home";
}
} catch (DataFormatException e) {
ourLog.warn("Failed to parse bundle", e);
theModel.put("errorMsg", "Failed to parse transaction bundle body. Error was: " + e.getMessage());
return "home";
}
long start = System.currentTimeMillis();
client.transaction().withBundle(bundle).execute();
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, ResultType.BUNDLE, theModel, delay, "Transaction");
return "result";
}
@RequestMapping(value = { "/conformance" })
public String actionConformance(final HomeRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) {
@ -262,11 +228,17 @@ public class Controller {
url = url.replace("&amp;", "&");
ResultType returnsResource = ResultType.BUNDLE;
long start = System.currentTimeMillis();
client.loadPage().url(url).execute();
try {
client.loadPage().url(url).execute();
} catch (Exception e) {
returnsResource = ResultType.NONE;
ourLog.warn("Failed to invoke server", e);
}
long delay = System.currentTimeMillis() - start;
ResultType returnsResource = ResultType.BUNDLE;
String outcomeDescription = "Bundle Page";
processAndAddLastClientInvocation(client, returnsResource, theModel, delay, outcomeDescription);
@ -440,6 +412,40 @@ public class Controller {
return "result";
}
@RequestMapping(value = { "/transaction" })
public String actionTransaction(final TransactionRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) {
addCommonParams(theRequest, theModel);
GenericClient client = theRequest.newClient(myCtx, myConfig);
loadAndAddConformance(theRequest, theModel, client);
String body = preProcessMessageBody(theRequest.getTransactionBody());
Bundle bundle;
try {
if (body.startsWith("{")) {
bundle = myCtx.newJsonParser().parseBundle(body);
} else if (body.startsWith("<")) {
bundle = myCtx.newXmlParser().parseBundle(body);
} else {
theModel.put("errorMsg", "Message body does not appear to be a valid FHIR resource instance document. Body should start with '<' (for XML encoding) or '{' (for JSON encoding).");
return "home";
}
} catch (DataFormatException e) {
ourLog.warn("Failed to parse bundle", e);
theModel.put("errorMsg", "Failed to parse transaction bundle body. Error was: " + e.getMessage());
return "home";
}
long start = System.currentTimeMillis();
client.transaction().withBundle(bundle).execute();
long delay = System.currentTimeMillis() - start;
processAndAddLastClientInvocation(client, ResultType.BUNDLE, theModel, delay, "Transaction");
return "result";
}
@RequestMapping(value = { "/validate" })
public String actionValidate(final HttpServletRequest theReq, final HomeRequest theRequest, final BindingResult theBindingResult, final ModelMap theModel) {
doActionCreateOrValidate(theReq, theRequest, theBindingResult, theModel, "validate");
@ -545,25 +551,6 @@ public class Controller {
}
private String preProcessMessageBody(String theBody) {
if (theBody == null) {
return "";
}
String retVal = theBody.trim();
StringBuilder b = new StringBuilder();
for (int i = 0; i < retVal.length(); i++) {
char nextChar = retVal.charAt(i);
int nextCharI = nextChar;
if (nextCharI == 65533) {
continue;
}
b.append(nextChar);
}
retVal = b.toString();
return retVal;
}
private void doActionHistory(HttpServletRequest theReq, HomeRequest theRequest, BindingResult theBindingResult, ModelMap theModel, String theMethod, String theMethodDescription) {
addCommonParams(theRequest, theModel);
@ -710,6 +697,41 @@ public class Controller {
return b.toString();
}
private String formatUrl(String theResultBody) {
String str = theResultBody;
if (str == null) {
return str;
}
StringBuilder b = new StringBuilder();
boolean inParams = false;
for (int i = 0; i < str.length(); i++) {
char nextChar = str.charAt(i);
if (!inParams) {
if (nextChar == '?') {
inParams = true;
b.append("<wbr /><span class='hlControl'>?</span><span class='hlTagName'>");
} else {
b.append(nextChar);
}
} else {
if (nextChar == '&') {
b.append("</span><wbr /><span class='hlControl'>&amp;</span><span class='hlTagName'>");
} else if (nextChar == '=') {
b.append("</span><span class='hlControl'>=</span><span class='hlAttr'>");
} else {
b.append(nextChar);
}
}
}
if (inParams) {
b.append("</span>");
}
return b.toString();
}
private RuntimeResourceDefinition getResourceType(HttpServletRequest theReq) throws ServletException {
String resourceName = StringUtils.defaultString(theReq.getParameter(PARAM_RESOURCE));
RuntimeResourceDefinition def = myCtx.getResourceDefinition(resourceName);
@ -828,6 +850,25 @@ public class Controller {
}
}
private String preProcessMessageBody(String theBody) {
if (theBody == null) {
return "";
}
String retVal = theBody.trim();
StringBuilder b = new StringBuilder();
for (int i = 0; i < retVal.length(); i++) {
char nextChar = retVal.charAt(i);
int nextCharI = nextChar;
if (nextCharI == 65533) {
continue;
}
b.append(nextChar);
}
retVal = b.toString();
return retVal;
}
private void processAndAddLastClientInvocation(GenericClient theClient, ResultType theResultType, ModelMap theModelMap, long theLatency, String outcomeDescription) {
try {
HttpRequestBase lastRequest = theClient.getLastRequest();
@ -889,11 +930,16 @@ public class Controller {
theModelMap.put("action", action);
theModelMap.put("bundle", bundle);
theModelMap.put("resultStatus", resultStatus);
theModelMap.put("requestUrl", requestUrl);
theModelMap.put("requestUrlText", formatUrl(requestUrl));
String requestBodyText = format(requestBody, ctEnum);
theModelMap.put("requestBody", requestBodyText);
String resultBodyText = format(resultBody, ctEnum);
theModelMap.put("resultBody", resultBodyText);
theModelMap.put("resultBodyIsLong", resultBodyText.length() > 1000);
theModelMap.put("requestHeaders", requestHeaders);
theModelMap.put("responseHeaders", responseHeaders);

View File

@ -43,7 +43,7 @@
</td>
<td>
<th:block th:text="${action}"/>
<a th:href="${requestUrl}" th:text="${requestUrl}"/>
<a th:href="${requestUrl}" th:utext="${requestUrlText}"/>
</td>
</tr>
<tr th:if="${requestHeaders.length} > 0">

View File

@ -19,9 +19,12 @@
<!-- Custom styles for this template -->
<link href="css/tester.css" rel="stylesheet" />
<link href="css/hapi-narrative.css" rel="stylesheet" />
<!--
<script type="text/javascript" src="js/moment.min.js"></script>
-->
<!-- Datetimepicker Component -->
<link href="css/bootstrap-datetimepicker.min.css" rel="stylesheet" />
<script src="js/bootstrap-datetimepicker.min.js"></script>

View File

@ -0,0 +1,46 @@
BODY {
font-family: sans-serif;
}
DIV.hapiHeaderText {
font-size: 1.3em;
}
/********************************************************
* The following section is used for tables of values
* with multiple columns (e.g. the table of Observations
* in a Diagnostic Report for a lab test)
********************************************************/
TABLE.hapiTableOfValues THEAD TR TD {
background: #A0A0F0;
color: #000080;
font-size: 1.2em;
font-weight: bold;
padding: 5px;
}
TABLE.hapiTableOfValues TBODY TR TD {
padding-left: 5px;
padding-right: 5px;
}
/* Even and odd row formatting */
TR.hapiTableOfValuesRowOdd TD {
background: #C0C0C0;
}
TR.hapiTableOfValuesRowEven TD {
background: #F0F0F0;
}
/********************************************************
* The following section is used for property tables. These
* tables have two columns, one for the property name, and
* one for the property value
********************************************************/
TABLE.hapiPropertyTable TBODY TR TD:FIRST-CHILD {
background: #C0C0C0;
text-align: right;
}

View File

@ -299,4 +299,5 @@ DIV.tab-pane DIV.container-fluid {
DIV.top-buffer {
margin-top: 2px;
}
}

View File

@ -68,7 +68,8 @@ function addSearchControls(theSearchParamType, theSearchParamName, theSearchPara
}
$('#search-param-rowopts-' + theContainerRowNum).append(
$('<input />', { id: 'param.' + theRowNum + '.name', type: 'hidden', value: theSearchParamName })
$('<input />', { id: 'param.' + theRowNum + '.name', type: 'hidden', value: theSearchParamName }),
$('<input />', { id: 'param.' + theRowNum + '.type', type: 'hidden', value: theSearchParamType })
);
if (theSearchParamType == 'token') {
@ -145,10 +146,11 @@ function handleSearchParamTypeChange(select, params, rowNum) {
}
$('#search-param-rowopts-' + rowNum).empty();
var searchParam = params[newVal];
/*
$('#search-param-rowopts-' + rowNum).append(
$('<input />', { name: 'param.' + rowNum + '.type', type: 'hidden', value: searchParam.type })
);
*/
addSearchControls(searchParam.type, searchParam.name, searchParam.chain, rowNum, rowNum);
select.prevVal = newVal;

File diff suppressed because one or more lines are too long

View File

@ -9,44 +9,6 @@
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/hapi-fhir-base"/>
<classpathentry kind="var" path="M2_REPO/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar" sourcepath="M2_REPO/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2-sources.jar"/>
<classpathentry kind="var" path="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar" sourcepath="M2_REPO/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0-sources.jar"/>
<classpathentry kind="var" path="M2_REPO/ca/uhn/hapi/fhir/hapi-fhir-base/1.0-SNAPSHOT/hapi-fhir-base-1.0-SNAPSHOT.jar"/>
<classpathentry kind="var" path="M2_REPO/com/google/code/gson/gson/2.2.4/gson-2.2.4.jar" sourcepath="M2_REPO/com/google/code/gson/gson/2.2.4/gson-2.2.4-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:file:/home/t3903uhn/.m2/repository/com/google/code/gson/gson/2.2.4/gson-2.2.4-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="var" path="M2_REPO/org/codehaus/woodstox/woodstox-core-asl/4.2.0/woodstox-core-asl-4.2.0.jar" sourcepath="M2_REPO/org/codehaus/woodstox/woodstox-core-asl/4.2.0/woodstox-core-asl-4.2.0-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:file:/home/t3903uhn/.m2/repository/org/codehaus/woodstox/woodstox-core-asl/4.2.0/woodstox-core-asl-4.2.0-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="var" path="M2_REPO/org/codehaus/woodstox/stax2-api/3.1.1/stax2-api-3.1.1.jar" sourcepath="M2_REPO/org/codehaus/woodstox/stax2-api/3.1.1/stax2-api-3.1.1-sources.jar"/>
<classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-lang3/3.2.1/commons-lang3-3.2.1.jar" sourcepath="M2_REPO/org/apache/commons/commons-lang3/3.2.1/commons-lang3-3.2.1-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:file:/home/t3903uhn/.m2/repository/org/apache/commons/commons-lang3/3.2.1/commons-lang3-3.2.1-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="var" path="M2_REPO/commons-codec/commons-codec/1.9/commons-codec-1.9.jar" sourcepath="M2_REPO/commons-codec/commons-codec/1.9/commons-codec-1.9-sources.jar"/>
<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.7.6/slf4j-api-1.7.6.jar" sourcepath="M2_REPO/org/slf4j/slf4j-api/1.7.6/slf4j-api-1.7.6-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:file:/home/t3903uhn/.m2/repository/org/slf4j/slf4j-api/1.7.6/slf4j-api-1.7.6-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="var" path="M2_REPO/org/apache/httpcomponents/httpclient/4.2.3/httpclient-4.2.3.jar" sourcepath="M2_REPO/org/apache/httpcomponents/httpclient/4.2.3/httpclient-4.2.3-sources.jar"/>
<classpathentry kind="var" path="M2_REPO/org/apache/httpcomponents/httpcore/4.2.2/httpcore-4.2.2.jar"/>
<classpathentry kind="var" path="M2_REPO/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" sourcepath="M2_REPO/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:file:/home/t3903uhn/.m2/repository/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.17/log4j-1.2.17.jar"/>
<classpathentry kind="var" path="M2_REPO/junit/junit/4.11/junit-4.11.jar" sourcepath="M2_REPO/junit/junit/4.11/junit-4.11-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:file:/Users/james/.m2/repository/junit/junit/4.11/junit-4.11-javadoc.jar!/"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>

View File

@ -1,4 +1,5 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -1,5 +1,13 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View File

@ -8,7 +8,6 @@
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-tinder-test</artifactId>
<packaging>jar</packaging>