Fix #33 - Server was incorrectly returning contained resources as

top-level resources
This commit is contained in:
James Agnew 2014-10-15 16:46:28 -04:00
parent b22bcaec32
commit 287162af91
7 changed files with 105 additions and 7 deletions

View File

@ -104,6 +104,11 @@
Documentation on contained resources contained a typo and did not actually produce contained resources. Thanks Documentation on contained resources contained a typo and did not actually produce contained resources. Thanks
to David Hay of Orion Health for reporting! to David Hay of Orion Health for reporting!
</action> </action>
<action type="fix" issue="33">
Server was incorrectly including contained resources being returned as both contained resources, and as
top-level resources in the returned bundle for search operations.
Thanks to Bill de Beaubien for reporting!
</action>
</release> </release>
<release version="0.6" date="2014-Sep-08" description="This release brings a number of new features and bug fixes!"> <release version="0.6" date="2014-Sep-08" description="This release brings a number of new features and bug fixes!">
<!-- <!--

View File

@ -411,6 +411,8 @@ public class JsonParser extends BaseParser implements IParser {
theEventWriter.writeStartArray(childName); theEventWriter.writeStartArray(childName);
inArray = true; inArray = true;
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theIsSubElementWithinResource); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theIsSubElementWithinResource);
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theIsSubElementWithinResource) {
// suppress narratives from contained resources
} else { } else {
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theIsSubElementWithinResource); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theIsSubElementWithinResource);
} }

View File

@ -549,6 +549,8 @@ public class XmlParser extends BaseParser implements IParser {
theEventWriter.writeAttribute("url", extensionUrl); theEventWriter.writeAttribute("url", extensionUrl);
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, null, theIncludedResource);
theEventWriter.writeEndElement(); theEventWriter.writeEndElement();
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theIncludedResource) {
// suppress narratives from contained resources
} else { } else {
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childName, childDef, extensionUrl, theIncludedResource);
} }

View File

@ -1035,6 +1035,13 @@ public class RestfulServer extends HttpServlet {
Set<IdDt> addedResourceIds = new HashSet<IdDt>(); Set<IdDt> addedResourceIds = new HashSet<IdDt>();
for (IResource next : theResult) { for (IResource next : theResult) {
Set<String> containedIds = new HashSet<String>();
for (IResource nextContained : next.getContained().getContainedResources()) {
if (nextContained.getId().isEmpty()==false) {
containedIds.add(nextContained.getId().getValue());
}
}
if (theContext.getNarrativeGenerator() != null) { if (theContext.getNarrativeGenerator() != null) {
String title = theContext.getNarrativeGenerator().generateTitle(next); String title = theContext.getNarrativeGenerator().generateTitle(next);
ourLog.trace("Narrative generator created title: {}", title); ourLog.trace("Narrative generator created title: {}", title);
@ -1053,6 +1060,11 @@ public class RestfulServer extends HttpServlet {
IResource nextRes = nextRef.getResource(); IResource nextRes = nextRef.getResource();
if (nextRes != null) { if (nextRes != null) {
if (nextRes.getId().hasIdPart()) { if (nextRes.getId().hasIdPart()) {
if (containedIds.contains(nextRes.getId().getValue())) {
// Don't add contained IDs as top level resources
continue;
}
IdDt id = nextRes.getId().toVersionless(); IdDt id = nextRes.getId().toVersionless();
if (id.hasResourceType() == false) { if (id.hasResourceType() == false) {
String resName = theContext.getResourceDefinition(nextRes).getName(); String resName = theContext.getResourceDefinition(nextRes).getName();

View File

@ -491,6 +491,29 @@ public class JsonParserTest {
assertThat(encoded, containsString("reference\":\"#1\"")); assertThat(encoded, containsString("reference\":\"#1\""));
} }
@Test
public void testEncodeContainedWithNarrativeIsSuppresed() {
IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
// Create an organization, note that the organization does not have an ID
Organization org = new Organization();
org.getName().setValue("Contained Test Organization");
org.getText().setDiv("<div>FOOBAR</div>");
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier("urn:mrns", "253345");
patient.getText().setDiv("<div>BARFOO</div>");
patient.getManagingOrganization().setResource(org);
String encoded = parser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, not(containsString("FOOBAR")));
assertThat(encoded, (containsString("BARFOO")));
}
@Test @Test
public void testEncodeContained() { public void testEncodeContained() {
IParser xmlParser = ourCtx.newJsonParser().setPrettyPrint(true); IParser xmlParser = ourCtx.newJsonParser().setPrettyPrint(true);
@ -603,7 +626,7 @@ public class JsonParserTest {
DiagnosticReport rpt = new DiagnosticReport(); DiagnosticReport rpt = new DiagnosticReport();
Specimen spm = new Specimen(); Specimen spm = new Specimen();
spm.getText().setDiv("AAA"); rpt.getText().setDiv("AAA");
rpt.addSpecimen().setResource(spm); rpt.addSpecimen().setResource(spm);
IParser p = new FhirContext(DiagnosticReport.class).newJsonParser().setPrettyPrint(true); IParser p = new FhirContext(DiagnosticReport.class).newJsonParser().setPrettyPrint(true);

View File

@ -1,9 +1,18 @@
package ca.uhn.fhir.parser; package ca.uhn.fhir.parser;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*; import static org.hamcrest.Matchers.not;
import static org.mockito.Matchers.*; import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.mockito.Mockito.*; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@ -12,7 +21,6 @@ import java.io.StringReader;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -115,6 +123,29 @@ public class XmlParserTest {
} }
@Test
public void testEncodeContainedWithNarrativeIsSuppresed() {
IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
// Create an organization, note that the organization does not have an ID
Organization org = new Organization();
org.getName().setValue("Contained Test Organization");
org.getText().setDiv("<div>FOOBAR</div>");
// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier("urn:mrns", "253345");
patient.getText().setDiv("<div>BARFOO</div>");
patient.getManagingOrganization().setResource(org);
String encoded = parser.encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded, not(containsString("FOOBAR")));
assertThat(encoded, (containsString("BARFOO")));
}
@Test @Test
public void testEncodeContained() { public void testEncodeContained() {
@ -388,7 +419,8 @@ public class XmlParserTest {
DiagnosticReport rpt = new DiagnosticReport(); DiagnosticReport rpt = new DiagnosticReport();
Specimen spm = new Specimen(); Specimen spm = new Specimen();
spm.getText().setDiv("AAA"); spm.addIdentifier("urn", "123");
rpt.getText().setDiv("AAA");
rpt.addSpecimen().setResource(spm); rpt.addSpecimen().setResource(spm);
IParser p = ourCtx.newXmlParser().setPrettyPrint(true); IParser p = ourCtx.newXmlParser().setPrettyPrint(true);

View File

@ -174,6 +174,28 @@ public class CompleteResourceProviderTest {
assertThat(actual.getText().getDiv().getValueAsString(), containsString("<td>Identifier</td><td>testSearchByResourceChain01</td>")); assertThat(actual.getText().getDiv().getValueAsString(), containsString("<td>Identifier</td><td>testSearchByResourceChain01</td>"));
} }
@Test
public void testSaveAndRetrieveWithContained() {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testSaveAndRetrieveWithContained01");
Organization o1 = new Organization();
o1.addIdentifier().setSystem("urn:system").setValue("testSaveAndRetrieveWithContained02");
p1.getManagingOrganization().setResource(o1);
IdDt newId = ourClient.create().resource(p1).execute().getId();
Patient actual = ourClient.read(Patient.class, newId);
assertEquals(1, actual.getContained().getContainedResources().size());
assertThat(actual.getText().getDiv().getValueAsString(), containsString("<td>Identifier</td><td>testSaveAndRetrieveWithContained01</td>"));
Bundle b = ourClient.search().forResource("Patient").where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system","testSaveAndRetrieveWithContained01")).execute();
assertEquals(1, b.size());
}
@Test @Test
public void testSearchByIdentifier() { public void testSearchByIdentifier() {
deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSearchByIdentifier01"); deleteToken("Patient", Patient.SP_IDENTIFIER, "urn:system", "testSearchByIdentifier01");