diff --git a/.classpath b/.classpath index d617da7776f..8778ddd58a3 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,5 @@ - diff --git a/hapi-fhir-structures-hl7org-dev/.classpath b/hapi-fhir-structures-hl7org-dev/.classpath new file mode 100644 index 00000000000..f8ce0d30f1d --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/.classpath @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hapi-fhir-structures-hl7org-dev/.project b/hapi-fhir-structures-hl7org-dev/.project new file mode 100644 index 00000000000..5ed54fe4349 --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/.project @@ -0,0 +1,23 @@ + + + hapi-fhir-structures-hl7org-dev + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/hapi-fhir-structures-hl7org-dev/pom.xml b/hapi-fhir-structures-hl7org-dev/pom.xml new file mode 100644 index 00000000000..c9291229ed9 --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/pom.xml @@ -0,0 +1,198 @@ + + 4.0.0 + + + ca.uhn.hapi.fhir + hapi-deployable-pom + 0.8-SNAPSHOT + ../hapi-deployable-pom/pom.xml + + + hapi-fhir-structures-hl7org-dev + jar + + HAPI FHIR Structures - HL7.org DEV (FHIR Latest) + + + + ca.uhn.hapi.fhir + hapi-fhir-base + 0.8-SNAPSHOT + + + + javax.servlet + javax.servlet-api + ${servlet_api_version} + provided + + + + + junit + junit + ${junit_version} + test + + + xmlunit + xmlunit + 1.5 + test + + + org.eclipse.jetty + jetty-servlets + ${jetty_version} + test + + + org.eclipse.jetty + jetty-servlet + ${jetty_version} + test + + + org.eclipse.jetty + jetty-server + ${jetty_version} + test + + + org.eclipse.jetty + jetty-servlet + ${jetty_version} + test + + + org.eclipse.jetty + jetty-util + ${jetty_version} + test + + + org.eclipse.jetty + jetty-webapp + ${jetty_version} + test + + + org.eclipse.jetty + jetty-http + ${jetty_version} + test + + + ch.qos.logback + logback-classic + ${logback_version} + true + test + + + org.ebaysf.web + cors-filter + ${ebay_cors_filter_version} + test + + + org.thymeleaf + thymeleaf + ${thymeleaf-version} + test + + + com.phloc + phloc-schematron + ${phloc_schematron_version} + test + + + com.phloc + phloc-commons + ${phloc_commons_version} + test + + + + + + org.mockito + mockito-all + 1.9.5 + test + + + net.sf.json-lib + json-lib + 2.4 + jdk15 + test + + + commons-logging + commons-logging + + + + + net.sf.json-lib + json-lib + 2.4 + jdk15-sources + test + + + directory-naming + naming-java + 0.8 + test + + + commons-logging + commons-logging + + + + + org.hamcrest + hamcrest-all + ${hamcrest_version} + test + + + com.google.guava + guava + ${guava_version} + test + + + + + + + + + + + diff --git a/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/ContainedResourceEncodingTest.java b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/ContainedResourceEncodingTest.java new file mode 100644 index 00000000000..ca8c2cb2ce8 --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/ContainedResourceEncodingTest.java @@ -0,0 +1,246 @@ +package ca.uhn.fhir.parser; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.Bundle; +import ca.uhn.fhir.model.api.IResource; +import ca.uhn.fhir.model.dstu.composite.CodeableConceptDt; +import ca.uhn.fhir.model.dstu.composite.CodingDt; +import ca.uhn.fhir.model.dstu.composite.HumanNameDt; +import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; +import ca.uhn.fhir.model.dstu.resource.Composition; +import ca.uhn.fhir.model.dstu.resource.Composition.Section; +import ca.uhn.fhir.model.dstu.resource.Condition; +import ca.uhn.fhir.model.dstu.resource.DiagnosticReport; +import ca.uhn.fhir.model.dstu.resource.Observation; +import ca.uhn.fhir.model.dstu.resource.Patient; +import ca.uhn.fhir.model.dstu.resource.Practitioner; +import ca.uhn.fhir.model.dstu.valueset.AdministrativeGenderCodesEnum; +import ca.uhn.fhir.model.dstu.valueset.ConditionStatusEnum; +import ca.uhn.fhir.model.dstu.valueset.NameUseEnum; +import ca.uhn.fhir.model.dstu.valueset.PractitionerRoleEnum; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.rest.server.RestfulServer; + +/** + * Initially contributed by Alexander Kley for bug #29 + */ +public class ContainedResourceEncodingTest { + + private static Logger logger = LoggerFactory.getLogger(ContainedResourceEncodingTest.class); + + private FhirContext ctx; + + private Composition comp; + + private Practitioner author; + + private Patient patient; + + private final String patFamName1 = "FirstFamilyName"; + + private final String patGivName1 = "FirstGivenName"; + + @Before + public void initTest() { + logger.info("[initTest]"); + + initPatient(); + initAuthor(); + initComposition(); + this.ctx = new FhirContext(); + + } + + private void initComposition() { + // new ConditionList + + final Condition c = new Condition(); + c.setId(UUID.randomUUID().toString()); + c.setNotes("This is a note"); + c.setSubject(new ResourceReferenceDt(this.patient)); + c.setCode(new CodeableConceptDt("mySystem", "theCode")); + c.setStatus(ConditionStatusEnum.CONFIRMED); + + // new General Note Section + final Section generalNoteSection = new Section(); + generalNoteSection.setElementSpecificId("Note"); + generalNoteSection.setTitle("Note"); + generalNoteSection.setContent(new ResourceReferenceDt(c)); + + // new SectionList + final List
sectionList = new ArrayList
(); + sectionList.add(generalNoteSection); + + // fill composition + this.comp = new Composition(); + this.comp.addAuthor().setResource(this.author); + this.comp.setSubject(new ResourceReferenceDt(this.patient)); + this.comp.setSection(sectionList); + } + + private void initPatient() { + this.patient = new Patient(); + this.patient.setId(new IdDt(UUID.randomUUID().toString())); + this.patient.addIdentifier().setSystem("http://example.com/fictitious-mrns").setValue("MRN001"); + this.patient.setGender(AdministrativeGenderCodesEnum.M); + this.patient.addName().setUse(NameUseEnum.OFFICIAL).addFamily(this.patFamName1).addGiven(this.patGivName1); + + } + + private void initAuthor() { + this.author = new Practitioner(); + this.author.setId(new IdDt(UUID.randomUUID().toString())); + this.author.addIdentifier().setSystem("DoctorID").setValue("4711"); + this.author.addRole(PractitionerRoleEnum.DOCTOR); + this.author.setName(new HumanNameDt().addFamily("Mueller").addGiven("Klaus").addPrefix("Prof. Dr.")); + + } + + @Test + public void testPatient() { + logger.debug("[xmlEncoding] encode resource to xml."); + + /** + * This works fine, although patient instance is modifing from encoder + */ + final String expectedPatientXml = this.ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(this.patient); + logger.debug("[xmlEncoding] first encoding: {}", expectedPatientXml); + final String actualPatientXml = this.ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(this.patient); + // second encoding - xml is corrupt - i.e.: patient content 4 times! should be the same as after first encoding! + logger.debug("[xmlEncoding] second encoding: {}", actualPatientXml); + + Assert.assertEquals(expectedPatientXml.length(), actualPatientXml.length()); + Assert.assertArrayEquals(expectedPatientXml.getBytes(), actualPatientXml.getBytes()); + + } + + @Test + public void testComposition() { + + IParser parser = this.ctx.newXmlParser().setPrettyPrint(true); + + assertEquals(0, this.comp.getContained().getContainedResources().size()); + + /** + * This doesn't works, secund encoding creates corrupt xml + */ + final String expectedCompXml = parser.encodeResourceToString(this.comp); + logger.debug("[xmlEncoding] first encoding: {}", expectedCompXml); + + assertEquals(0, this.comp.getContained().getContainedResources().size()); + + final String actualCompXml = parser.encodeResourceToString(this.comp); + + assertEquals(0, this.comp.getContained().getContainedResources().size()); + + // second encoding - xml could not be parsed back to compositon - i.e.: patient content 4 times! should be the same + // as after first encoding! + logger.debug("[xmlEncoding] second encoding: {}", actualCompXml); + + final String thirdCompXml = parser.encodeResourceToString(this.comp); + + assertEquals(0, this.comp.getContained().getContainedResources().size()); + + // third encoding - xml could not be parsed back to compositon i.e.: patient content 4 times! should be the same as + // afterfirst encoding! + logger.debug("[xmlEncoding] third encoding: {}", thirdCompXml); + + Assert.assertEquals(expectedCompXml.length(), actualCompXml.length()); + Assert.assertArrayEquals(expectedCompXml.getBytes(), actualCompXml.getBytes()); + + } + + + @Test + public void testBundleWithContained() { + + DiagnosticReport dr = new DiagnosticReport(); + dr.setId(new IdDt("DiagnosticReport","123")); + + Observation observation = new Observation(); + + CodeableConceptDt obsName = new CodeableConceptDt(); + obsName.setText("name"); + observation.setName(obsName); + + ResourceReferenceDt result = dr.addResult(); + result.setResource(observation); + + ArrayList performers = new ArrayList(); + ResourceReferenceDt performer = new ResourceReferenceDt(); + + Practitioner p = new Practitioner(); + p.setId(new IdDt(UUID.randomUUID().toString())); + p.addIdentifier().setSystem("DoctorID").setValue("4711"); + p.addRole(PractitionerRoleEnum.DOCTOR); + p.setName(new HumanNameDt().addFamily("Mueller").addGiven("Klaus").addPrefix("Prof. Dr.")); + + performer.setResource(p); + performers.add(performer); + observation.setPerformer(performers); + + + List list = new ArrayList(); + list.add(dr); + Bundle bundle = RestfulServer.createBundleFromResourceList(new FhirContext(), null, list, null, null, 0); + + IParser parser = this.ctx.newXmlParser().setPrettyPrint(true); + String xml = parser.encodeBundleToString(bundle); + Assert.assertTrue(xml.contains("Mueller")); + + } + + @Test + public void testBundleWithContainedWithNoIdDt() { + + DiagnosticReport dr = new DiagnosticReport(); + dr.setId(new IdDt("DiagnosticReport","123")); + + Observation observation = new Observation(); + + CodeableConceptDt obsName = new CodeableConceptDt(); + obsName.setText("name"); + observation.setName(obsName); + + ResourceReferenceDt result = dr.addResult(); + result.setResource(observation); + + ArrayList performers = new ArrayList(); + ResourceReferenceDt performer = new ResourceReferenceDt(); + + Practitioner p = new Practitioner(); + // no idDt on practitioner p + p.addIdentifier().setSystem("DoctorID").setValue("4711"); + p.addRole(PractitionerRoleEnum.DOCTOR); + p.setName(new HumanNameDt().addFamily("Mueller").addGiven("Klaus").addPrefix("Prof. Dr.")); + + performer.setResource(p); + performers.add(performer); + observation.setPerformer(performers); + + + List list = new ArrayList(); + list.add(dr); + Bundle bundle = RestfulServer.createBundleFromResourceList(new FhirContext(), null, list, null, null, 0); + + IParser parser = this.ctx.newXmlParser().setPrettyPrint(true); + String xml = parser.encodeBundleToString(bundle); + Assert.assertTrue(xml.contains("Mueller")); + + } + +} diff --git a/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java new file mode 100644 index 00000000000..6786d06f53a --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java @@ -0,0 +1,1198 @@ +package ca.uhn.fhir.parser; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import net.sf.json.JSON; +import net.sf.json.JSONSerializer; + +import org.apache.commons.io.IOUtils; +import org.hamcrest.Matchers; +import org.hamcrest.core.IsNot; +import org.hamcrest.core.StringContains; +import org.hamcrest.text.StringContainsInOrder; +import org.junit.BeforeClass; +import org.junit.Test; + +import ca.uhn.fhir.context.ConfigurationException; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.model.api.Bundle; +import ca.uhn.fhir.model.api.BundleEntry; +import ca.uhn.fhir.model.api.ExtensionDt; +import ca.uhn.fhir.model.api.IResource; +import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; +import ca.uhn.fhir.model.api.TagList; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.model.dstu.composite.AddressDt; +import ca.uhn.fhir.model.dstu.composite.HumanNameDt; +import ca.uhn.fhir.model.dstu.composite.NarrativeDt; +import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; +import ca.uhn.fhir.model.dstu.resource.Binary; +import ca.uhn.fhir.model.dstu.resource.Conformance; +import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource; +import ca.uhn.fhir.model.dstu.resource.DiagnosticReport; +import ca.uhn.fhir.model.dstu.resource.ListResource; +import ca.uhn.fhir.model.dstu.resource.Observation; +import ca.uhn.fhir.model.dstu.resource.Organization; +import ca.uhn.fhir.model.dstu.resource.Patient; +import ca.uhn.fhir.model.dstu.resource.Profile; +import ca.uhn.fhir.model.dstu.resource.Query; +import ca.uhn.fhir.model.dstu.resource.Specimen; +import ca.uhn.fhir.model.dstu.resource.ValueSet; +import ca.uhn.fhir.model.dstu.resource.ValueSet.Define; +import ca.uhn.fhir.model.dstu.resource.ValueSet.DefineConcept; +import ca.uhn.fhir.model.dstu.valueset.AddressUseEnum; +import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum; +import ca.uhn.fhir.model.primitive.DecimalDt; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.model.primitive.InstantDt; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.model.primitive.XhtmlDt; +import ca.uhn.fhir.narrative.INarrativeGenerator; + +public class JsonParserTest { + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserTest.class); + private static FhirContext ourCtx; + + @Test + public void testEncodeNarrativeBlockInBundle() { + Patient p = new Patient(); + p.addIdentifier("foo", "bar"); + p.getText().setStatus(NarrativeStatusEnum.GENERATED); + p.getText().setDiv("
hello
"); + + Bundle b = new Bundle(); + b.getTotalResults().setValue(123); + b.addEntry().setResource(p); + + String out = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(out); + assertThat(out, containsString("
hello
")); + + p.getText().setDiv("hello"); + out = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(out); + // Backslashes need to be escaped because they are in a JSON value + assertThat(out, containsString("hello")); + + } + + @Test + public void testEncodeNonContained() { + Organization org = new Organization(); + org.setId("Organization/65546"); + org.getName().setValue("Contained Test Organization"); + + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + patient.getManagingOrganization().setResource(org); + + Bundle b = Bundle.withResources(Collections.singletonList((IResource)patient), ourCtx, "http://foo"); + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(encoded); + assertThat(encoded, not(containsString("contained"))); + assertThat(encoded, containsString("\"reference\":\"Organization/65546\"")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString("contained"))); + assertThat(encoded, containsString("\"reference\":\"Organization/65546\"")); + } + + + @Test + public void testEncodeIds() { + Patient pt =new Patient(); + pt.addIdentifier("sys", "val"); + + ListResource list = new ListResource(); + list.setId("listId"); + list.addEntry().setItem(new ResourceReferenceDt(pt)); + + String enc = ourCtx.newJsonParser().encodeResourceToString(list); + ourLog.info(enc); + + assertThat(enc, containsString("\"id\":\"1\"")); + + ListResource parsed = ourCtx.newJsonParser().parseResource(ListResource.class,enc); + assertEquals(Patient.class, parsed.getEntryFirstRep().getItem().getResource().getClass()); + + enc = enc.replace("\"id\"", "\"_id\""); + parsed = ourCtx.newJsonParser().parseResource(ListResource.class,enc); + assertEquals(Patient.class, parsed.getEntryFirstRep().getItem().getResource().getClass()); +} + + @Test + public void testEncodingNullExtension() { + Patient p = new Patient(); + ExtensionDt extension = new ExtensionDt(false, "http://foo#bar"); + p.addUndeclaredExtension(extension); + String str = ourCtx.newJsonParser().encodeResourceToString(p); + + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new StringDt()); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new StringDt("")); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + } + + @Test + public void testParseSingleQuotes() { + try { + ourCtx.newJsonParser().parseBundle("{ 'resourceType': 'Bundle' }"); + fail(); + } catch (DataFormatException e) { + // Should be an error message about how single quotes aren't valid JSON + assertThat(e.getMessage(), containsString("double quote")); + } + } + + @Test + public void testEncodeExtensionInCompositeElement() { + + Conformance c = new Conformance(); + c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"rest\":[{\"security\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}]}"); + + } + + @Test + public void testEncodeExtensionInPrimitiveElement() { + + Conformance c = new Conformance(); + c.getAcceptUnknown().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"_acceptUnknown\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}]}"); + + // Now with a value + ourLog.info("---------------"); + + c = new Conformance(); + c.getAcceptUnknown().setValue(true); + c.getAcceptUnknown().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"acceptUnknown\":true,\"_acceptUnknown\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}]}"); + + } + + @Test + public void testEncodeExtensionInResourceElement() { + + Conformance c = new Conformance(); + // c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + c.addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"); + + } + + @Test + public void testEncodeBinaryResource() { + + Binary patient = new Binary(); + patient.setContentType("foo"); + patient.setContent(new byte[] { 1, 2, 3, 4 }); + + String val = ourCtx.newJsonParser().encodeResourceToString(patient); + assertEquals("{\"resourceType\":\"Binary\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}", val); + + } + + @Test + public void testParseEmptyNarrative() throws ConfigurationException, DataFormatException, IOException { + //@formatter:off + String text = "{\n" + + " \"resourceType\" : \"Patient\",\n" + + " \"extension\" : [\n" + + " {\n" + + " \"url\" : \"http://clairol.org/colour\",\n" + + " \"valueCode\" : \"B\"\n" + + " }\n" + + " ],\n" + + " \"text\" : {\n" + + " \"div\" : \"\"\n" + + " }" + + "}"; + //@formatter:on + + Patient res = (Patient) ourCtx.newJsonParser().parseResource(text); + XhtmlDt div = res.getText().getDiv(); + String value = div.getValueAsString(); + + assertEquals("", value); + assertEquals(null, div.getValue()); + } + + @Test + public void testNestedContainedResources() { + + Observation A = new Observation(); + A.getName().setText("A"); + + Observation B = new Observation(); + B.getName().setText("B"); + A.addRelated().setTarget(new ResourceReferenceDt(B)); + + Observation C = new Observation(); + C.getName().setText("C"); + B.addRelated().setTarget(new ResourceReferenceDt(C)); + + String str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(A); + ourLog.info(str); + + assertThat(str, stringContainsInOrder(Arrays.asList("\"text\":\"B\"", "\"text\":\"C\"", "\"text\":\"A\""))); + + // Only one (outer) contained block + int idx0 = str.indexOf("\"contained\""); + int idx1 = str.indexOf("\"contained\"", idx0 + 1); + + assertNotEquals(-1, idx0); + assertEquals(-1, idx1); + + Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, str); + assertEquals("A", obs.getName().getText().getValue()); + + Observation obsB = (Observation) obs.getRelatedFirstRep().getTarget().getResource(); + assertEquals("B", obsB.getName().getText().getValue()); + + Observation obsC = (Observation) obsB.getRelatedFirstRep().getTarget().getResource(); + assertEquals("C", obsC.getName().getText().getValue()); + + } + + @Test + public void testParseQuery() { + String msg = "{\n" + " \"resourceType\": \"Query\",\n" + " \"text\": {\n" + " \"status\": \"generated\",\n" + " \"div\": \"
[Put rendering here]
\"\n" + " },\n" + + " \"identifier\": \"urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376\",\n" + " \"parameter\": [\n" + " {\n" + " \"url\": \"http://hl7.org/fhir/query#_query\",\n" + + " \"valueString\": \"example\"\n" + " }\n" + " ]\n" + "}"; + Query query = ourCtx.newJsonParser().parseResource(Query.class, msg); + + assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString()); + assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString()); + assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString()); + + } + + @Test + public void testEncodeQuery() { + Query q = new Query(); + ExtensionDt parameter = q.addParameter(); + parameter.setUrl("http://hl7.org/fhir/query#_query").setValue(new StringDt("example")); + + String val = new FhirContext().newJsonParser().encodeResourceToString(q); + ourLog.info(val); + + //@formatter:off + String expected = + "{" + + "\"resourceType\":\"Query\"," + + "\"parameter\":[" + + "{" + + "\"url\":\"http://hl7.org/fhir/query#_query\"," + + "\"valueString\":\"example\"" + + "}" + + "]" + + "}"; + //@formatter:on + + ourLog.info("Expect: {}", expected); + ourLog.info("Got : {}", val); + assertEquals(expected, val); + + } + + @Test + public void testParseBinaryResource() { + + Binary val = ourCtx.newJsonParser().parseResource(Binary.class, "{\"resourceType\":\"Binary\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}"); + assertEquals("foo", val.getContentType()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, val.getContent()); + + } + + @Test + public void testTagList() { + + //@formatter:off + String tagListStr = "{\n" + + " \"resourceType\" : \"TagList\", " + + " \"category\" : [" + + " { " + + " \"term\" : \"term0\", " + + " \"label\" : \"label0\", " + + " \"scheme\" : \"scheme0\" " + + " }," + + " { " + + " \"term\" : \"term1\", " + + " \"label\" : \"label1\", " + + " \"scheme\" : null " + + " }," + + " { " + + " \"term\" : \"term2\", " + + " \"label\" : \"label2\" " + + " }" + + " ] " + + "}"; + //@formatter:on + + TagList tagList = new FhirContext().newJsonParser().parseTagList(tagListStr); + assertEquals(3, tagList.size()); + assertEquals("term0", tagList.get(0).getTerm()); + assertEquals("label0", tagList.get(0).getLabel()); + assertEquals("scheme0", tagList.get(0).getScheme()); + assertEquals("term1", tagList.get(1).getTerm()); + assertEquals("label1", tagList.get(1).getLabel()); + assertEquals(null, tagList.get(1).getScheme()); + assertEquals("term2", tagList.get(2).getTerm()); + assertEquals("label2", tagList.get(2).getLabel()); + assertEquals(null, tagList.get(2).getScheme()); + + /* + * Encode + */ + + //@formatter:off + String expected = "{" + + "\"resourceType\":\"TagList\"," + + "\"category\":[" + + "{" + + "\"term\":\"term0\"," + + "\"label\":\"label0\"," + + "\"scheme\":\"scheme0\"" + + "}," + + "{" + + "\"term\":\"term1\"," + + "\"label\":\"label1\"" + + "}," + + "{" + + "\"term\":\"term2\"," + + "\"label\":\"label2\"" + + "}" + + "]" + + "}"; + //@formatter:on + + String encoded = new FhirContext().newJsonParser().encodeTagListToString(tagList); + assertEquals(expected, encoded); + + } + + @Test + public void testEncodeBundleCategory() { + + Bundle b = new Bundle(); + BundleEntry e = b.addEntry(); + e.setResource(new Patient()); + b.addCategory("scheme", "term", "label"); + + String val = new FhirContext().newJsonParser().setPrettyPrint(false).encodeBundleToString(b); + ourLog.info(val); + + assertThat(val, StringContains.containsString("\"category\":[{\"term\":\"term\",\"label\":\"label\",\"scheme\":\"scheme\"}]")); + + b = new FhirContext().newJsonParser().parseBundle(val); + assertEquals(1, b.getEntries().size()); + assertEquals(1, b.getCategories().size()); + assertEquals("term", b.getCategories().get(0).getTerm()); + assertEquals("label", b.getCategories().get(0).getLabel()); + assertEquals("scheme", b.getCategories().get(0).getScheme()); + assertNull(b.getEntries().get(0).getResource()); + + } + + @Test + public void testEncodeBundleEntryCategory() { + + Bundle b = new Bundle(); + BundleEntry e = b.addEntry(); + e.setResource(new Patient()); + e.addCategory("scheme", "term", "label"); + + String val = ourCtx.newJsonParser().setPrettyPrint(false).encodeBundleToString(b); + ourLog.info(val); + + assertThat(val, StringContains.containsString("\"category\":[{\"term\":\"term\",\"label\":\"label\",\"scheme\":\"scheme\"}]")); + + b = ourCtx.newJsonParser().parseBundle(val); + assertEquals(1, b.getEntries().size()); + assertEquals(1, b.getEntries().get(0).getCategories().size()); + assertEquals("term", b.getEntries().get(0).getCategories().get(0).getTerm()); + assertEquals("label", b.getEntries().get(0).getCategories().get(0).getLabel()); + assertEquals("scheme", b.getEntries().get(0).getCategories().get(0).getScheme()); + assertNull(b.getEntries().get(0).getResource()); + + } + + @Test + public void testEncodeContained__() { + // Create an organization + Organization org = new Organization(); + org.getName().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + patient.getManagingOrganization().setResource(org); + + // Create a bundle with just the patient resource + List resources = new ArrayList(); + resources.add(patient); + Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base"); + + // Encode the buntdle + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\":\"Organization", "id\":\"1\""))); + assertThat(encoded, containsString("reference\":\"#1\"")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\":\"Organization", "id\":\"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("
FOOBAR
"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + patient.getText().setDiv("
BARFOO
"); + patient.getManagingOrganization().setResource(org); + + String encoded = parser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString("FOOBAR"))); + assertThat(encoded, (containsString("BARFOO"))); + + } + + @Test + public void testEncodeContained() { + IParser xmlParser = 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"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + + // Put the organization as a reference in the patient resource + patient.getManagingOrganization().setResource(org); + + String encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\":[", "\"id\":\"1\"", "\"identifier\"", "\"reference\":\"#1\""))); + + // Create a bundle with just the patient resource + List resources = new ArrayList(); + resources.add(patient); + Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base"); + + // Encode the bundle + encoded = xmlParser.encodeBundleToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\":[", "\"id\":\"1\"", "\"identifier\"", "\"reference\":\"#1\""))); + + // Re-parse the bundle + patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); + assertEquals("#1", patient.getManagingOrganization().getReference().getValue()); + + assertNotNull(patient.getManagingOrganization().getResource()); + org = (Organization) patient.getManagingOrganization().getResource(); + assertEquals("#1", org.getId().getValue()); + assertEquals("Contained Test Organization", org.getName().getValue()); + + // And re-encode a second time + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\":[", "\"id\":\"1\"", "\"identifier\"", "\"reference\":\"#1\""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("\"contained\":", "[", "\"contained\":")))); + + // And re-encode once more, with the references cleared + patient.getContained().getContainedResources().clear(); + patient.getManagingOrganization().setReference((IdDt)null); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\":[", "\"id\":\"1\"", "\"identifier\"", "\"reference\":\"#1\""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("\"contained\":", "[", "\"contained\":")))); + + // And re-encode once more, with the references cleared and a manually set local ID + patient.getContained().getContainedResources().clear(); + patient.getManagingOrganization().setReference((IdDt)null); + patient.getManagingOrganization().getResource().setId(new IdDt("#333")); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\":[", "\"id\":\"333\"", "\"identifier\"", "\"reference\":\"#333\""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("\"contained\":", "[", "\"contained\":")))); + + } + + + + + @Test + public void testEncodeContainedResources() throws IOException { + + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/contained-diagnosticreport.xml")); + IParser p = ourCtx.newXmlParser(); + DiagnosticReport res = p.parseResource(DiagnosticReport.class, msg); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + } + + @Test + public void testParseJsonProfile() throws IOException { + parseAndEncode("/patient.profile.json"); + parseAndEncode("/alert.profile.json"); + } + + private void parseAndEncode(String name) throws IOException { + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream(name)); + ourLog.info(msg); + + IParser p = ourCtx.newJsonParser(); + Profile res = p.parseResource(Profile.class, msg); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + JSON expected = JSONSerializer.toJSON(msg.trim()); + JSON actual = JSONSerializer.toJSON(encoded.trim()); + + String exp = expected.toString().replace("\\r\\n", "\\n"); // .replace("§", "§"); + String act = actual.toString().replace("\\r\\n", "\\n"); + + ourLog.info("Expected: {}", exp); + ourLog.info("Actual : {}", act); + + assertEquals(exp, act); + } + + @Test + public void testEncodeContainedResourcesMore() { + + DiagnosticReport rpt = new DiagnosticReport(); + Specimen spm = new Specimen(); + rpt.getText().setDiv("AAA"); + rpt.addSpecimen().setResource(spm); + + IParser p = new FhirContext(DiagnosticReport.class).newJsonParser().setPrettyPrint(true); + String str = p.encodeResourceToString(rpt); + + ourLog.info(str); + assertThat(str, StringContains.containsString("
AAA
")); + String substring = "\"reference\":\"#"; + assertThat(str, StringContains.containsString(substring)); + + int idx = str.indexOf(substring) + substring.length(); + int idx2 = str.indexOf('"', idx + 1); + String id = str.substring(idx, idx2); + assertThat(str, StringContains.containsString("\"id\":\"" + id + "\"")); + assertThat(str, IsNot.not(StringContains.containsString(""))); + + } + + @Test + public void testEncodeDeclaredExtensionWithAddressContent() { + IParser parser = new FhirContext().newJsonParser(); + + MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension(); + patient.addAddress().setUse(AddressUseEnum.HOME); + patient.setFoo(new AddressDt().addLine("line1")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueAddress\":{\"line\":[\"line1\"]}}]")); + + MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + AddressDt ref = actual.getFoo(); + assertEquals("line1", ref.getLineFirstRep().getValue()); + + } + + @Test + public void testEncodeDeclaredExtensionWithResourceContent() { + IParser parser = new FhirContext().newJsonParser(); + + MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension(); + patient.addAddress().setUse(AddressUseEnum.HOME); + patient.setFoo(new ResourceReferenceDt("Organization/123")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueResource\":{\"reference\":\"Organization/123\"}}]")); + + MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + ResourceReferenceDt ref = actual.getFoo(); + assertEquals("Organization/123", ref.getReference().getValue()); + + } + + @Test + public void testEncodeExtensionOnEmptyElement() throws Exception { + + ValueSet valueSet = new ValueSet(); + valueSet.addTelecom().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet); + assertThat(encoded, containsString("\"telecom\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}")); + + } + + @Test + public void testEncodeExt() throws Exception { + + ValueSet valueSet = new ValueSet(); + valueSet.setId("123456"); + + Define define = valueSet.getDefine(); + DefineConcept code = define.addConcept(); + code.setCode("someCode"); + code.setDisplay("someDisplay"); + code.addUndeclaredExtension(false, "urn:alt", new StringDt("alt name")); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet); + ourLog.info(encoded); + + assertThat(encoded, not(containsString("123456"))); + assertEquals( + "{\"resourceType\":\"ValueSet\",\"define\":{\"concept\":[{\"extension\":[{\"url\":\"urn:alt\",\"valueString\":\"alt name\"}],\"code\":\"someCode\",\"display\":\"someDisplay\"}]}}", + encoded); + + } + + @Test + public void testEncodeExtensionWithResourceContent() { + IParser parser = new FhirContext().newJsonParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUseEnum.HOME); + patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt("Organization/123")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueResource\":{\"reference\":\"Organization/123\"}}]")); + + Patient actual = parser.parseResource(Patient.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + List ext = actual.getUndeclaredExtensionsByUrl("urn:foo"); + assertEquals(1, ext.size()); + ResourceReferenceDt ref = (ResourceReferenceDt) ext.get(0).getValue(); + assertEquals("Organization/123", ref.getReference().getValue()); + + } + + @Test + public void testEncodeInvalidChildGoodException() { + Observation obs = new Observation(); + obs.setValue(new DecimalDt(112.22)); + + IParser p = new FhirContext(Observation.class).newJsonParser(); + + try { + p.encodeResourceToString(obs); + } catch (DataFormatException e) { + assertThat(e.getMessage(), StringContains.containsString("DecimalDt")); + } + } + + @Test + public void testEncodeResourceRef() throws DataFormatException { + + Patient patient = new Patient(); + patient.setManagingOrganization(new ResourceReferenceDt()); + + IParser p = new FhirContext().newJsonParser(); + String str = p.encodeResourceToString(patient); + assertThat(str, IsNot.not(StringContains.containsString("managingOrganization"))); + + patient.setManagingOrganization(new ResourceReferenceDt("Organization/123")); + str = p.encodeResourceToString(patient); + assertThat(str, StringContains.containsString("\"managingOrganization\":{\"reference\":\"Organization/123\"}")); + + Organization org = new Organization(); + org.addIdentifier().setSystem("foo").setValue("bar"); + patient.setManagingOrganization(new ResourceReferenceDt(org)); + str = p.encodeResourceToString(patient); + assertThat(str, StringContains.containsString("\"contained\":[{\"resourceType\":\"Organization\"")); + + } + + @Test + public void testEncodeUndeclaredExtensionWithAddressContent() { + IParser parser = new FhirContext().newJsonParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUseEnum.HOME); + patient.addUndeclaredExtension(false, "urn:foo", new AddressDt().addLine("line1")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueAddress\":{\"line\":[\"line1\"]}}]")); + + MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + AddressDt ref = actual.getFoo(); + assertEquals("line1", ref.getLineFirstRep().getValue()); + + } + + @Test + public void testExtensionOnComposite() throws Exception { + + Patient patient = new Patient(); + + HumanNameDt name = patient.addName(); + name.addFamily().setValue("Shmoe"); + HumanNameDt given = name.addGiven("Joe"); + ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello")); + given.addUndeclaredExtension(ext2); + String enc = new FhirContext().newJsonParser().encodeResourceToString(patient); + ourLog.info(enc); + assertEquals("{\"resourceType\":\"Patient\",\"name\":[{\"extension\":[{\"url\":\"http://examples.com#givenext\",\"valueString\":\"Hello\"}],\"family\":[\"Shmoe\"],\"given\":[\"Joe\"]}]}", enc); + + IParser newJsonParser = new FhirContext().newJsonParser(); + StringReader reader = new StringReader(enc); + Patient parsed = newJsonParser.parseResource(Patient.class, reader); + + ourLog.info(new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed)); + + assertEquals(1, parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size()); + ExtensionDt ext = parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0); + assertEquals("Hello", ext.getValueAsPrimitive().getValue()); + + } + + @Test + public void testExtensionOnPrimitive() throws Exception { + + Patient patient = new Patient(); + + HumanNameDt name = patient.addName(); + StringDt family = name.addFamily(); + family.setValue("Shmoe"); + + ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello")); + family.addUndeclaredExtension(ext2); + String enc = new FhirContext().newJsonParser().encodeResourceToString(patient); + ourLog.info(enc); + //@formatter:off + assertThat(enc, containsString(("{\n" + + " \"resourceType\":\"Patient\",\n" + + " \"name\":[\n" + + " {\n" + + " \"family\":[\n" + + " \"Shmoe\"\n" + + " ],\n" + + " \"_family\":[\n" + + " {\n" + + " \"extension\":[\n" + + " {\n" + + " \"url\":\"http://examples.com#givenext\",\n" + + " \"valueString\":\"Hello\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}").replace("\n", "").replaceAll(" +", ""))); + //@formatter:on + + Patient parsed = new FhirContext().newJsonParser().parseResource(Patient.class, new StringReader(enc)); + assertEquals(1, parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size()); + ExtensionDt ext = parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0); + assertEquals("Hello", ext.getValueAsPrimitive().getValue()); + + } + + @Test + public void testNarrativeGeneration() throws DataFormatException, IOException { + + Patient patient = new Patient(); + patient.addName().addFamily("Smith"); + Organization org = new Organization(); + patient.getManagingOrganization().setResource(org); + + INarrativeGenerator gen = mock(INarrativeGenerator.class); + XhtmlDt xhtmlDt = new XhtmlDt("
help
"); + NarrativeDt nar = new NarrativeDt(xhtmlDt, NarrativeStatusEnum.GENERATED); + when(gen.generateNarrative(eq("http://hl7.org/fhir/profiles/Patient"), eq(patient))).thenReturn(nar); + + FhirContext context = new FhirContext(); + context.setNarrativeGenerator(gen); + IParser p = context.newJsonParser(); + p.encodeResourceToWriter(patient, new OutputStreamWriter(System.out)); + String str = p.encodeResourceToString(patient); + + ourLog.info(str); + + assertThat(str, StringContains.containsString(",\"text\":{\"status\":\"generated\",\"div\":\"
help
\"},")); + } + + @Test + public void testParseBundle() throws DataFormatException, IOException { + + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/atom-document-large.json")); + IParser p = ourCtx.newJsonParser(); + Bundle bundle = p.parseBundle(msg); + + assertEquals(1, bundle.getCategories().size()); + assertEquals("http://scheme", bundle.getCategories().get(0).getScheme()); + assertEquals("http://term", bundle.getCategories().get(0).getTerm()); + assertEquals("label", bundle.getCategories().get(0).getLabel()); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle); + ourLog.info(encoded); + + assertEquals("http://fhir.healthintersections.com.au/open/DiagnosticReport/_search?_format=application/json+fhir&search-id=46d5f0e7-9240-4d4f-9f51-f8ac975c65&search-sort=_id", bundle + .getLinkSelf().getValue()); + assertEquals("urn:uuid:0b754ff9-03cf-4322-a119-15019af8a3", bundle.getBundleId().getValue()); + + BundleEntry entry = bundle.getEntries().get(0); + assertEquals("http://fhir.healthintersections.com.au/open/DiagnosticReport/101", entry.getId().getValue()); + assertEquals("http://fhir.healthintersections.com.au/open/DiagnosticReport/101/_history/1", entry.getLinkSelf().getValue()); + assertEquals("2014-03-10T11:55:59Z", entry.getUpdated().getValueAsString()); + + DiagnosticReport res = (DiagnosticReport) entry.getResource(); + assertEquals("Complete Blood Count", res.getName().getText().getValue()); + + assertThat(entry.getSummary().getValueAsString(), containsString("CBC Report for Wile")); + + } + + @Test + public void testParseBundleFromHI() throws DataFormatException, IOException { + + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/bundle.json")); + IParser p = ourCtx.newJsonParser(); + Bundle bundle = p.parseBundle(msg); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle); + ourLog.info(encoded); + + BundleEntry entry = bundle.getEntries().get(0); + + Patient res = (Patient) entry.getResource(); + assertEquals("444111234", res.getIdentifierFirstRep().getValue().getValue()); + + BundleEntry deletedEntry = bundle.getEntries().get(3); + assertEquals("2014-06-20T20:15:49Z", deletedEntry.getDeletedAt().getValueAsString()); + + } + + /** + * This sample has extra elements in that are not actually a part of the spec any more.. + */ + @Test + public void testParseFuroreMetadataWithExtraElements() throws IOException { + String msg = IOUtils.toString(JsonParserTest.class.getResourceAsStream("/furore-conformance.json")); + + IParser p = ourCtx.newJsonParser(); + Conformance conf = p.parseResource(Conformance.class, msg); + RestResource res = conf.getRestFirstRep().getResourceFirstRep(); + assertEquals("_id", res.getSearchParam().get(1).getName().getValue()); + } + + @Test + public void testParseWithContained() throws DataFormatException, IOException { + + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/diagnostic-report.json")); + IParser p = ourCtx.newJsonParser(); + // ourLog.info("Reading in message: {}", msg); + DiagnosticReport res = p.parseResource(DiagnosticReport.class, msg); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + ResourceReferenceDt reference = res.getResult().get(1); + Observation obs = (Observation) reference.getResource(); + + assertEquals("789-8", obs.getName().getCoding().get(0).getCode().getValue()); + } + + @BeforeClass + public static void beforeClass() { + ourCtx = new FhirContext(); + } + + @Test + public void testParseBundleDeletedEntry() { + + //@formatter:off + String bundleString = + "{" + + "\"resourceType\":\"Bundle\"," + + "\"totalResults\":\"1\"," + + "\"entry\":[" + + "{" + + "\"deleted\":\"2012-05-29T23:45:32+00:00\"," + + "\"id\":\"http://fhir.furore.com/fhir/Patient/1\"," + + "\"link\":[" + + "{" + + "\"rel\":\"self\"," + + "\"href\":\"http://fhir.furore.com/fhir/Patient/1/_history/2\"" + + "}" + + "]" + + "}" + + "]" + + "}"; + //@formatter:on + + Bundle bundle = ourCtx.newJsonParser().parseBundle(bundleString); + BundleEntry entry = bundle.getEntries().get(0); + assertEquals("2012-05-29T23:45:32+00:00", entry.getDeletedAt().getValueAsString()); + assertEquals("http://fhir.furore.com/fhir/Patient/1/_history/2", entry.getLinkSelf().getValue()); + assertEquals("1", entry.getResource().getId().getIdPart()); + assertEquals("2", entry.getResource().getId().getVersionIdPart()); + assertEquals(new InstantDt("2012-05-29T23:45:32+00:00"), entry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.DELETED_AT)); + + // Now encode + + ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(bundle)); + String encoded = ourCtx.newJsonParser().encodeBundleToString(bundle); + assertEquals(bundleString, encoded); + + } + + @Test + public void testEncodeBundle() throws InterruptedException { + Bundle b = new Bundle(); + + InstantDt pub = InstantDt.withCurrentTime(); + b.setPublished(pub); + Thread.sleep(2); + + Patient p1 = new Patient(); + p1.addName().addFamily("Family1"); + BundleEntry entry = b.addEntry(); + entry.getId().setValue("1"); + entry.setResource(p1); + entry.getSummary().setValueAsString("this is the summary"); + + Patient p2 = new Patient(); + p2.addName().addFamily("Family2"); + entry = b.addEntry(); + entry.getId().setValue("2"); + entry.setLinkAlternate(new StringDt("http://foo/bar")); + entry.setResource(p2); + + BundleEntry deletedEntry = b.addEntry(); + deletedEntry.setId(new IdDt("Patient/3")); + InstantDt nowDt = InstantDt.withCurrentTime(); + deletedEntry.setDeleted(nowDt); + + String bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(bundleString); + + List strings = new ArrayList(); + strings.addAll(Arrays.asList("\"published\":\"" + pub.getValueAsString() + "\"")); + strings.addAll(Arrays.asList("\"id\":\"1\"")); + strings.addAll(Arrays.asList("this is the summary")); + strings.addAll(Arrays.asList("\"id\":\"2\"", "\"rel\":\"alternate\"", "\"href\":\"http://foo/bar\"")); + strings.addAll(Arrays.asList("\"deleted\":\"" + nowDt.getValueAsString() + "\"", "\"id\":\"Patient/3\"")); + assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings)); + + b.getEntries().remove(2); + bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + assertThat(bundleString, not(containsString("deleted"))); + + } + + @Test + public void testSimpleBundleEncode() throws IOException { + + String xmlString = IOUtils.toString(JsonParser.class.getResourceAsStream("/atom-document-large.xml"), Charset.forName("UTF-8")); + Bundle obs = ourCtx.newXmlParser().parseBundle(xmlString); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(obs); + ourLog.info(encoded); + + } + + @Test + public void testSimpleParse() throws DataFormatException, IOException { + + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/example-patient-general.json")); + IParser p = ourCtx.newJsonParser(); + // ourLog.info("Reading in message: {}", msg); + Patient res = p.parseResource(Patient.class, msg); + + assertEquals(2, res.getUndeclaredExtensions().size()); + assertEquals(1, res.getUndeclaredModifierExtensions().size()); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + } + + @Test + public void testSimpleResourceEncode() throws IOException { + + String xmlString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.xml"), Charset.forName("UTF-8")); + Patient obs = ourCtx.newXmlParser().parseResource(Patient.class, xmlString); + + List undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions(); + ExtensionDt undeclaredExtension = undeclaredExtensions.get(0); + assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue()); + + ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out)); + + IParser jsonParser = ourCtx.newJsonParser(); + String encoded = jsonParser.encodeResourceToString(obs); + ourLog.info(encoded); + + String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.json"), Charset.forName("UTF-8")); + + JSON expected = JSONSerializer.toJSON(jsonString); + JSON actual = JSONSerializer.toJSON(encoded.trim()); + + // The encoded escapes quote marks using XML escaping instead of JSON escaping, which is probably nicer anyhow... + String exp = expected.toString().replace("\\\"Jim\\\"", ""Jim""); + String act = actual.toString(); + + ourLog.info("Expected: {}", exp); + ourLog.info("Actual : {}", act); + assertEquals(exp, act); + + } + + /** + * HAPI FHIR < 0.6 incorrectly used "resource" instead of "reference" + */ + @Test + public void testParseWithIncorrectReference() throws IOException { + String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.json")); + jsonString = jsonString.replace("\"reference\"", "\"resource\""); + Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, jsonString); + assertEquals("Organization/1", parsed.getManagingOrganization().getReference().getValue()); + } + + @Test + public void testSimpleResourceEncodeWithCustomType() throws IOException { + + FhirContext fhirCtx = new FhirContext(MyObservationWithExtensions.class); + String xmlString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.xml"), Charset.forName("UTF-8")); + MyObservationWithExtensions obs = fhirCtx.newXmlParser().parseResource(MyObservationWithExtensions.class, xmlString); + + assertEquals(0, obs.getAllUndeclaredExtensions().size()); + assertEquals("aaaa", obs.getExtAtt().getContentType().getValue()); + assertEquals("str1", obs.getMoreExt().getStr1().getValue()); + assertEquals("2011-01-02", obs.getModExt().getValueAsString()); + + List undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions(); + ExtensionDt undeclaredExtension = undeclaredExtensions.get(0); + assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue()); + + IParser jsonParser = fhirCtx.newJsonParser().setPrettyPrint(true); + String encoded = jsonParser.encodeResourceToString(obs); + ourLog.info(encoded); + + String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.json"), Charset.forName("UTF-8")); + + JSON expected = JSONSerializer.toJSON(jsonString); + JSON actual = JSONSerializer.toJSON(encoded.trim()); + + // The encoded escapes quote marks using XML escaping instead of JSON escaping, which is probably nicer anyhow... + String exp = expected.toString().replace("\\\"Jim\\\"", ""Jim""); + String act = actual.toString(); + + ourLog.info("Expected: {}", exp); + ourLog.info("Actual : {}", act); + assertEquals(exp, act); + + } + + @ResourceDef(name = "Patient") + public static class MyPatientWithOneDeclaredAddressExtension extends Patient { + + @Child(order = 0, name = "foo") + @Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private AddressDt myFoo; + + public AddressDt getFoo() { + return myFoo; + } + + public void setFoo(AddressDt theFoo) { + myFoo = theFoo; + } + + } + + @ResourceDef(name = "Patient") + public static class MyPatientWithOneDeclaredExtension extends Patient { + + @Child(order = 0, name = "foo") + @Extension(url = "urn:foo", definedLocally = true, isModifier = false) + private ResourceReferenceDt myFoo; + + public ResourceReferenceDt getFoo() { + return myFoo; + } + + public void setFoo(ResourceReferenceDt theFoo) { + myFoo = theFoo; + } + + } + +} diff --git a/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyObservationWithExtensions.java b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyObservationWithExtensions.java new file mode 100644 index 00000000000..5309bf2131f --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyObservationWithExtensions.java @@ -0,0 +1,109 @@ +package ca.uhn.fhir.parser; + +import java.util.Collections; +import java.util.List; + +import ca.uhn.fhir.model.api.BaseIdentifiableElement; +import ca.uhn.fhir.model.api.IElement; +import ca.uhn.fhir.model.api.IResourceBlock; +import ca.uhn.fhir.model.api.annotation.Block; +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.model.dstu.composite.AttachmentDt; +import ca.uhn.fhir.model.dstu.resource.Patient; +import ca.uhn.fhir.model.primitive.DateDt; +import ca.uhn.fhir.model.primitive.StringDt; +import ca.uhn.fhir.util.ElementUtil; + +@ResourceDef(name="Patient") +public class MyObservationWithExtensions extends Patient { + + @Extension(url = "urn:patientext:att", definedLocally = false, isModifier = false) + @Child(name = "extAtt", order = 0) + private AttachmentDt myExtAtt; + + @Extension(url = "urn:patientext:moreext", definedLocally = false, isModifier = false) + @Child(name = "moreExt", order = 1) + private MoreExt myMoreExt; + + @Extension(url = "urn:modext", definedLocally = false, isModifier = true) + @Child(name = "modExt", order = 2) + private DateDt myModExt; + + public AttachmentDt getExtAtt() { + return myExtAtt; + } + + public MoreExt getMoreExt() { + return myMoreExt; + } + + public void setMoreExt(MoreExt theMoreExt) { + myMoreExt = theMoreExt; + } + + public DateDt getModExt() { + return myModExt; + } + + public void setModExt(DateDt theModExt) { + myModExt = theModExt; + } + + public void setExtAtt(AttachmentDt theExtAtt) { + myExtAtt = theExtAtt; + } + + @Override + public boolean isEmpty() { + return super.isEmpty() && ElementUtil.isEmpty(myExtAtt, myModExt, myMoreExt); + } + + /** + * Block class for child element: Observation.referenceRange (Provides guide for interpretation) + * + *

+ * Definition: Guidance on how to interpret the value by comparison to a normal or recommended range + *

+ */ + @Block(name = "Observation.someExtensions") + public static class MoreExt extends BaseIdentifiableElement implements IResourceBlock { + + @Extension(url = "urn:patientext:moreext:1", definedLocally = false, isModifier = false) + @Child(name = "str1", order = 0) + private StringDt myStr1; + + @Extension(url = "urn:patientext:moreext:2", definedLocally = false, isModifier = false) + @Child(name = "str2", order = 1) + private StringDt myStr2; + + public StringDt getStr1() { + return myStr1; + } + + public void setStr1(StringDt theStr1) { + myStr1 = theStr1; + } + + public StringDt getStr2() { + return myStr2; + } + + public void setStr2(StringDt theStr2) { + myStr2 = theStr2; + } + + @Override + public List getAllPopulatedChildElementsOfType(Class theType) { + return Collections.emptyList(); + } + + @Override + public boolean isEmpty() { + return ElementUtil.isEmpty(myStr1, myStr2); + } + + } + +} diff --git a/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyOrganization.java b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyOrganization.java new file mode 100644 index 00000000000..6e69d520ec4 --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyOrganization.java @@ -0,0 +1,9 @@ +package ca.uhn.fhir.parser; + +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.model.dstu.resource.Organization; + +@ResourceDef() +public class MyOrganization extends Organization { + +} diff --git a/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyPatient.java b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyPatient.java new file mode 100644 index 00000000000..b3c9b635b2c --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/MyPatient.java @@ -0,0 +1,62 @@ +package ca.uhn.fhir.parser; + +import java.util.ArrayList; +import java.util.List; + +import ca.uhn.fhir.model.api.annotation.Child; +import ca.uhn.fhir.model.api.annotation.Description; +import ca.uhn.fhir.model.api.annotation.Extension; +import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt; +import ca.uhn.fhir.model.dstu.resource.Patient; +import ca.uhn.fhir.model.primitive.DateTimeDt; +import ca.uhn.fhir.model.primitive.StringDt; + +@ResourceDef() +public class MyPatient extends Patient { + + @Child(name="petName") + @Extension(url="http://example.com/dontuse#petname", definedLocally=false, isModifier=false) + @Description(shortDefinition="The name of the patient's favourite pet") + private StringDt myPetName; + + @Child(name="importantDates", max=Child.MAX_UNLIMITED) + @Extension(url="http://example.com/dontuse#importantDates", definedLocally=false, isModifier=true) + @Description(shortDefinition="Some dates of note for the patient") + private List myImportantDates; + + @Child(name="managingOrganization", order=Child.REPLACE_PARENT, min=0, max=1, type={ + MyOrganization.class }) + @Description( + shortDefinition="Organization that is the custodian of the patient record", + formalDefinition="Organization that is the custodian of the patient record" + ) + private ResourceReferenceDt myManagingOrganization; + + + @Override + public boolean isEmpty() { + return super.isEmpty() && myPetName.isEmpty(); + } + + + public List getImportantDates() { + if (myImportantDates==null) { + myImportantDates = new ArrayList(); + } + return myImportantDates; + } + + public StringDt getPetName() { + return myPetName; + } + + public void setImportantDates(List theImportantDates) { + myImportantDates = theImportantDates; + } + + public void setPetName(StringDt thePetName) { + myPetName = thePetName; + } + +} diff --git a/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java new file mode 100644 index 00000000000..16fc8fe4d78 --- /dev/null +++ b/hapi-fhir-structures-hl7org-dev/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java @@ -0,0 +1,1434 @@ +package ca.uhn.fhir.parser; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.stringContainsInOrder; +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.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.StringReader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import org.apache.commons.io.IOUtils; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; +import org.hamcrest.core.IsNot; +import org.hamcrest.core.StringContains; +import org.hamcrest.text.StringContainsInOrder; +import org.junit.BeforeClass; +import org.junit.Test; +import org.xml.sax.SAXException; + +import ca.uhn.fhir.context.ConfigurationException; +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.context.ResourceWithExtensionsA; +import ca.uhn.fhir.model.api.Bundle; +import ca.uhn.fhir.model.api.BundleEntry; +import ca.uhn.fhir.model.api.ExtensionDt; +import ca.uhn.fhir.model.api.IResource; +import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; +import ca.uhn.fhir.model.api.TagList; +import ca.uhn.fhir.narrative.INarrativeGenerator; +import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredAddressExtension; +import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredExtension; + +public class XmlParserTest { + + private static FhirContext ourCtx; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class); + + @BeforeClass + public static void beforeClass2() { + System.setProperty("file.encoding", "ISO-8859-1"); + } + + @Test + public void testProfileWithBoundCode() throws IOException { + String content = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/DMIXAuditException.xml"), "UTF-8"); + ourCtx.newXmlParser().parseResource(Profile.class, content); + } + + @Test + public void testEncodeBinaryWithNoContentType() { + Binary b = new Binary(); + b.setContent(new byte[] {1,2,3,4}); + + String output = ourCtx.newXmlParser().encodeResourceToString(b); + ourLog.info(output); + + assertEquals("AQIDBA==", output); + } + + + @Test + public void testEncodeNonContained() { + // Create an organization + Organization org = new Organization(); + org.setId("Organization/65546"); + org.getName().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + patient.getManagingOrganization().setResource(org); + + // Create a list containing both resources. In a server method, you might just + // return this list, but here we will create a bundle to encode. + List resources = new ArrayList(); + resources.add(org); + resources.add(patient); + + // Create a bundle with both + Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base"); + + // Encode the buntdle + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(encoded); + assertThat(encoded, not(containsString(""))); + assertThat(encoded, containsString("")); + + encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString(""))); + assertThat(encoded, containsString("")); + + + } + + @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("
FOOBAR
"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + patient.getText().setDiv("
BARFOO
"); + patient.getManagingOrganization().setResource(org); + + String encoded = parser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString("FOOBAR"))); + assertThat(encoded, (containsString("BARFOO"))); + + } + + + @Test + public void testEncodeContained() { + IParser xmlParser = 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"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + + // Put the organization as a reference in the patient resource + patient.getManagingOrganization().setResource(org); + + String encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, containsString("")); + assertThat(encoded, containsString("")); + + // Create a bundle with just the patient resource + List resources = new ArrayList(); + resources.add(patient); + Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base"); + + // Encode the buntdle + encoded = xmlParser.encodeBundleToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("","id=\"1\"", ""))); + assertThat(encoded, containsString("")); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); + + // Re-parse the bundle + patient = (Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient)); + assertEquals("#1", patient.getManagingOrganization().getReference().getValue()); + + assertNotNull(patient.getManagingOrganization().getResource()); + org = (Organization) patient.getManagingOrganization().getResource(); + assertEquals("#1", org.getId().getValue()); + assertEquals("Contained Test Organization", org.getName().getValue()); + + // And re-encode a second time + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared + patient.getContained().getContainedResources().clear(); + patient.getManagingOrganization().setReference((IdDt)null); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + assertThat(encoded, containsString("")); + + // And re-encode once more, with the references cleared and a manually set local ID + patient.getContained().getContainedResources().clear(); + patient.getManagingOrganization().setReference((IdDt)null); + patient.getManagingOrganization().getResource().setId(new IdDt("#333")); + encoded = xmlParser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "")))); + + } + + + /** + * Thanks to Alexander Kley! + */ + @Test + public void testParseContainedBinaryResource() { + byte[] bin = new byte[] {0,1,2,3,4}; + final Binary binary = new Binary("PatientConsent", bin); +// binary.setId(UUID.randomUUID().toString()); + DocumentManifest manifest = new DocumentManifest(); +// manifest.setId(UUID.randomUUID().toString()); + manifest.setType(new CodeableConceptDt("mySystem", "PatientDocument")); + manifest.setMasterIdentifier("mySystem", UUID.randomUUID().toString()); + manifest.addContent().setResource(binary); + manifest.setStatus(DocumentReferenceStatusEnum.CURRENT); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest); + ourLog.info(encoded); + assertThat(encoded, StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>",""))); + + DocumentManifest actual = ourCtx.newXmlParser().parseResource(DocumentManifest.class, encoded); + assertEquals(1, actual.getContained().getContainedResources().size()); + assertEquals(1, actual.getContent().size()); + assertNotNull(actual.getContent().get(0).getResource()); + + } + + + @Test + public void testComposition() { + + Composition comp = new Composition(); + comp.setId("1"); + + ourCtx.newXmlParser().encodeResourceToString(comp); + ourCtx.newXmlParser().encodeResourceToString(comp); + ourCtx.newXmlParser().encodeResourceToString(comp); + ourCtx.newXmlParser().encodeResourceToString(comp); + +// comp. + + } + + + @Test + public void testEncodeProfile() { + + Profile p = new Profile(); + p.getStructureFirstRep().getElementFirstRep().getDefinition().getBinding().setReference(new ResourceReferenceDt("ValudSet/123")); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(p); + ourLog.info(encoded); + } + + @Test + public void testEncodeBinaryResource() { + + Binary patient = new Binary(); + patient.setContentType("foo"); + patient.setContent(new byte[] { 1, 2, 3, 4 }); + + String val = ourCtx.newXmlParser().encodeResourceToString(patient); + assertEquals("AQIDBA==", val); + + } + + @Test + public void testEncodeBoundCode() { + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUseEnum.HOME); + + patient.getGender().setValueAsEnum(AdministrativeGenderCodesEnum.M); + + String val = ourCtx.newXmlParser().encodeResourceToString(patient); + ourLog.info(val); + + } + + @Test + public void testEncodeBundle() throws InterruptedException { + Bundle b = new Bundle(); + b.getCategories().addTag("http://hl7.org/fhir/tag", "http://hl7.org/fhir/tag/message", "Message"); + + InstantDt pub = InstantDt.withCurrentTime(); + b.setPublished(pub); + Thread.sleep(2); + + Patient p1 = new Patient(); + p1.addName().addFamily("Family1"); + BundleEntry entry = b.addEntry(); + entry.getId().setValue("1"); + entry.setResource(p1); + entry.getSummary().setValueAsString("this is the summary"); + + Patient p2 = new Patient(); + p2.addName().addFamily("Family2"); + entry = b.addEntry(); + entry.getId().setValue("2"); + entry.setLinkAlternate(new StringDt("http://foo/bar")); + entry.setLinkSearch(new StringDt("http://foo/bar/search")); + entry.setResource(p2); + + BundleEntry deletedEntry = b.addEntry(); + deletedEntry.setId(new IdDt("Patient/3")); + deletedEntry.setDeleted(InstantDt.withCurrentTime()); + + String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(bundleString); + + List strings = new ArrayList(); + strings.addAll(Arrays.asList("", pub.getValueAsString(), "")); + strings.add(""); + strings.addAll(Arrays.asList("", "1", "", "", "")); + strings.addAll(Arrays.asList("", "2", "", "", "")); + strings.addAll(Arrays.asList("")); + assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings)); + assertThat(bundleString, not(containsString("at:by"))); + + } + + @Test + public void testEncodeBundleCategory() { + + Bundle b = new Bundle(); + BundleEntry e = b.addEntry(); + e.setResource(new Patient()); + e.addCategory("scheme", "term", "label"); + + String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(val); + + assertThat(val, StringContains.containsString("")); + + b = ourCtx.newXmlParser().parseBundle(val); + assertEquals(1, b.getEntries().size()); + assertEquals(1, b.getEntries().get(0).getCategories().size()); + assertEquals("term", b.getEntries().get(0).getCategories().get(0).getTerm()); + assertEquals("label", b.getEntries().get(0).getCategories().get(0).getLabel()); + assertEquals("scheme", b.getEntries().get(0).getCategories().get(0).getScheme()); + assertNull(b.getEntries().get(0).getResource()); + + } + + @Test + public void testEncodeBundleResultCount() { + + Bundle b = new Bundle(); + b.getTotalResults().setValue(123); + + String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(val); + + assertThat(val, StringContains.containsString("123")); + + } + + @Test + public void testEncodeEscapedChars() { + + Patient p = new Patient(); + p.addName().addFamily("and <>&ü"); + + String enc = ourCtx.newXmlParser().encodeResourceToString(p); + ourLog.info(enc); + + p = ourCtx.newXmlParser().parseResource(Patient.class, enc); + assertEquals("and <>&ü", p.getNameFirstRep().getFamilyFirstRep().getValue()); + + p = ourCtx.newXmlParser().parseResource(Patient.class, ""); + assertEquals("quot \"", p.getNameFirstRep().getFamilyFirstRep().getValue()); + + } + + @Test + public void testEncodeEscapedExtendedChars() { + Patient p = ourCtx.newXmlParser().parseResource(Patient.class, ""); + assertEquals("uuml ü", p.getNameFirstRep().getFamilyFirstRep().getValue()); + } + + @Test + public void testEncodeContainedAndIncludedResources() { + + DiagnosticReport rpt = new DiagnosticReport(); + rpt.getName().setText("Report"); + + Specimen spm = new Specimen(); + spm.addIdentifier().setLabel("Report1ContainedSpecimen1"); + rpt.addSpecimen().setResource(spm); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String str = p.encodeResourceToString(rpt); + + ourLog.info(str); + + } + + @Test + public void testEncodeContainedResources() { + + DiagnosticReport rpt = new DiagnosticReport(); + Specimen spm = new Specimen(); + spm.addIdentifier("urn", "123"); + rpt.getText().setDiv("AAA"); + rpt.addSpecimen().setResource(spm); + + IParser p = ourCtx.newXmlParser().setPrettyPrint(true); + String str = p.encodeResourceToString(rpt); + + ourLog.info(str); + assertThat(str, StringContains.containsString("
AAA
")); + assertThat(str, StringContains.containsString("reference value=\"#")); + + int idx = str.indexOf("reference value=\"#") + "reference value=\"#".length(); + int idx2 = str.indexOf('"', idx + 1); + String id = str.substring(idx, idx2); + assertThat(str, StringContains.containsString("")); + assertThat(str, IsNot.not(StringContains.containsString(""))); + + } + + @Test + public void testEncodeDeclaredExtensionWithAddressContent() { + IParser parser = ourCtx.newXmlParser(); + + MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension(); + patient.addAddress().setUse(AddressUseEnum.HOME); + patient.setFoo(new AddressDt().addLine("line1")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("")); + + MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + AddressDt ref = actual.getFoo(); + assertEquals("line1", ref.getLineFirstRep().getValue()); + + } + + @Test + public void testEncodeDeclaredExtensionWithResourceContent() { + IParser parser = ourCtx.newXmlParser(); + + MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension(); + patient.addAddress().setUse(AddressUseEnum.HOME); + patient.setFoo(new ResourceReferenceDt("Organization/123")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("")); + + MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + ResourceReferenceDt ref = actual.getFoo(); + assertEquals("Organization/123", ref.getReference().getValue()); + + } + + @Test + public void testEncodeExtensionWithResourceContent() { + IParser parser = ourCtx.newXmlParser(); + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUseEnum.HOME); + patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt("Organization/123")); + + String val = parser.encodeResourceToString(patient); + ourLog.info(val); + assertThat(val, StringContains.containsString("")); + + Patient actual = parser.parseResource(Patient.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + List ext = actual.getUndeclaredExtensionsByUrl("urn:foo"); + assertEquals(1, ext.size()); + ResourceReferenceDt ref = (ResourceReferenceDt) ext.get(0).getValue(); + assertEquals("Organization/123", ref.getReference().getValue()); + + } + + @Test + public void testEncodeInvalidChildGoodException() { + Observation obs = new Observation(); + obs.setValue(new DecimalDt(112.22)); + + IParser p = ourCtx.newJsonParser(); + + try { + p.encodeResourceToString(obs); + } catch (DataFormatException e) { + assertThat(e.getMessage(), StringContains.containsString("DecimalDt")); + } + } + + @Test + public void testEncodeNarrativeBlockInBundle() { + Patient p = new Patient(); + p.addIdentifier("foo", "bar"); + p.getText().setStatus(NarrativeStatusEnum.GENERATED); + p.getText().setDiv("
hello
"); + + Bundle b = new Bundle(); + b.getTotalResults().setValue(123); + b.addEntry().setResource(p); + + String out = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(out); + assertThat(out, containsString("
hello
")); + + p.getText().setDiv("hello"); + out = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(out); + assertThat(out, containsString("hello")); + + } + + @Test + public void testEncodePrettyPrint() throws DataFormatException { + + Patient patient = new Patient(); + patient.getText().getDiv().setValueAsString("
\n hello
\n  LINE1\n  LINE2
\n\n\n\n
"); + patient.addName().addFamily("Family").addGiven("Given"); + + //@formatter:off + String encoded = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(patient); + ourLog.info(encoded); + /* + * Note at least one space is placed where any whitespace was, as + * it is hard to tell what whitespace had no purpose + */ + String expected = "
" + + " hello " + + "
\n  LINE1\n  LINE2
" + + "
"; + assertEquals(expected, encoded); + + encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + expected = "\n" + + " \n" + + "
\n" + + " hello \n" + + "
\n  LINE1\n  LINE2
\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
"; + //@formatter:on + + // Whitespace should be preserved and not reformatted in narrative blocks + assertEquals(expected, encoded); + + } + + @Test + public void testEncodeQuery() { + Query q = new Query(); + ExtensionDt parameter = q.addParameter(); + parameter.setUrl("http://foo").setValue(new StringDt("bar")); + + String val = ourCtx.newXmlParser().encodeResourceToString(q); + ourLog.info(val); + + assertEquals("", val); + + } + + @Test + public void testEncodeResourceRef() throws DataFormatException { + + Patient patient = new Patient(); + patient.setManagingOrganization(new ResourceReferenceDt()); + + IParser p = ourCtx.newXmlParser(); + String str = p.encodeResourceToString(patient); + assertThat(str, IsNot.not(StringContains.containsString("managingOrganization"))); + + ResourceReferenceDt ref = new ResourceReferenceDt(); + ref.setReference("Organization/123"); + ref.setDisplay("DISPLAY!"); + patient.setManagingOrganization(ref); + str = p.encodeResourceToString(patient); + assertThat(str, StringContains.containsString("")); + + Organization org = new Organization(); + org.addIdentifier().setSystem("foo").setValue("bar"); + patient.setManagingOrganization(new ResourceReferenceDt(org)); + str = p.encodeResourceToString(patient); + assertThat(str, StringContains.containsString("")); + + MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val); + assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum()); + AddressDt ref = actual.getFoo(); + assertEquals("line1", ref.getLineFirstRep().getValue()); + + } + + @Test + public void testExtensionOnComposite() throws Exception { + + Patient patient = new Patient(); + + HumanNameDt name = patient.addName(); + name.addFamily().setValue("Shmoe"); + HumanNameDt given = name.addGiven("Joe"); + ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello")); + given.addUndeclaredExtension(ext2); + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString("")); + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc)); + assertEquals(1, parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size()); + ExtensionDt ext = parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0); + assertEquals("Hello", ext.getValueAsPrimitive().getValue()); + + } + + @Test + public void testExtensionOnPrimitive() throws Exception { + + Patient patient = new Patient(); + + HumanNameDt name = patient.addName(); + StringDt family = name.addFamily(); + family.setValue("Shmoe"); + + ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("Hello")); + family.addUndeclaredExtension(ext2); + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString("")); + + Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, new StringReader(enc)); + assertEquals(1, parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size()); + ExtensionDt ext = parsed.getNameFirstRep().getFamilyFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0); + assertEquals("Hello", ext.getValueAsPrimitive().getValue()); + + } + + @Test + public void testExtensions() throws DataFormatException { + + MyPatient patient = new MyPatient(); + patient.setPetName(new StringDt("Fido")); + patient.getImportantDates().add(new DateTimeDt("2010-01-02")); + patient.getImportantDates().add(new DateTimeDt("2014-01-26T11:11:11")); + + patient.addName().addFamily("Smith"); + + IParser p = ourCtx.newXmlParser(); + String str = p.encodeResourceToString(patient); + + ourLog.info(str); + + assertThat(str, StringContains.containsString("")); + assertThat(str, StringContains.containsString("")); + assertThat(str, StringContains.containsString("")); + assertThat(str, StringContains.containsString("")); + assertThat(str, StringContains.containsString("")); + + } + + @Test + public void testLoadAndAncodeMessage() throws SAXException, IOException { + + //@formatter:off + String msg = "" + + "
John Cardinal: 444333333
" + + "" + + "" + + "" + + "" + + "" + + "
" + + "
"; + //@formatter:on + + Patient patient = ourCtx.newXmlParser().parseResource(Patient.class, msg); + + assertEquals(NarrativeStatusEnum.GENERATED, patient.getText().getStatus().getValueAsEnum()); + assertEquals("
John Cardinal: 444333333
", patient.getText().getDiv().getValueAsString()); + assertEquals("PRP1660", patient.getIdentifier().get(0).getValue().getValueAsString()); + + String encoded = ourCtx.newXmlParser().encodeResourceToString(patient); + + Diff d = new Diff(new StringReader(msg), new StringReader(encoded)); + assertTrue(d.toString(), d.identical()); + + } + + @Test + public void testLoadAndEncodeDeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException { + IParser p = new FhirContext(ResourceWithExtensionsA.class).newXmlParser(); + + //@formatter:off + String msg = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + ResourceWithExtensionsA resource = (ResourceWithExtensionsA) p.parseResource(msg); + assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel().getValue()); + assertEquals("Foo1Value", resource.getFoo1().get(0).getValue()); + assertEquals("Foo1Value2", resource.getFoo1().get(1).getValue()); + assertEquals("Foo2Value1", resource.getFoo2().getValue()); + assertEquals("2013-01-01", resource.getBar1().get(0).getBar11().get(0).getValueAsString()); + assertEquals("2013-01-02", resource.getBar1().get(0).getBar12().get(0).getBar121().get(0).getValueAsString()); + assertEquals("2013-01-12", resource.getBar1().get(0).getBar12().get(0).getBar121().get(1).getValueAsString()); + assertEquals("2013-01-03", resource.getBar1().get(0).getBar12().get(0).getBar122().get(0).getValueAsString()); + + String encoded = p.encodeResourceToString(resource); + ourLog.info(encoded); + + Diff d = new Diff(new StringReader(msg), new StringReader(encoded)); + assertTrue(d.toString(), d.identical()); + } + + @Test + public void testLoadAndEncodeUndeclaredExtensions() throws ConfigurationException, DataFormatException, SAXException, IOException { + IParser p = ourCtx.newXmlParser(); + + //@formatter:off + String msg = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + Patient resource = (Patient) p.parseResource(msg); + assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel().getValue()); + assertEquals("Foo1Value", resource.getUndeclaredExtensions().get(0).getValueAsPrimitive().getValueAsString()); + assertEquals("Foo1Value2", resource.getUndeclaredExtensions().get(1).getValueAsPrimitive().getValueAsString()); + assertEquals("Foo2Value1", resource.getUndeclaredModifierExtensions().get(0).getValueAsPrimitive().getValueAsString()); + + assertEquals("2013-01-01", resource.getUndeclaredExtensions().get(2).getUndeclaredExtensions().get(0).getValueAsPrimitive().getValueAsString()); + assertEquals("2013-01-02", resource.getUndeclaredExtensions().get(2).getUndeclaredExtensions().get(1).getUndeclaredExtensions().get(0).getValueAsPrimitive().getValueAsString()); + + String encoded = p.encodeResourceToString(resource); + ourLog.info(encoded); + + Diff d = new Diff(new StringReader(msg), new StringReader(encoded)); + assertTrue(d.toString(), d.identical()); + } + + @Test + public void testLoadObservation() throws ConfigurationException, DataFormatException, IOException { + + IParser p = ourCtx.newXmlParser(); + + String string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/observation-example-eeg.xml"), Charset.forName("UTF-8")); + IResource resource = p.parseResource(string); + + String result = p.encodeResourceToString(resource); + ourLog.info(result); + } + + @Test + public void testParseFeedWithListResource() throws ConfigurationException, DataFormatException, IOException { + + // Use new context here to ensure List isn't already loaded + IParser p = new FhirContext().newXmlParser(); + + String string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/feed-with-list.xml"), Charset.forName("UTF-8")); + Bundle bundle = p.parseBundle(string); + + ListResource res = (ListResource) bundle.toListOfResources().get(2); + assertEquals("cid:patient@bundle", res.getSubject().getReference().getValue()); + + } + + @Test + public void testLoadPatient() throws ConfigurationException, DataFormatException, IOException { + + IParser p = ourCtx.newXmlParser(); + + String string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/patient-example-dicom.xml"), Charset.forName("UTF-8")); + IResource resource = p.parseResource(string); + + String result = p.encodeResourceToString(resource); + ourLog.info(result); + + // Nothing + + string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/patient-example-us-extensions.xml"), Charset.forName("UTF-8")); + resource = p.parseResource(string); + + result = p.encodeResourceToString(resource); + ourLog.info(result); + + } + + @Test + public void testLoadQuestionnaire() throws ConfigurationException, DataFormatException, IOException { + + IParser p = ourCtx.newXmlParser(); + + String string = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/questionnaire-example.xml"), Charset.forName("UTF-8")); + IResource resource = p.parseResource(string); + + String result = p.encodeResourceToString(resource); + ourLog.info(result); + } + + @Test + public void testMessageWithMultipleTypes() throws SAXException, IOException { + + //@formatter:off + String msg = "" + + "" + + ""; + //@formatter:on + + Patient patient1 = ourCtx.newXmlParser().parseResource(Patient.class, msg); + String encoded1 = ourCtx.newXmlParser().encodeResourceToString(patient1); + + ca.uhn.fhir.testmodel.Patient patient2 = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.testmodel.Patient.class, msg); + String encoded2 = ourCtx.newXmlParser().encodeResourceToString(patient2); + + Diff d = new Diff(new StringReader(encoded1), new StringReader(encoded2)); + assertTrue(d.toString(), d.identical()); + + } + + @Test + public void testMoreExtensions() throws Exception { + + Patient patient = new Patient(); + patient.addIdentifier(IdentifierUseEnum.OFFICIAL, "urn:example", "7000135", null); + + ExtensionDt ext = new ExtensionDt(); + ext.setModifier(false); + ext.setUrl("http://example.com/extensions#someext"); + ext.setValue(new DateTimeDt("2011-01-02T11:13:15")); + + // Add the extension to the resource + patient.addUndeclaredExtension(ext); + // END SNIPPET: resourceExtension + + // START SNIPPET: resourceStringExtension + HumanNameDt name = patient.addName(); + name.addFamily().setValue("Shmoe"); + StringDt given = name.addGiven(); + given.setValue("Joe"); + ExtensionDt ext2 = new ExtensionDt(false, "http://examples.com#givenext", new StringDt("given")); + given.addUndeclaredExtension(ext2); + // END SNIPPET: resourceStringExtension + + // START SNIPPET: subExtension + ExtensionDt parent = new ExtensionDt(false, "http://example.com#parent"); + patient.addUndeclaredExtension(parent); + + ExtensionDt child1 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1")); + parent.addUndeclaredExtension(child1); + + ExtensionDt child2 = new ExtensionDt(false, "http://example.com#child", new StringDt("value1")); + parent.addUndeclaredExtension(child2); + // END SNIPPET: subExtension + + String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(output); + + String enc = ourCtx.newXmlParser().encodeResourceToString(patient); + assertThat(enc, containsString("")); + assertThat( + enc, + containsString("")); + assertThat(enc, containsString("")); + } + + @Test + public void testNarrativeGeneration() throws DataFormatException { + + Patient patient = new Patient(); + + patient.addName().addFamily("Smith"); + + INarrativeGenerator gen = mock(INarrativeGenerator.class); + XhtmlDt xhtmlDt = new XhtmlDt("
help
"); + NarrativeDt nar = new NarrativeDt(xhtmlDt, NarrativeStatusEnum.GENERATED); + when(gen.generateNarrative(eq("http://hl7.org/fhir/profiles/Patient"), eq(patient))).thenReturn(nar); + + FhirContext context = ourCtx; + context.setNarrativeGenerator(gen); + IParser p = context.newXmlParser(); + String str = p.encodeResourceToString(patient); + + ourLog.info(str); + + assertThat(str, StringContains.containsString("")); + assertThat(str, StringContains.containsString("")); + } + + @Test + public void testDuplicateContainedResources() { + + Observation resA = new Observation(); + resA.getName().setText("A"); + + Observation resB = new Observation(); + resB.getName().setText("B"); + resB.addRelated().setTarget(new ResourceReferenceDt(resA)); + resB.addRelated().setTarget(new ResourceReferenceDt(resA)); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(resB); + ourLog.info(encoded); + + assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", "", "")))); + + } + + @Test + public void testNestedContainedResources() { + + Observation A = new Observation(); + A.getName().setText("A"); + + Observation B = new Observation(); + B.getName().setText("B"); + A.addRelated().setTarget(new ResourceReferenceDt(B)); + + Observation C = new Observation(); + C.getName().setText("C"); + B.addRelated().setTarget(new ResourceReferenceDt(C)); + + String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(A); + ourLog.info(str); + + assertThat(str, stringContainsInOrder(Arrays.asList("", "", ""))); + assertThat(str, stringContainsInOrder(Arrays.asList("", ""))); + + // Only one (outer) contained block + int idx0 = str.indexOf(""); + int idx1 = str.indexOf("", idx0 + 1); + assertNotEquals(-1, idx0); + assertEquals(-1, idx1); + + Observation obs = ourCtx.newXmlParser().parseResource(Observation.class, str); + assertEquals("A", obs.getName().getText().getValue()); + + Observation obsB = (Observation) obs.getRelatedFirstRep().getTarget().getResource(); + assertEquals("B", obsB.getName().getText().getValue()); + + Observation obsC = (Observation) obsB.getRelatedFirstRep().getTarget().getResource(); + assertEquals("C", obsC.getName().getText().getValue()); + + } + + @Test + public void testParseBinaryResource() { + + Binary val = ourCtx.newXmlParser().parseResource(Binary.class, "AQIDBA=="); + assertEquals("foo", val.getContentType()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, val.getContent()); + + } + + @SuppressWarnings("deprecation") + @Test + public void testParseBundle() { + + //@formatter:off + String summaryText = + "
\n" + + "

Value set \"LOINC Codes for Cholesterol\": This is an example value set that includes \n" + + " all the LOINC codes for serum cholesterol from v2.36. \n" + + " Developed by: FHIR project team (example)

"; + + String msg = "\n" + + " FHIR Core Valuesets\n" + + " http://hl7.org/fhir/profile/valuesets\n" + + " \n" + + " \n" + + " 2014-02-10T04:11:24.435-00:00\n" + + " \n" + + " Valueset "256a5231-a2bb-49bd-9fea-f349d428b70d" to support automated processing\n" + + " http://hl7.org/fhir/valueset/256a5231-a2bb-49bd-9fea-f349d428b70d\n" + + " \n" + + " \n" + + " \n" + + " 2014-02-10T04:10:46.987-00:00\n" + + " \n" + + " HL7, Inc (FHIR Project)\n" + + " http://hl7.org/fhir\n" + + " \n" + + " 2014-02-10T04:10:46.987-00:00\n" + + " \n "+ + " \n" + + " \n" + + " \n" + + " " + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " "+ + summaryText + + " \n" + + " " + + ""; + //@formatter:on + + IParser p = new FhirContext(ValueSet.class).newXmlParser(); + Bundle bundle = p.parseBundle(msg); + + assertEquals(1, bundle.getCategories().size()); + assertEquals("http://hl7.org/fhir/tag", bundle.getCategories().get(0).getScheme()); + + assertEquals("FHIR Core Valuesets", bundle.getTitle().getValue()); + assertEquals("http://hl7.org/implement/standards/fhir/valuesets.xml", bundle.getLinkSelf().getValue()); + assertEquals("2014-02-10T04:11:24.435-00:00", bundle.getUpdated().getValueAsString()); + assertEquals(1, bundle.getEntries().size()); + + BundleEntry entry = bundle.getEntries().get(0); + assertEquals("HL7, Inc (FHIR Project)", entry.getAuthorName().getValue()); + assertEquals("http://hl7.org/fhir/valueset/256a5231-a2bb-49bd-9fea-f349d428b70d", entry.getId().getValue()); + assertEquals("http://hl7.org/foo", entry.getLinkAlternate().getValue()); + assertEquals("http://hl7.org/foo/search", entry.getLinkSearch().getValue()); + assertEquals(1, entry.getCategories().size()); + assertEquals("term", entry.getCategories().get(0).getTerm()); + assertEquals("label", entry.getCategories().get(0).getLabel()); + assertEquals("http://foo", entry.getCategories().get(0).getScheme()); + + ValueSet resource = (ValueSet) entry.getResource(); + assertEquals("LOINC Codes for Cholesterol", resource.getName().getValue()); + + String exp = summaryText.trim(); + exp = exp.replace("\"LOINC", ""LOINC"); + exp = exp.replace("terol\"", "terol""); + assertEquals(exp, entry.getSummary().getValueAsString().trim()); + + TagList tl = (TagList) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST); + assertEquals(1, tl.size()); + assertEquals("term", tl.get(0).getTerm()); + assertEquals("label", tl.get(0).getLabel()); + assertEquals("http://foo", tl.get(0).getScheme()); + + assertEquals("256a5231-a2bb-49bd-9fea-f349d428b70d", resource.getId().getIdPart()); + + msg = msg.replace("", + ""); + entry = p.parseBundle(msg).getEntries().get(0); + resource = (ValueSet) entry.getResource(); + assertEquals("256a5231-a2bb-49bd-9fea-f349d428b70d", resource.getId().getIdPart()); + assertEquals("12345", resource.getId().getVersionIdPart()); + assertEquals("12345", ((IdDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION_ID)).getVersionIdPart()); + + assertThat(entry.getSummary().getValueAsString(), containsString("LOINC Codes for Cholesterol")); + + } + + @SuppressWarnings("deprecation") + @Test + public void testParseBundleDeletedEntry() { + + //@formatter:off + String msg = "" + + "FHIR Core Valuesets" + + "http://hl7.org/fhir/profile/valuesets" + + "" + + "2014-02-10T04:11:24.435+00:00" + + "" + + "" + + "John Doe" + + "jdoe@example.org" + + "" + + "Removed comment spam" + + "" + + "" + + ""; + //@formatter:on + + IParser p = ourCtx.newXmlParser(); + Bundle bundle = p.parseBundle(msg); + + BundleEntry entry = bundle.getEntries().get(0); + assertEquals("http://foo/Patient/1", entry.getId().getValue()); + assertEquals("2013-02-10T04:11:24.435+00:00", entry.getDeletedAt().getValueAsString()); + assertEquals("http://foo/Patient/1/_history/2", entry.getLinkSelf().getValue()); + assertEquals("1", entry.getResource().getId().getIdPart()); + assertEquals("2", entry.getResource().getId().getVersionIdPart()); + assertEquals("2", ((IdDt) entry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.VERSION_ID)).getVersionIdPart()); + assertEquals("John Doe", entry.getDeletedByName().getValue()); + assertEquals("jdoe@example.org", entry.getDeletedByEmail().getValue()); + assertEquals("Removed comment spam", entry.getDeletedComment().getValue()); + assertEquals(new InstantDt("2013-02-10T04:11:24.435+00:00"), entry.getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.DELETED_AT)); + + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle)); + + String encoded = ourCtx.newXmlParser().encodeBundleToString(bundle); + assertEquals(msg, encoded); + + } + + @Test + public void testParseBundleLarge() throws IOException { + + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/atom-document-large.xml")); + IParser p = ourCtx.newXmlParser(); + Bundle bundle = p.parseBundle(msg); + + assertEquals("http://spark.furore.com/fhir/_snapshot?id=327d6bb9-83b0-4929-aa91-6dd9c41e587b&start=0&_count=20", bundle.getLinkSelf().getValue()); + assertEquals("Patient resource with id 3216379", bundle.getEntries().get(0).getTitle().getValue()); + assertEquals("http://spark.furore.com/fhir/Patient/3216379", bundle.getEntries().get(0).getId().getValue()); + assertEquals("3216379", bundle.getEntries().get(0).getResource().getId().getIdPart()); + + } + + @Test + public void testParseBundleWithMixedReturnTypes() { + InputStreamReader str = new InputStreamReader(getClass().getResourceAsStream("/mixed-return-bundle.xml")); + Bundle b = ourCtx.newXmlParser().parseBundle(Patient.class, str); + assertEquals(Patient.class, b.getEntries().get(0).getResource().getClass()); + assertEquals(Patient.class, b.getEntries().get(1).getResource().getClass()); + assertEquals(Organization.class, b.getEntries().get(2).getResource().getClass()); + } + + @Test + public void testParseContainedResources() throws IOException { + + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/contained-diagnosticreport.xml")); + IParser p = ourCtx.newXmlParser(); + DiagnosticReport bundle = p.parseResource(DiagnosticReport.class, msg); + + ResourceReferenceDt result0 = bundle.getResult().get(0); + Observation obs = (Observation) result0.getResource(); + + assertNotNull(obs); + assertEquals("718-7", obs.getName().getCoding().get(0).getCode().getValue()); + + } + + @Test + public void testParseEncodeNarrative() { + + String input = "
Donald null DUCK
Identifier7000135
Address10 Duxon Street
VICTORIA BC Can
Date of birth01 June 1980
"; + IResource res = ourCtx.newXmlParser().parseResource(input); + + String output = ourCtx.newXmlParser().encodeResourceToString(res); + + // Should occur exactly twice (once for the resource, once for the DIV + assertThat(output, (StringContainsInOrder.stringContainsInOrder(Arrays.asList("Patient xmlns", "div xmlns")))); + assertThat(output, not(StringContainsInOrder.stringContainsInOrder(Arrays.asList("b xmlns")))); + + output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); + + // Should occur exactly twice (once for the resource, once for the DIV + assertThat(output, (StringContainsInOrder.stringContainsInOrder(Arrays.asList("Patient xmlns", "div xmlns")))); + assertThat(output, not(StringContainsInOrder.stringContainsInOrder(Arrays.asList("b xmlns")))); + + } + + /** + * This sample has extra elements in that are not actually a part of the spec any more.. + */ + @Test + public void testParseFuroreMetadataWithExtraElements() throws IOException { + String msg = IOUtils.toString(XmlParserTest.class.getResourceAsStream("/furore-conformance.xml")); + + IParser p = new FhirContext(ValueSet.class).newXmlParser(); + Conformance conf = p.parseResource(Conformance.class, msg); + RestResource res = conf.getRestFirstRep().getResourceFirstRep(); + assertEquals("_id", res.getSearchParam().get(1).getName().getValue()); + } + + @Test + public void testParseLanguage() { + String input = "
海生
IdentifierURNo
Address99 Houston Road
BENTLEIGH Victoria
Date of birth01 January 1997
"; + Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input); + + assertEquals("zh-CN", pt.getLanguage().getValue()); + } + + @Test + public void testParseQuery() { + String msg = "\n" + " \n" + " \n" + "
[Put rendering here]
\n" + + "
\n" + "\n" + " \n" + + " \n" + " \n" + " \n" + + " \n" + "
"; + Query query = ourCtx.newXmlParser().parseResource(Query.class, msg); + + assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString()); + assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString()); + assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString()); + + } + + @Test + public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException { + IParser p = ourCtx.newXmlParser(); + + //@formatter:off + String msg = "" + + "\n" + + " \n" + + " \n" + + ""; + //@formatter:on + + Patient resource = (Patient) p.parseResource(msg); + assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getLabel().getValue()); + } + + @Test + public void testSimpleResourceEncode() throws IOException, SAXException { + + String xmlString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.json"), Charset.forName("UTF-8")); + Patient obs = ourCtx.newJsonParser().parseResource(Patient.class, xmlString); + + List undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions(); + ExtensionDt undeclaredExtension = undeclaredExtensions.get(0); + assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue()); + + ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out)); + + IParser jsonParser = ourCtx.newXmlParser(); + String encoded = jsonParser.encodeResourceToString(obs); + ourLog.info(encoded); + + String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.xml"), Charset.forName("UTF-8")); + + String expected = (jsonString); + String actual = (encoded.trim()); + + Diff d = new Diff(new StringReader(expected), new StringReader(actual)); + assertTrue(d.toString(), d.identical()); + + } + + @Test + public void testSimpleResourceEncodeWithCustomType() throws IOException, SAXException { + + FhirContext fhirCtx = new FhirContext(MyObservationWithExtensions.class); + String xmlString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.json"), Charset.forName("UTF-8")); + MyObservationWithExtensions obs = fhirCtx.newJsonParser().parseResource(MyObservationWithExtensions.class, xmlString); + + assertEquals(0, obs.getAllUndeclaredExtensions().size()); + assertEquals("aaaa", obs.getExtAtt().getContentType().getValue()); + assertEquals("str1", obs.getMoreExt().getStr1().getValue()); + assertEquals("2011-01-02", obs.getModExt().getValueAsString()); + + List undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions(); + ExtensionDt undeclaredExtension = undeclaredExtensions.get(0); + assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue()); + + fhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out)); + + IParser jsonParser = fhirCtx.newXmlParser(); + String encoded = jsonParser.encodeResourceToString(obs); + ourLog.info(encoded); + + String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.xml"), Charset.forName("UTF-8")); + + String expected = (jsonString); + String actual = (encoded.trim()); + + Diff d = new Diff(new StringReader(expected), new StringReader(actual)); + assertTrue(d.toString(), d.identical()); + + } + + @Test + public void testTagList() { + + //@formatter:off + String tagListStr = " \n" + + " \n" + + " \n" + + " \n" + + ""; + //@formatter:on + + TagList tagList = ourCtx.newXmlParser().parseTagList(tagListStr); + assertEquals(3, tagList.size()); + assertEquals("term0", tagList.get(0).getTerm()); + assertEquals("label0", tagList.get(0).getLabel()); + assertEquals("scheme0", tagList.get(0).getScheme()); + assertEquals("term1", tagList.get(1).getTerm()); + assertEquals("label1", tagList.get(1).getLabel()); + assertEquals(null, tagList.get(1).getScheme()); + assertEquals("term2", tagList.get(2).getTerm()); + assertEquals("label2", tagList.get(2).getLabel()); + assertEquals(null, tagList.get(2).getScheme()); + + /* + * Encode + */ + + //@formatter:off + String expected = "" + + "" + + "" + + "" + + ""; + //@formatter:on + + String encoded = ourCtx.newXmlParser().encodeTagListToString(tagList); + assertEquals(expected, encoded); + + } + + @Test + public void testTotalResultsUsingOldNamespace() { + + //@formatter:off + String bundle = "\n" + + " Search results for Patient\n" + + " urn:uuid:374f2876-0da7-4441-87da-526e2fc624f8\n" + + " 15\n" + + " 2014-05-04T13:19:47.027-04:00\n" + + " \n" + + " AEGIS Wildfhir Server\n" + + " " + + ""; + //@formatter:off + + Bundle bundleR = ourCtx.newXmlParser().parseBundle(bundle); + assertEquals(15, bundleR.getTotalResults().getValue().intValue()); + } + + @BeforeClass + public static void beforeClass() { + XMLUnit.setIgnoreAttributeOrder(true); + XMLUnit.setIgnoreComments(true); + XMLUnit.setIgnoreWhitespace(true); + ourCtx = new FhirContext(); + } + +}