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.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.*; import org.apache.commons.io.IOUtils; import org.hamcrest.core.IsNot; import org.hamcrest.core.StringContains; import org.hamcrest.text.StringContainsInOrder; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.INarrative; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.mockito.ArgumentCaptor; 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.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.Location; 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.Questionnaire; import ca.uhn.fhir.model.dstu.resource.Remittance; 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.IdentifierUseEnum; import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum; import ca.uhn.fhir.model.primitive.CodeDt; import ca.uhn.fhir.model.primitive.DateDt; import ca.uhn.fhir.model.primitive.DateTimeDt; 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; import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation; import ca.uhn.fhir.parser.json.JsonLikeValue; import ca.uhn.fhir.parser.json.JsonLikeValue.ScalarType; import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType; import ca.uhn.fhir.util.TestUtil; import net.sf.json.JSON; import net.sf.json.JSONSerializer; public class JsonParserTest { private static FhirContext ourCtx; private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserTest.class); private void parseAndEncode(String name) throws IOException { String msg = IOUtils.toString(XmlParser.class.getResourceAsStream(name), StandardCharsets.UTF_8); // ourLog.info(msg); msg = msg.replace("\"div\": \"<div>", "\"div\":\"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">"); 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 testDecimalPrecisionPreserved() { String number = "52.3779939997090374535378485873776474764643249869328698436986235758587"; Location loc = new Location(); // This is far more precision than is realistic, but let's see if we preserve it loc.getPosition().setLatitude(new DecimalDt(number)); String encoded = ourCtx.newJsonParser().encodeResourceToString(loc); Location parsed = ourCtx.newJsonParser().parseResource(Location.class, encoded); assertEquals(number, parsed.getPosition().getLatitude().getValueAsString()); } @Test public void testDecimalPrecisionPreservedInResource() { Remittance obs = new Remittance(); obs.addService().setRate(new DecimalDt("0.10000")); String output = ourCtx.newJsonParser().encodeResourceToString(obs); ourLog.info(output); assertEquals("{\"resourceType\":\"Remittance\",\"service\":[{\"rate\":0.10000}]}", output); obs = ourCtx.newJsonParser().parseResource(Remittance.class, output); assertEquals("0.10000", obs.getService().get(0).getRate().getValueAsString()); } @Test public void testParseStringWithNewlineUnencoded() { Observation obs = new Observation(); obs.setValue(new StringDt("line1\\nline2")); String output = ourCtx.newJsonParser().encodeResourceToString(obs); ourLog.info(output); assertEquals("{\"resourceType\":\"Observation\",\"valueString\":\"line1\\\\nline2\"}", output); obs = ourCtx.newJsonParser().parseResource(Observation.class, output); assertEquals("line1\\nline2", ((StringDt)obs.getValue()).getValue()); } @Test public void testParseStringWithNewlineEncoded() { Observation obs = new Observation(); obs.setValue(new StringDt("line1\nline2")); String output = ourCtx.newJsonParser().encodeResourceToString(obs); ourLog.info(output); assertEquals("{\"resourceType\":\"Observation\",\"valueString\":\"line1\\nline2\"}", output); obs = ourCtx.newJsonParser().parseResource(Observation.class, output); assertEquals("line1\nline2", ((StringDt)obs.getValue()).getValue()); } @Test public void testEncodeAndParseExtensions() throws Exception { Patient patient = new Patient(); patient.addIdentifier().setUse(IdentifierUseEnum.OFFICIAL).setSystem("urn:example").setValue("7000135"); ExtensionDt ext = new ExtensionDt(); ext.setUrl("http://example.com/extensions#someext"); ext.setValue(new DateTimeDt("2011-01-02T11:13:15")); patient.addUndeclaredExtension(ext); ExtensionDt parent = new ExtensionDt().setUrl("http://example.com#parent"); patient.addUndeclaredExtension(parent); ExtensionDt child1 = new ExtensionDt().setUrl("http://example.com#child").setValue(new StringDt("value1")); parent.addUndeclaredExtension(child1); ExtensionDt child2 = new ExtensionDt().setUrl("http://example.com#child").setValue(new StringDt("value2")); parent.addUndeclaredExtension(child2); ExtensionDt modExt = new ExtensionDt(); modExt.setUrl("http://example.com/extensions#modext"); modExt.setValue(new DateDt("1995-01-02")); modExt.setModifier(true); patient.addUndeclaredExtension(modExt); HumanNameDt name = patient.addName(); name.addFamily("Blah"); StringDt given = name.addGiven(); given.setValue("Joe"); ExtensionDt ext2 = new ExtensionDt().setUrl("http://examples.com#givenext").setValue(new StringDt("given")); given.addUndeclaredExtension(ext2); StringDt given2 = name.addGiven(); given2.setValue("Shmoe"); ExtensionDt given2ext = new ExtensionDt().setUrl("http://examples.com#givenext_parent"); given2.addUndeclaredExtension(given2ext); given2ext.addUndeclaredExtension(new ExtensionDt().setUrl("http://examples.com#givenext_child").setValue(new StringDt("CHILD"))); String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); ourLog.info(output); String enc = ourCtx.newJsonParser().encodeResourceToString(patient); assertThat(enc, org.hamcrest.Matchers.stringContainsInOrder("{\"resourceType\":\"Patient\",", "\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}", "{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}")); assertThat(enc, org.hamcrest.Matchers.stringContainsInOrder("\"modifierExtension\":[" + "{" + "\"url\":\"http://example.com/extensions#modext\"," + "\"valueDate\":\"1995-01-02\"" + "}" + "],")); assertThat(enc, containsString("\"_given\":[" + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext\"," + "\"valueString\":\"given\"" + "}" + "]" + "}," + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_parent\"," + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_child\"," + "\"valueString\":\"CHILD\"" + "}" + "]" + "}" + "]" + "}")); /* * Now parse this back */ Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc); ext = parsed.getUndeclaredExtensions().get(0); assertEquals("http://example.com/extensions#someext", ext.getUrl()); assertEquals("2011-01-02T11:13:15", ((DateTimeDt) ext.getValue()).getValueAsString()); parent = patient.getUndeclaredExtensions().get(1); assertEquals("http://example.com#parent", parent.getUrl()); assertNull(parent.getValue()); child1 = parent.getExtension().get(0); assertEquals("http://example.com#child", child1.getUrl()); assertEquals("value1", ((StringDt) child1.getValue()).getValueAsString()); child2 = parent.getExtension().get(1); assertEquals("http://example.com#child", child2.getUrl()); assertEquals("value2", ((StringDt) child2.getValue()).getValueAsString()); modExt = parsed.getUndeclaredModifierExtensions().get(0); assertEquals("http://example.com/extensions#modext", modExt.getUrl()); assertEquals("1995-01-02", ((DateDt) modExt.getValue()).getValueAsString()); name = parsed.getName().get(0); ext2 = name.getGiven().get(0).getUndeclaredExtensions().get(0); assertEquals("http://examples.com#givenext", ext2.getUrl()); assertEquals("given", ((StringDt) ext2.getValue()).getValueAsString()); given2ext = name.getGiven().get(1).getUndeclaredExtensions().get(0); assertEquals("http://examples.com#givenext_parent", given2ext.getUrl()); assertNull(given2ext.getValue()); ExtensionDt given2ext2 = given2ext.getExtension().get(0); assertEquals("http://examples.com#givenext_child", given2ext2.getUrl()); assertEquals("CHILD", ((StringDt) given2ext2.getValue()).getValue()); } @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 testEncodeBundle() throws InterruptedException { Bundle b = new Bundle(); InstantDt pub = InstantDt.withCurrentTime(); 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<String> strings = new ArrayList<String>(); 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 testEncodeBundleCategory() { Bundle b = new Bundle(); BundleEntry e = b.addEntry(); e.setResource(new Patient()); b.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\"}]")); assertThat(val, not(containsString("text"))); b = ourCtx.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() { 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<IResource> resources = new ArrayList<IResource>(); 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 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<IResource> resources = new ArrayList<IResource>(); 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 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 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("<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">AAA</div>")); 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("<?xml version='1.0'?>"))); } @Test public void testEncodeContainedWithNarrativeIsSuppresed() { IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); // Create an organization, note that the organization does not have an ID Organization org = new Organization(); org.getName().setValue("Contained Test Organization"); org.getText().setDiv("<div>FOOBAR</div>"); // Create a patient Patient patient = new Patient(); patient.setId("Patient/1333"); patient.addIdentifier("urn:mrns", "253345"); patient.getText().setDiv("<div>BARFOO</div>"); patient.getManagingOrganization().setResource(org); String encoded = parser.encodeResourceToString(patient); ourLog.info(encoded); assertThat(encoded, not(containsString("FOOBAR"))); assertThat(encoded, (containsString("BARFOO"))); } @Test public void testEncodeDeclaredExtensionWithAddressContent() { IParser parser = ourCtx.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 = ourCtx.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 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")); IParser parser = ourCtx.newJsonParser(); String encoded = parser.encodeResourceToString(valueSet); ourLog.info(encoded); assertThat(encoded, not(containsString("123456"))); String expected = "{\"resourceType\":\"ValueSet\",\"define\":{\"concept\":[{\"extension\":[{\"url\":\"urn:alt\",\"valueString\":\"alt name\"}],\"code\":\"someCode\",\"display\":\"someDisplay\"}]}}"; ourLog.info("Expected: {}", expected); ourLog.info("Actual : {}", encoded); assertEquals(expected, encoded); } @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); IParser setPrettyPrint = ourCtx.newJsonParser().setPrettyPrint(false); encoded = setPrettyPrint.encodeResourceToString(c); String expected = "{\"resourceType\":\"Conformance\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"; ourLog.info("Expected: {}", expected); ourLog.info("Actual : {}", encoded); assertEquals(expected, encoded); } @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 testEncodeExtensionWithResourceContent() { IParser parser = ourCtx.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<ExtensionDt> 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 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()); } @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 testEncodeNarrativeBlockInBundle() { Patient p = new Patient(); p.addIdentifier("foo", "bar"); p.getText().setStatus(NarrativeStatusEnum.GENERATED); p.getText().setDiv("<div>hello</div>"); 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("<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">hello</div>")); p.getText().setDiv("<xhtml:div xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">hello</xhtml:div>"); 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("<xhtml:div xmlns:xhtml=\\\"http://www.w3.org/1999/xhtml\\\">hello</xhtml:div>")); } @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 testEncodeOmitsVersionAndBase() { Patient p = new Patient(); p.getManagingOrganization().setReference("http://example.com/base/Patient/1/_history/2"); String enc; enc = ourCtx.newJsonParser().encodeResourceToString(p); ourLog.info(enc); assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); enc = ourCtx.newJsonParser().setServerBaseUrl("http://example.com/base").encodeResourceToString(p); ourLog.info(enc); assertThat(enc, containsString("\"Patient/1\"")); enc = ourCtx.newJsonParser().setServerBaseUrl("http://example.com/base2").encodeResourceToString(p); ourLog.info(enc); assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); } @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 = ourCtx.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 testEncodeResourceRef() throws DataFormatException { Patient patient = new Patient(); patient.setManagingOrganization(new ResourceReferenceDt()); IParser p = ourCtx.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 = ourCtx.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 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 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 = ourCtx.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 = ourCtx.newJsonParser(); StringReader reader = new StringReader(enc); Patient parsed = newJsonParser.parseResource(Patient.class, reader); ourLog.info(ourCtx.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 = ourCtx.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 = ourCtx.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()); } /** * #65 */ @Test public void testJsonPrimitiveWithExtensionEncoding() { String res = "{\"resourceType\":\"Questionnaire\",\"status\":\"draft\",\"authored\":\"2014-10-30T14:15:00\",\"subject\":{\"reference\":\"http://www.hl7.org/fhir/Patient/1\"},\"author\":{\"reference\":\"http://www.hl7.org/fhir/Practitioner/1\"},\"name\":{\"text\":\"WDHB Friends and Family Test\"},\"group\":{\"header\":\"Note: This is an anonymous survey, which means you cannot be identified.\",\"_header\":[{\"extension\":[{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#language\",\"valueCode\":\"en\"},{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#string-translation\",\"valueString\":\"è«\\u008b注æ\\u0084\\u008fï¼\\u009aè¿\\u0099æ\\u0098¯ä¸\\u0080个å\\u008c¿å\\u0090\\u008dè°\\u0083æ\\u009f¥ï¼\\u008c被è°\\u0083æ\\u009f¥äººå°\\u0086ä¸\\u008dä¼\\u009a被è¯\\u0086å\\u0088«å\\u0087ºæ\\u009d¥ã\\u0080\\u0082\"},{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#string-translation\",\"valueString\":\"ì\\u009dµëª\\u0085ì\\u009c¼ë¡\\u009c í\\u0095\\u0098ë\\u008a\\u0094 ì\\u0084¤ë¬¸ì¡°ì\\u0082¬ì\\u009d´ë¯\\u0080ë¡\\u009c ì\\u009e\\u0091ì\\u0084±ì\\u009e\\u0090ê°\\u0080 ë\\u0088\\u0084구ì\\u009d¸ì§\\u0080 ë°\\u009dí\\u0098\\u0080ì§\\u0080ì§\\u0080 ì\\u0095\\u008aì\\u008aµë\\u008b\\u0088ë\\u008b¤.\"}]}],\"question\":[{\"extension\":[{\"url\":\"http://hl7.org/fhir/questionnaire-extensions#answerFormat\",\"valueCode\":\"single-choice\"}],\"text\":\"Are you a patient?\",\"options\":{\"reference\":\"#question1\"}}]}}"; Questionnaire parsed = ourCtx.newJsonParser().parseResource(Questionnaire.class, res); assertEquals("Note: This is an anonymous survey, which means you cannot be identified.", parsed.getGroup().getHeader().getValue()); assertEquals(1, parsed.getGroup().getHeader().getUndeclaredExtensionsByUrl("http://hl7.org/fhir/Profile/iso-21090#language").size()); String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed); ourLog.info(encoded); assertThat(encoded, containsString("\"_header\": {")); } @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 = new INarrativeGenerator() { @Override public void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative) { try { theNarrative.setDivAsString("<div>help</div>"); } catch (Exception e) { throw new Error(e); } theNarrative.setStatusAsString("generated"); } }; FhirContext context = ourCtx; 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\":\"<div xmlns=\\\"http://www.w3.org/1999/xhtml\\\">help</div>\"},")); } @Before public void before() { ourCtx.setNarrativeGenerator(null); } @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 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 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 testTotalResultsInJsonBundle() { String json = "{" + " \"resourceType\" : \"Bundle\"," + " \"title\" : \"FHIR Atom Feed\"," + " \"id\" : \"cb095f55-afb0-41e8-89d5-155259b2a032\"," + " \"updated\" : \"2015-09-01T08:52:02.793-04:00\"," + " \"author\": [" + " {" + " \"name\": \"author-name\", " + " \"uri\": \"uri\" " + " }" + " ]," + " \"link\" : [{" + " \"rel\" : \"self\"," + " \"href\" : \"http://fhirtest.uhn.ca/baseDstu1/Patient/_search?family=Perez\"" + " }, {" + " \"rel\" : \"next\"," + " \"href\" : \"http://fhirtest.uhn.ca/baseDstu1?_getpages=c1db1094-cc46-49f1-ae69-4763ba52458b&_getpagesoffset=10&_count=10&_format=json&_pretty=true\"" + " }, {" + " \"rel\" : \"fhir-base\"," + " \"href\" : \"http://fhirtest.uhn.ca/baseDstu1\"" + " }" + " ]," + " \"totalResults\" : \"1\"," + " \"entry\" : [{" + " \"title\" : \"GONZALO PEREZ (DNI20425239)\"," + " \"id\" : \"http://fhirtest.uhn.ca/baseDstu1/Patient/34834\"," + " \"link\" : [{" + " \"rel\" : \"self\"," + " \"href\" : \"http://fhirtest.uhn.ca/baseDstu1/Patient/34834/_history/1\"" + " }" + " ]," + " \"updated\" : \"2015-06-10T10:39:38.712-04:00\"," + " \"published\" : \"2015-06-10T10:39:38.665-04:00\"," + " \"content\" : {" + " \"resourceType\" : \"Patient\"," + " \"name\" : [{" + " \"family\" : [" + " \"PEREZ\"" + " ]," + " \"given\" : [" + " \"GONZALO\"" + " ]" + " }" + " ]" + " }" + " }" + " ]" + "}"; IParser jsonParser = ourCtx.newJsonParser(); Bundle bundle = jsonParser.parseBundle(json); assertEquals("author-name", bundle.getAuthorName().getValue()); assertEquals("uri", bundle.getAuthorUri().getValue()); } @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 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()); } @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\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\"\n" + " }" + "}"; //@formatter:on Patient res = (Patient) ourCtx.newJsonParser().parseResource(text); XhtmlDt div = res.getText().getDiv(); String value = div.getValueAsString(); assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", value); assertEquals(null, div.getValue()); } /** * This sample has extra elements in <searchParam> 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 testParseJsonProfile() throws IOException { parseAndEncode("/patient.profile.json"); parseAndEncode("/alert.profile.json"); } @Test public void testParseQuery() { String msg = "{\n" + " \"resourceType\": \"Query\",\n" + " \"text\": {\n" + " \"status\": \"generated\",\n" + " \"div\": \"<div>[Put rendering here]</div>\"\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 testParseSingleQuotes() { assertEquals("1", ourCtx.newJsonParser().parseBundle("{ 'resourceType': 'Bundle', 'id':'1' }").getBundleId().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()); } /** * HAPI FHIR < 0.6 incorrectly used "resource" instead of "reference" */ @Test @Ignore 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()); } @SuppressWarnings("unused") @Test public void testParseWithIncorrectResourceType() { String input = "{\"resourceType\":\"Patient\"}"; try { IParser parser = ourCtx.newJsonParser(); Organization o = parser.parseResource(Organization.class, input); fail(); } catch (DataFormatException e) { assertThat(e.getMessage(), containsString("expected \"Organization\" but found \"Patient\"")); } } @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")); IParser parser = ourCtx.newXmlParser(); parser.setParserErrorHandler(new StrictErrorHandler()); Patient obs = parser.parseResource(Patient.class, xmlString); List<ExtensionDt> 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()); assertEquals("VV", ((CodeDt)undeclaredExtension.getValue()).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("\nExpected: " + exp + "\nActual : " + act, exp, act); } @Test public void testSimpleResourceEncodeWithCustomType() throws IOException { FhirContext fhirCtx = new FhirContext(MyPatientWithExtensions.class); String xmlString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.xml"), Charset.forName("UTF-8")); MyPatientWithExtensions obs = fhirCtx.newXmlParser().parseResource(MyPatientWithExtensions.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<ExtensionDt> 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()); 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("\nExpected: " + exp + "\nActual : " + act, exp, act); } @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 = ourCtx.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 = ourCtx.newJsonParser().encodeTagListToString(tagList); assertEquals(expected, encoded); } @Test public void testCustomUrlExtension() { final String expected = "{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://www.example.com/petname\",\"valueString\":\"myName\"}]}"; final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); patient.setPetName(new StringDt("myName")); final IParser jsonParser = ourCtx.newJsonParser(); jsonParser.setServerBaseUrl("http://www.example.com"); final String parsedPatient = jsonParser.encodeResourceToString(patient); System.out.println(parsedPatient); assertEquals(expected, parsedPatient); // Parse with string MyPatientWithCustomUrlExtension newPatient = jsonParser.parseResource(MyPatientWithCustomUrlExtension.class, parsedPatient); assertEquals("myName", newPatient.getPetName().getValue()); // Parse with stream newPatient = jsonParser.parseResource(MyPatientWithCustomUrlExtension.class, new StringReader(parsedPatient)); assertEquals("myName", newPatient.getPetName().getValue()); //Check no NPE if base server not configure newPatient = ourCtx.newJsonParser().parseResource(MyPatientWithCustomUrlExtension.class, new StringReader(parsedPatient)); assertNull("myName", newPatient.getPetName()); assertEquals("myName", ((StringDt) newPatient.getUndeclaredExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); } @Test public void testCustomUrlExtensioninBundle() { final String expected = "{\"resourceType\":\"Bundle\",\"entry\":[{\"id\":null,\"content\":{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://www.example.com/petname\",\"valueString\":\"myName\"}]}}]}"; final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); patient.setPetName(new StringDt("myName")); final Bundle bundle = new Bundle(); final BundleEntry entry = new BundleEntry(); entry.setResource(patient); bundle.addEntry(entry); final IParser jsonParser = ourCtx.newJsonParser(); jsonParser.setServerBaseUrl("http://www.example.com"); final String parsedBundle = jsonParser.encodeBundleToString(bundle); System.out.println(parsedBundle); assertEquals(expected, parsedBundle); // Parse with string Bundle newBundle = jsonParser.parseBundle(parsedBundle); assertNotNull(newBundle); assertEquals(1, newBundle.getEntries().size()); Patient newPatient = (Patient) newBundle.getEntries().get(0).getResource(); assertEquals("myName", ((StringDt) newPatient.getUndeclaredExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); // Parse with stream newBundle = jsonParser.parseBundle(new StringReader(parsedBundle)); assertNotNull(newBundle); assertEquals(1, newBundle.getEntries().size()); newPatient = (Patient) newBundle.getEntries().get(0).getResource(); assertEquals("myName", ((StringDt) newPatient.getUndeclaredExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue()); } @BeforeClass public static void beforeClass() { ourCtx = FhirContext.forDstu1(); } @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; } } @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); } }