mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-25 01:18:37 +00:00
Correctly support _summary=search option
This commit is contained in:
parent
153c3ac5aa
commit
81fa46820a
@ -145,9 +145,6 @@ public abstract class BaseParser implements IParser {
|
||||
/*
|
||||
* There are lots of reasons we might skip encoding a particular child
|
||||
*/
|
||||
// if (myNext.getDef().getElementName().equals("extension") || myNext.getDef().getElementName().equals("modifierExtension")) {
|
||||
// myNext = null;
|
||||
// } else
|
||||
if (myNext.getDef().getElementName().equals("id")) {
|
||||
myNext = null;
|
||||
} else if (!myNext.shouldBeEncoded()) {
|
||||
@ -981,6 +978,12 @@ public abstract class BaseParser implements IParser {
|
||||
}
|
||||
|
||||
if (myDef != null) {
|
||||
if (myDef.getMin() > 0) {
|
||||
if (theElements.contains("*.(mandatory)")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
thePathBuilder.append('.');
|
||||
thePathBuilder.append(myDef.getElementName());
|
||||
return theElements.contains(thePathBuilder.toString());
|
||||
@ -1016,6 +1019,12 @@ public abstract class BaseParser implements IParser {
|
||||
retVal = !checkIfParentShouldNotBeEncodedAndBuildPath(new StringBuilder(), true);
|
||||
}
|
||||
}
|
||||
// if (retVal == false && myEncodeElements.contains("*.(mandatory)")) {
|
||||
// if (myDef.getMin() > 0) {
|
||||
// retVal = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
@ -257,6 +257,7 @@ public interface IParser {
|
||||
* <li><b>Patient.name.family</b> - Encode only the patient's family name</li>
|
||||
* <li><b>*.text</b> - Encode the text element on any resource (only the very first position may contain a
|
||||
* wildcard)</li>
|
||||
* <li><b>*.(mandatory)</b> - This is a special case which causes any mandatory fields (min > 0) to be encoded</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param theEncodeElements
|
||||
|
@ -71,7 +71,7 @@ public class RestfulServerUtils {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServerUtils.class);
|
||||
|
||||
private static final HashSet<String> TEXT_ENCODE_ELEMENTS = new HashSet<String>(Arrays.asList("Bundle", "*.text"));
|
||||
private static final HashSet<String> TEXT_ENCODE_ELEMENTS = new HashSet<String>(Arrays.asList("Bundle", "*.text", "*.(mandatory)"));
|
||||
|
||||
public static void configureResponseParser(RequestDetails theRequestDetails, IParser parser) {
|
||||
// Pretty print
|
||||
|
@ -31,8 +31,8 @@ public class FhirResourceDaoBundleDstu2 extends FhirResourceDaoDstu2<Bundle> {
|
||||
protected void preProcessResourceForStorage(Bundle theResource) {
|
||||
super.preProcessResourceForStorage(theResource);
|
||||
|
||||
if (theResource.getTypeElement().getValueAsEnum() != BundleTypeEnum.DOCUMENT) {
|
||||
String message = "Unable to store a Bundle resource on this server with a Bundle.type value other than '" + BundleTypeEnum.DOCUMENT.getCode() + "' - Value was: " + (theResource.getTypeElement().getValueAsEnum() != null ? theResource.getTypeElement().getValueAsEnum().getCode() : "(missing)");
|
||||
if (theResource.getTypeElement().getValueAsEnum() != BundleTypeEnum.DOCUMENT && theResource.getTypeElement().getValueAsEnum() != BundleTypeEnum.COLLECTION) {
|
||||
String message = "Unable to store a Bundle resource on this server with a Bundle.type of: " + (theResource.getTypeElement().getValueAsEnum() != null ? theResource.getTypeElement().getValueAsEnum().getCode() : "(missing)");
|
||||
throw new UnprocessableEntityException(message);
|
||||
}
|
||||
|
||||
|
@ -32,8 +32,8 @@ public class FhirResourceDaoBundleDstu3 extends FhirResourceDaoDstu3<Bundle> {
|
||||
protected void preProcessResourceForStorage(Bundle theResource) {
|
||||
super.preProcessResourceForStorage(theResource);
|
||||
|
||||
if (theResource.getType() != BundleType.DOCUMENT) {
|
||||
String message = "Unable to store a Bundle resource on this server with a Bundle.type value other than '" + BundleType.DOCUMENT.toCode() + "' - Value was: " + (theResource.getType() != null ? theResource.getType().toCode() : "(missing)");
|
||||
if (theResource.getType() != BundleType.DOCUMENT && theResource.getType() != BundleType.COLLECTION) {
|
||||
String message = "Unable to store a Bundle resource on this server with a Bundle.type value of: " + (theResource.getType() != null ? theResource.getType().toCode() : "(missing)");
|
||||
throw new UnprocessableEntityException(message);
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,9 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
|
||||
@Qualifier("myConceptMapDaoDstu2")
|
||||
protected IFhirResourceDao<ConceptMap> myConceptMapDao;
|
||||
@Autowired
|
||||
@Qualifier("myBundleDaoDstu2")
|
||||
protected IFhirResourceDao<Bundle> myBundleDao;
|
||||
@Autowired
|
||||
@Qualifier("myMedicationDaoDstu2")
|
||||
protected IFhirResourceDao<Medication> myMedicationDao;
|
||||
@Autowired
|
||||
|
@ -34,6 +34,7 @@ import java.util.Set;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
@ -73,6 +74,7 @@ import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.IssueTypeEnum;
|
||||
@ -106,7 +108,6 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -129,6 +130,49 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateBundleAllowsDocumentAndCollection() {
|
||||
String methodName = "testCreateBundleAllowsDocumentAndCollection";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IIdType pid = myPatientDao.create(p, mySrd).getId();
|
||||
p.setId(pid);
|
||||
ourLog.info("Created patient, got it: {}", pid);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType((BundleTypeEnum)null);
|
||||
bundle.addEntry().setResource(p).setFullUrl(pid.toUnqualifiedVersionless().getValue());
|
||||
try {
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Unable to store a Bundle resource on this server with a Bundle.type of: (missing)", e.getMessage());
|
||||
}
|
||||
|
||||
bundle = new Bundle();
|
||||
bundle.setType(BundleTypeEnum.BATCH_RESPONSE);
|
||||
bundle.addEntry().setResource(p).setFullUrl(pid.toUnqualifiedVersionless().getValue());
|
||||
try {
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Unable to store a Bundle resource on this server with a Bundle.type of: batch-response", e.getMessage());
|
||||
}
|
||||
|
||||
bundle = new Bundle();
|
||||
bundle.setType(BundleTypeEnum.COLLECTION);
|
||||
bundle.addEntry().setResource(p).setFullUrl(pid.toUnqualifiedVersionless().getValue());
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
|
||||
bundle = new Bundle();
|
||||
bundle.setType(BundleTypeEnum.DOCUMENT);
|
||||
bundle.addEntry().setResource(p).setFullUrl(pid.toUnqualifiedVersionless().getValue());
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This gets called from assertGone too! Careful about exceptions...
|
||||
*/
|
||||
|
@ -93,6 +93,9 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
||||
@Qualifier("myCodeSystemDaoDstu3")
|
||||
protected IFhirResourceDao<CodeSystem> myCodeSystemDao;
|
||||
@Autowired
|
||||
@Qualifier("myBundleDaoDstu3")
|
||||
protected IFhirResourceDao<Bundle> myBundleDao;
|
||||
@Autowired
|
||||
@Qualifier("myConceptMapDaoDstu3")
|
||||
protected IFhirResourceDao<ConceptMap> myConceptMapDao;
|
||||
@Autowired
|
||||
|
@ -36,6 +36,7 @@ import org.hamcrest.Matchers;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hl7.fhir.dstu3.model.BaseResource;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
||||
import org.hl7.fhir.dstu3.model.CodeType;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
@ -532,6 +533,48 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateBundleAllowsDocumentAndCollection() {
|
||||
String methodName = "testCreateBundleAllowsDocumentAndCollection";
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setSystem("urn:system").setValue(methodName);
|
||||
IIdType pid = myPatientDao.create(p, mySrd).getId();
|
||||
p.setId(pid);
|
||||
ourLog.info("Created patient, got it: {}", pid);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(null);
|
||||
bundle.addEntry().setResource(p).setFullUrl(pid.toUnqualifiedVersionless().getValue());
|
||||
try {
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Unable to store a Bundle resource on this server with a Bundle.type value of: (missing)", e.getMessage());
|
||||
}
|
||||
|
||||
bundle = new Bundle();
|
||||
bundle.setType(BundleType.SEARCHSET);
|
||||
bundle.addEntry().setResource(p).setFullUrl(pid.toUnqualifiedVersionless().getValue());
|
||||
try {
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertEquals("Unable to store a Bundle resource on this server with a Bundle.type value of: searchset", e.getMessage());
|
||||
}
|
||||
|
||||
bundle = new Bundle();
|
||||
bundle.setType(BundleType.COLLECTION);
|
||||
bundle.addEntry().setResource(p).setFullUrl(pid.toUnqualifiedVersionless().getValue());
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
|
||||
bundle = new Bundle();
|
||||
bundle.setType(BundleType.DOCUMENT);
|
||||
bundle.addEntry().setResource(p).setFullUrl(pid.toUnqualifiedVersionless().getValue());
|
||||
myBundleDao.create(bundle, mySrd);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWithIfNoneExistBasic() {
|
||||
String methodName = "testCreateWithIfNoneExistBasic";
|
||||
|
@ -188,7 +188,9 @@
|
||||
<baseResourceName>deviceusestatement</baseResourceName>
|
||||
<baseResourceName>diagnosticorder</baseResourceName>
|
||||
<baseResourceName>diagnosticreport</baseResourceName>
|
||||
<!-- This is not a real resource
|
||||
<baseResourceName>documentation</baseResourceName>
|
||||
-->
|
||||
<baseResourceName>documentmanifest</baseResourceName>
|
||||
<baseResourceName>documentreference</baseResourceName>
|
||||
<baseResourceName>eligibilityrequest</baseResourceName>
|
||||
|
@ -1475,6 +1475,30 @@ public class XmlParserDstu2Test {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeWithEncodeElementsMandatory() throws Exception {
|
||||
MedicationOrder mo = new MedicationOrder();
|
||||
mo.getText().setDiv("<div>DIV</div>");
|
||||
mo.setNote("NOTE");
|
||||
mo.setMedication(new ResourceReferenceDt("Medication/123"));
|
||||
|
||||
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = new ca.uhn.fhir.model.dstu2.resource.Bundle();
|
||||
bundle.setTotal(100);
|
||||
bundle.addEntry().setResource(mo);
|
||||
|
||||
{
|
||||
IParser p = ourCtx.newXmlParser();
|
||||
p.setEncodeElements(new HashSet<String>(Arrays.asList("Bundle.entry", "*.text", "*.(mandatory)")));
|
||||
p.setPrettyPrint(true);
|
||||
String out = p.encodeResourceToString(bundle);
|
||||
ourLog.info(out);
|
||||
assertThat(out, (containsString("DIV")));
|
||||
assertThat(out, (containsString("Medication/123")));
|
||||
assertThat(out, not(containsString("NOTE")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeWithEncodeElements() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.rest.server;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -15,6 +16,7 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
@ -22,6 +24,8 @@ import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.MaritalStatusCodesEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
@ -79,11 +83,27 @@ public class SummaryParamTest {
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertEquals(Constants.CT_HTML_WITH_UTF8.replace(" ", "").toLowerCase(), status.getEntity().getContentType().getValue().replace(" ", "").replace("UTF", "utf"));
|
||||
assertThat(responseContent, not(containsString("<Bundle")));
|
||||
assertThat(responseContent, not(containsString("<Patien")));
|
||||
assertThat(responseContent, not(containsString("<Medic")));
|
||||
assertEquals("<div>THE DIV</div>", responseContent);
|
||||
assertThat(responseContent, not(containsString("efer")));
|
||||
assertEquals(SummaryEnum.TEXT, ourLastSummary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadSummaryTextWithMandatory() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/MedicationOrder/1?_summary=" + SummaryEnum.TEXT.getCode());
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertEquals(Constants.CT_HTML_WITH_UTF8.replace(" ", "").toLowerCase(), status.getEntity().getContentType().getValue().replace(" ", "").replace("UTF", "utf"));
|
||||
assertThat(responseContent, not(containsString("<Bundle")));
|
||||
assertThat(responseContent, not(containsString("<Patien")));
|
||||
assertEquals("<div>TEXT</div>", responseContent);
|
||||
assertThat(responseContent, not(containsString("family")));
|
||||
assertThat(responseContent, not(containsString("maritalStatus")));
|
||||
assertEquals(SummaryEnum.TEXT, ourLastSummary);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -170,6 +190,22 @@ public class SummaryParamTest {
|
||||
assertEquals(SummaryEnum.TEXT, ourLastSummary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchSummaryTextWithMandatory() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/MedicationOrder?_summary=" + SummaryEnum.TEXT.getCode() + "&_pretty=true");
|
||||
HttpResponse status = ourClient.execute(httpGet);
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||
ourLog.info(responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(responseContent, (containsString("<total value=\"1\"/>")));
|
||||
assertThat(responseContent, (containsString("entry")));
|
||||
assertThat(responseContent, (containsString(">TEXT<")));
|
||||
assertThat(responseContent, (containsString("Medication/123")));
|
||||
assertThat(responseContent, not(containsStringIgnoringCase("note")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchSummaryTextMulti() throws Exception {
|
||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_query=multi&_summary=" + SummaryEnum.TEXT.getCode());
|
||||
@ -226,12 +262,10 @@ public class SummaryParamTest {
|
||||
ourPort = PortUtil.findFreePort();
|
||||
ourServer = new Server(ourPort);
|
||||
|
||||
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
RestfulServer servlet = new RestfulServer(ourCtx);
|
||||
|
||||
servlet.setResourceProviders(patientProvider);
|
||||
servlet.setResourceProviders(new DummyPatientResourceProvider(), new DummyMedicationOrderProvider());
|
||||
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
@ -244,6 +278,30 @@ public class SummaryParamTest {
|
||||
|
||||
}
|
||||
|
||||
public static class DummyMedicationOrderProvider implements IResourceProvider{
|
||||
|
||||
@Override
|
||||
public Class<? extends IBaseResource> getResourceType() {
|
||||
return MedicationOrder.class;
|
||||
}
|
||||
|
||||
@Read
|
||||
public MedicationOrder read(@IdParam IdDt theId) {
|
||||
MedicationOrder retVal = new MedicationOrder();
|
||||
retVal.getText().setDiv("<div>TEXT</div>");
|
||||
retVal.getNoteElement().setValue("NOTE");
|
||||
retVal.setMedication(new ResourceReferenceDt("Medication/123"));
|
||||
retVal.setId(theId);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Search
|
||||
public List<MedicationOrder> read() {
|
||||
return Arrays.asList(read(new IdDt("999")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
|
@ -426,6 +426,16 @@
|
||||
Improve CLI error message if the tool can't bind to the requested port. Thanks
|
||||
to Claude Nanjo for the suggestion!
|
||||
</action>
|
||||
<action type="fix">
|
||||
Server param of <![CDATA[<code>_summary=text</code>]]> did not
|
||||
include mandatory elements in return as well as
|
||||
the text element, even though the FHIR specification
|
||||
required it.
|
||||
</action>
|
||||
<action type="fix">
|
||||
Remove invalid resource type "Documentation" from DSTU2
|
||||
structures.
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.4" date="2016-02-04">
|
||||
<action type="add">
|
||||
|
Loading…
x
Reference in New Issue
Block a user