Fix #150 - Don't encode null fluent client values

This commit is contained in:
jamesagnew 2016-07-14 07:18:48 -04:00
parent f6601cc347
commit ef1c81e241
5 changed files with 95 additions and 23 deletions

View File

@ -887,7 +887,9 @@ public class GenericClient extends BaseClient implements IGenericClient {
for (ICriterionInternal next : this) {
String parameterName = next.getParameterName();
String parameterValue = next.getParameterValue(myContext);
addParam(theParams, parameterName, parameterValue);
if (isNotBlank(parameterValue)) {
addParam(theParams, parameterName, parameterValue);
}
}
}

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.gclient;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/*
* #%L
* HAPI FHIR - Core Library
@ -81,10 +83,12 @@ public class DateClientParam extends BaseClientParam implements IParam {
@Override
public String getParameterValue(FhirContext theContext) {
StringBuilder b = new StringBuilder();
if (myPrefix != null && myPrefix != ParamPrefixEnum.EQUAL) {
b.append(myPrefix.getValueForContext(theContext));
if (isNotBlank(myValue)) {
if (myPrefix != null && myPrefix != ParamPrefixEnum.EQUAL) {
b.append(myPrefix.getValueForContext(theContext));
}
b.append(myValue);
}
b.append(myValue);
return b.toString();
}

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.gclient;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import ca.uhn.fhir.rest.param.ParameterUtil;
@ -48,14 +50,16 @@ class QuantityCriterion implements ICriterion<QuantityClientParam>, ICriterionIn
@Override
public String getParameterValue(FhirContext theContext) {
StringBuilder b = new StringBuilder();
if (myPrefix != null) {
b.append(ParameterUtil.escapeWithDefault(myPrefix.getValueForContext(theContext)));
if (isNotBlank(myValue) || isNotBlank(mySystem) || isNotBlank(myUnits)) {
if (myPrefix != null) {
b.append(ParameterUtil.escapeWithDefault(myPrefix.getValueForContext(theContext)));
}
b.append(ParameterUtil.escapeWithDefault(myValue));
b.append('|');
b.append(ParameterUtil.escapeWithDefault(mySystem));
b.append('|');
b.append(ParameterUtil.escapeWithDefault(myUnits));
}
b.append(ParameterUtil.escapeWithDefault(myValue));
b.append('|');
b.append(ParameterUtil.escapeWithDefault(mySystem));
b.append('|');
b.append(ParameterUtil.escapeWithDefault(myUnits));
return b.toString();
}

View File

@ -39,6 +39,7 @@ import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
import org.hl7.fhir.dstu3.model.Conformance;
import org.hl7.fhir.dstu3.model.Device;
import org.hl7.fhir.dstu3.model.Encounter;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.OperationOutcome;
import org.hl7.fhir.dstu3.model.Parameters;
@ -155,6 +156,58 @@ public class GenericClientDstu3Test {
Patient outputPt = (Patient) ourCtx.newJsonParser().parseResource(new String(output.getContent(), "UTF-8"));
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">A PATIENT</div>", outputPt.getText().getDivAsString());
}
/**
* See #150
*/
@Test
public void testNullAndEmptyParamValuesAreIgnored() throws Exception {
ArgumentCaptor<HttpUriRequest> capt = prepareClientForSearchResponse();
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
//@formatter:off
client
.search()
.forResource(Patient.class)
.where(Patient.FAMILY.matches().value((String)null))
.and(Patient.BIRTHDATE.exactly().day((Date)null))
.and(Patient.GENDER.exactly().code((String)null))
.and(Patient.ORGANIZATION.hasId((String)null))
.returnBundle(Bundle.class)
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString());
idx++;
//@formatter:off
client
.search()
.forResource(Encounter.class)
.where(Encounter.LENGTH.exactly().number(null))
.returnBundle(Bundle.class)
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Encounter", capt.getAllValues().get(idx).getURI().toString());
idx++;
//@formatter:off
client
.search()
.forResource(Observation.class)
.where(Observation.VALUE_QUANTITY.exactly().number(null).andUnits(null))
.returnBundle(Bundle.class)
.execute();
//@formatter:on
assertEquals("http://example.com/fhir/Observation", capt.getAllValues().get(idx).getURI().toString());
idx++;
}
@Test
@ -1099,18 +1152,7 @@ public class GenericClientDstu3Test {
@Test
public void testSearchWithMultipleTokens() throws Exception {
final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
ArgumentCaptor<HttpUriRequest> capt = prepareClientForSearchResponse();
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
int idx = 0;
@ -1130,6 +1172,22 @@ public class GenericClientDstu3Test {
}
private ArgumentCaptor<HttpUriRequest> prepareClientForSearchResponse() throws IOException, ClientProtocolException {
final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
return capt;
}
/**
* See #371
*/

View File

@ -38,6 +38,10 @@
DSTU2 QuestionnaireResponse validator failed with an exception if the
QuestionnaireResponse contained certain groups with no content
</action>
<action type="add" issue="150">
Fluent client should ignore parameter values which are null instead of including
them as <![CDATA[<code>?foo=null</code>]]>
</action>
</release>
<release version="1.6" date="2016-07-07">
<action type="fix">