From 66ebfa0ed306fa2e4e5f6987cd037ae086243745 Mon Sep 17 00:00:00 2001
From: jpoth A selection of Education Levels Generated Narrative with Details id: 180f219f-97a8-486d-99d9-ed631fe4fc57 meta: date: Feb 1, 2013 12:30:02 PM type: Discharge Summary from Responsible Clinician (Details : {LOINC code '28655-9' = 'Physician attending Discharge summary) status: final confidentiality: N author: Doctor Dave. Generated Summary: 23; Adam Careful encounter: http://fhir.healthintersections.com.au/open/Encounter/doc-example Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321 A P TAGEducation Levels
http://csiro.au/ValueSet/education-levels",
+ "
",
+ "
",
+ "
",
+ "
",
+ "
",
+ "
",
+ "
", "
", "", "
", "
", "", "
", "
", "", "
line1\nline2\nline3 BOLD
", + "
line1\nline2\nline3 BOLD" + )); + //@formatter:on + + } + + @Test + public void testEncodeDivWithPrePrettyPrint() { + + Patient p = new Patient(); + p.getText().setDivAsString("
A P TAG
line1\nline2\nline3 BOLD
", ""));
+ assertThat(encoded, not(containsString("text")));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, containsString("maritalStatus"));
+ }
+
+ @Test
+ public void testEncodeNonContained() {
+ // Create an organization
+ Organization org = new Organization();
+ org.setId("Organization/65546");
+ org.getNameElement().setValue("Contained Test Organization");
+
+ // Create a patient
+ Patient patient = new Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("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
", ""));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeSummary2() {
+ Patient patient = new Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("", ""));
+ assertThat(encoded, stringContainsInOrder("", " ", "
", " "));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeWithContained() {
+ List contained = new ArrayList();
+
+ // Will be added by reference
+ Patient p = new Patient();
+ p.setId("#" + "1000");
+ contained.add(p);
+
+ // Will be added by direct resource object
+ Location l = new Location();
+ l.setId("#" + "1001");
+ contained.add(l);
+
+ // Will not be referred to (and therefore shouldn't appear in output)
+ Location l2 = new Location();
+ l2.setId("#1002");
+ contained.add(l2);
+
+ Appointment appointment = new Appointment();
+ appointment.setId("1234");
+ appointment.getContained().addAll(contained);
+
+ appointment.addParticipant().getActor().setReference("#1000");
+ appointment.addParticipant().getActor().setResource(l);
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(appointment);
+ ourLog.info(encoded);
+
+ //@formatter:off
+ assertThat(encoded, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ " "
+ ));
+ //@formatter:on
+
+ assertThat(encoded, not(containsString("#1002")));
+ }
+
+ @Test
+ public void testEncodeWithDontEncodeElements() throws Exception {
+ Patient patient = new Patient();
+ patient.setId("123");
+ patient.getMeta().addProfile("http://profile");
+ patient.addName().addFamily("FAMILY").addGiven("GIVEN");
+ patient.addAddress().addLine("LINE1");
+
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.meta", "Patient.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.name.family"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("GIVEN"));
+ assertThat(out, not(containsString("FAMILY")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.meta"));
+ p.setEncodeElements(new HashSet(Arrays.asList("Patient.name")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("id"));
+ assertThat(out, not(containsString("address")));
+ assertThat(out, not(containsString("meta")));
+ }
+ }
+
+ @Test
+ public void testEncodeWithEncodeElements() throws Exception {
+ Patient patient = new Patient();
+ patient.getMeta().addProfile("http://profile");
+ patient.addName().addFamily("FAMILY");
+ patient.addAddress().addLine("LINE1");
+
+ Bundle bundle = new Bundle();
+ bundle.setTotal(100);
+ bundle.addEntry().setResource(patient);
+
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setEncodeElements(new HashSet(Arrays.asList("Patient.name", "Bundle.entry")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(bundle);
+ ourLog.info(out);
+ assertThat(out, not(containsString("total")));
+ assertThat(out, (containsString("Patient")));
+ assertThat(out, (containsString("name")));
+ assertThat(out, not(containsString("address")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setEncodeElements(new HashSet(Arrays.asList("Patient.name")));
+ p.setEncodeElementsAppliesToResourceTypes(new HashSet(Arrays.asList("Patient")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(bundle);
+ ourLog.info(out);
+ assertThat(out, (containsString("total")));
+ assertThat(out, (containsString("Patient")));
+ assertThat(out, (containsString("name")));
+ assertThat(out, not(containsString("address")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setEncodeElements(new HashSet(Arrays.asList("Patient")));
+ p.setEncodeElementsAppliesToResourceTypes(new HashSet(Arrays.asList("Patient")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(bundle);
+ ourLog.info(out);
+ assertThat(out, (containsString("total")));
+ assertThat(out, (containsString("Patient")));
+ assertThat(out, (containsString("name")));
+ assertThat(out, (containsString("address")));
+ }
+
+ }
+
+ @Test
+ public void testMoreExtensions() throws Exception {
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
+
+ Extension ext = new Extension();
+ ext.setUrl("http://example.com/extensions#someext");
+ ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
+
+ // Add the extension to the resource
+ patient.addExtension(ext);
+ // END SNIPPET: resourceExtension
+
+ // START SNIPPET: resourceStringExtension
+ HumanName name = patient.addName();
+ name.addFamily("Shmoe");
+ StringType given = name.addGivenElement();
+ given.setValue("Joe");
+ Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given"));
+ given.addExtension(ext2);
+
+ StringType given2 = name.addGivenElement();
+ given2.setValue("Shmoe");
+ Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent");
+ given2.addExtension(given2ext);
+ Extension givenExtChild = new Extension();
+ givenExtChild.setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD"));
+ given2ext.addExtension(givenExtChild);
+ // END SNIPPET: resourceStringExtension
+
+ // START SNIPPET: subExtension
+ Extension parent = new Extension().setUrl("http://example.com#parent");
+ patient.addExtension(parent);
+
+ Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.addExtension(child1);
+
+ Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.addExtension(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(" "));
+ assertThat(enc, containsString(
+ " "));
+ }
+
+ @Test
+ public void testOmitResourceId() {
+ Patient p = new Patient();
+ p.setId("123");
+ p.addName().addFamily("ABC");
+
+ assertThat(ourCtx.newXmlParser().encodeResourceToString(p), stringContainsInOrder("123", "ABC"));
+ assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), containsString("ABC"));
+ assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123")));
+ }
+
+
+ @Test
+ public void testParseAndEncodeComments() throws IOException {
+ //@formatter:off
+ String input = "\n" +
+ " " +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "\n" +
+ " Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321
\n" +
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " " +
+ " " +
+ " ";
+ //@formatter:off
+
+ Patient res = ourCtx.newXmlParser().parseResource(Patient.class, input);
+ res.getFormatCommentsPre();
+ assertEquals("Patient/pat1", res.getId());
+ assertEquals("654321", res.getIdentifier().get(0).getValue());
+ assertEquals(true, res.getActive());
+
+ assertThat(res.getIdElement().getFormatCommentsPre(), contains("pre resource comment"));
+ assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2"));
+ assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2"));
+ assertThat(res.getActiveElement().getFormatCommentsPost(), contains("post resource comment"));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res);
+ ourLog.info(encoded);
+
+ //@formatter:off
+ assertThat(encoded, stringContainsInOrder(
+ "\"identifier\": [",
+ "{",
+ "\"fhir_comments\":",
+ "[",
+ "\"identifier comment 1\"",
+ ",",
+ "\"identifier comment 2\"",
+ "]",
+ "\"use\": \"usual\",",
+ "\"_use\": {",
+ "\"fhir_comments\":",
+ "[",
+ "\"use comment 1\"",
+ ",",
+ "\"use comment 2\"",
+ "]",
+ "},",
+ "\"type\""
+ ));
+ //@formatter:off
+
+ encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res);
+ ourLog.info(encoded);
+
+ //@formatter:off
+ assertThat(encoded, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ " ",
+ "Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321
",
+ "",
+ " ",
+ " \n",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ "",
+ " "
+ ));
+ //@formatter:off
+
+ }
+
+ @Test
+ public void testParseAndEncodeCommentsOnExtensions() {
+ //@formatter:off
+ String input =
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Patient pat = ourCtx.newXmlParser().parseResource(Patient.class, input);
+ String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(pat);
+ ourLog.info(output);
+
+ assertThat(output, stringContainsInOrder(
+ "",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " "
+ ));
+
+ output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(pat);
+ ourLog.info(output);
+
+ assertThat(output, stringContainsInOrder(
+ "{",
+ " \"resourceType\": \"Patient\",",
+ " \"id\": \"someid\",",
+ " \"_id\": {",
+ " \"fhir_comments\": [",
+ " \" comment 1 \"",
+ " ]",
+ " },",
+ " \"extension\": [",
+ " {",
+ " \"fhir_comments\": [",
+ " \" comment 2 \",",
+ " \" comment 7 \"",
+ " ],",
+ " \"url\": \"urn:patientext:att\",",
+ " \"valueAttachment\": {",
+ " \"fhir_comments\": [",
+ " \" comment 3 \",",
+ " \" comment 6 \"",
+ " ],",
+ " \"contentType\": \"aaaa\",",
+ " \"_contentType\": {",
+ " \"fhir_comments\": [",
+ " \" comment 4 \"",
+ " ]",
+ " },",
+ " \"data\": \"AAAA\",",
+ " \"_data\": {",
+ " \"fhir_comments\": [",
+ " \" comment 5 \"",
+ " ]",
+ " }",
+ " }",
+ " }",
+ " ]",
+ "}"
+ ));
+
+ //@formatter:on
+ }
+
+
+ @Test
+ public void testParseAndEncodeNestedExtensions() {
+ //@formatter:off
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+ //@formatter:on
+
+ Patient p = ourCtx.newXmlParser().parseResource(Patient.class, input);
+ DateType bd = p.getBirthDateElement();
+ assertEquals("2005-03-04", bd.getValueAsString());
+
+ List exts = bd.getExtensionsByUrl("http://my.fancy.extension.url");
+ assertEquals(1, exts.size());
+ Extension ext = exts.get(0);
+ assertEquals(null, ext.getValue());
+
+ exts = ext.getExtensionsByUrl("http://my.fancy.extension.url");
+ assertEquals(1, exts.size());
+ ext = exts.get(0);
+ assertEquals("myNestedValue", ((StringType) ext.getValue()).getValue());
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(encoded);
+
+ //@formatter:off
+ assertThat(encoded, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ " ",
+ " "));
+ //@formatter:on
+
+ }
+
+ @Test
+ public void testParseBundleNewWithPlaceholderIds() {
+ //@formatter:off
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+ //@formatter:on
+
+ Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+
+ }
+
+ @Test
+ public void testParseBundleNewWithPlaceholderIdsInBase1() {
+ //@formatter:off
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+ //@formatter:on
+
+ Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+ }
+
+ @Test
+ public void testParseBundleNewWithPlaceholderIdsInBase2() {
+ //@formatter:off
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+ //@formatter:on
+
+ Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("urn:uuid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+
+ //@formatter:off
+ input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+ //@formatter:on
+
+ parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("urn:uuid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+
+ }
+
+ @Test
+ public void testParseBundleOldStyleWithUnknownLinks() throws Exception {
+ //@formatter:off
+ String bundle = "\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
+
+ Bundle b = (Bundle) ourCtx.newXmlParser().parseResource(bundle);
+ assertEquals(1, b.getEntry().size());
+
+ }
+
+ @Test
+ public void testParseBundleOldWithPlaceholderIds() {
+ //@formatter:off
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+ //@formatter:on
+
+ Bundle parsed = (Bundle) ourCtx.newXmlParser().parseResource(input);
+ assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getId());
+
+ }
+
+ @Test
+ public void testParseBundleWithBinary() {
+ // TODO: implement this test, make sure we handle ID and meta correctly in Binary
+ }
+
+
+
+ @Test
+ public void testParseBundleWithResourceId() {
+ //@formatter:off
+ String input = ""
+ + " "
+ + " "
+ + " "
+ + " \n";
+ //@formatter:on
+
+ Bundle bundle = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/3", bundle.getEntry().get(0).getResource().getIdElement().getValue());
+ assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/2", bundle.getEntry().get(1).getResource().getIdElement().getValue());
+ assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/1", bundle.getEntry().get(2).getResource().getIdElement().getValue());
+ }
+
+ /**
+ * Thanks to Alexander Kley!
+ */
+ @Test
+ public void testParseContainedBinaryResource() {
+ byte[] bin = new byte[] { 0, 1, 2, 3, 4 };
+ final Binary binary = new Binary();
+ binary.setContentType("PatientConsent").setContent(bin);
+
+ DocumentManifest manifest = new DocumentManifest();
+ CodeableConcept cc = new CodeableConcept();
+ cc.addCoding().setSystem("mySystem").setCode("PatientDocument");
+ manifest.setType(cc);
+ manifest.setMasterIdentifier(new Identifier().setSystem("mySystem").setValue(UUID.randomUUID().toString()));
+ manifest.addContent().setP(new Reference(binary));
+ manifest.setStatus(Enumerations.DocumentReferenceStatus.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().size());
+ assertEquals(1, actual.getContent().size());
+
+ /*
+ * If this fails, it's possibe the DocumentManifest structure is wrong: It should be
+ *
+ * @Child(name = "p", type = {Attachment.class, ValueSet.class}, order=1, min=1, max=1, modifier=false, summary=true)
+ */
+ assertNotNull(((Reference) actual.getContent().get(0).getP()).getResource());
+ }
+
+ /**
+ * See #426
+ */
+ @Test
+ public void testParseExtensionWithIdType() {
+ //@formatter:off
+ String input =
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+ //@formatter:on
+ Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
+
+ List extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare");
+ extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id");
+ Extension ext = extList.get(0);
+ IdType value = (IdType) ext.getValue();
+ assertEquals("mc1", value.getValueAsString());
+ }
+
+ /**
+ * See #426
+ *
+ * Value type of FOO isn't a valid datatype
+ */
+ @Test
+ public void testParseExtensionWithInvalidType() {
+ //@formatter:off
+ String input =
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+ //@formatter:on
+ Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
+
+ List extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare");
+ extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id");
+ Extension ext = extList.get(0);
+ IdType value = (IdType) ext.getValue();
+ assertEquals(null, value);
+ }
+
+ /**
+ * See #342
+ */
+ @Test(expected = DataFormatException.class)
+ public void testParseInvalid() {
+ ourCtx.newXmlParser().parseResource("FOO");
+ }
+
+ /**
+ * See #366
+ */
+ @Test()
+ public void testParseInvalidBoolean() {
+ //@formatter:off
+ String resource = "\n" +
+ " \n" +
+ " ";
+ //@formatter:on
+
+ IParser p = ourCtx.newXmlParser();
+
+ try {
+ p.parseResource(resource);
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Invalid attribute value \"1\": Invalid boolean string: '1'", e.getMessage());
+ }
+
+ LenientErrorHandler errorHandler = new LenientErrorHandler();
+ assertEquals(true, errorHandler.isErrorOnInvalidValue());
+ errorHandler.setErrorOnInvalidValue(false);
+ p.setParserErrorHandler(errorHandler);
+ }
+
+ @Test
+ public void testParseInvalidTextualNumber() {
+ Observation obs = new Observation();
+ obs.setValue(new Quantity().setValue(1234));
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs);
+ encoded = encoded.replace("1234", "\"1234\"");
+ ourLog.info(encoded);
+ ourCtx.newJsonParser().parseResource(encoded);
+ }
+
+ @Test
+ public void testParseMetadata() throws Exception {
+ //@formatter:off
+ String bundle = "\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
+
+ Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, bundle);
+ assertEquals(1, b.getEntry().size());
+
+ Bundle.BundleEntryComponent entry = b.getEntry().get(0);
+ Patient pt = (Patient) entry.getResource();
+ assertEquals("http://foo/fhirBase2/Patient/1/_history/2", pt.getIdElement().getValue());
+ assertEquals("2012-01-02", pt.getBirthDateElement().getValueAsString());
+ assertEquals("0.123", entry.getSearch().getScore().toString());
+ assertEquals("match", entry.getSearch().getMode().toCode());
+ assertEquals("POST", entry.getRequest().getMethod().toCode());
+ assertEquals("http://foo/Patient?identifier=value", entry.getRequest().getUrl());
+ assertEquals("2001-02-22T09:22:33-07:00", pt.getMeta().getLastUpdatedElement().getValueAsString());
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
+ String reEncoded = p.encodeResourceToString(b);
+ ourLog.info(reEncoded);
+
+ compareXml(bundle, reEncoded);
+
+ }
+
+ @Test
+ public void testParseMetaUpdatedDate() {
+ //@formatter:off
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+ //@formatter:on
+ Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+
+ InstantType updated = b.getMeta().getLastUpdatedElement();
+ assertEquals("2015-06-22T15:48:57.554-04:00", updated.getValueAsString());
+
+ }
+
+ @Test
+ public void testParseNestedExtensionsInvalid() {
+ //@formatter:off
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+ //@formatter:on
+
+ try {
+ ourCtx.newXmlParser().parseResource(Patient.class, input);
+ fail();
+ } catch (DataFormatException e) {
+ assertThat(e.getMessage(), containsString("Extension (URL='http://my.fancy.extension.url') must not have both a value and other contained extensions"));
+ }
+ }
+
+ /**
+ * See #163
+ */
+ @Test
+ public void testParseResourceType() {
+ IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
+
+ // Patient
+ Patient patient = new Patient();
+ String patientId = UUID.randomUUID().toString();
+ patient.setId(new IdType("Patient", patientId));
+ patient.addName().addGiven("John").addFamily("Smith");
+ patient.setGender(Enumerations.AdministrativeGender.MALE);
+ patient.setBirthDateElement(new DateType("1987-04-16"));
+
+ // Bundle
+ Bundle bundle = new Bundle();
+ bundle.setType(Bundle.BundleType.COLLECTION);
+ bundle.addEntry().setResource(patient);
+
+ String bundleText = xmlParser.encodeResourceToString(bundle);
+ ourLog.info(bundleText);
+
+ Bundle reincarnatedBundle = xmlParser.parseResource(Bundle.class, bundleText);
+ Patient reincarnatedPatient = (Patient) reincarnatedBundle.getEntry().get(0).getResource();
+
+ assertEquals("Patient", patient.getIdElement().getResourceType());
+ assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType());
+ }
+
+ /**
+ * See #344
+ */
+ @Test
+ public void testParserIsCaseSensitive() {
+ Observation obs = new Observation();
+ SampledData data = new SampledData();
+ data.setData("1 2 3");
+ data.setOrigin((SimpleQuantity) new SimpleQuantity().setValue(0L));
+ data.setPeriod(1000L);
+ obs.setValue(data);
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler());
+ String encoded = p.encodeResourceToString(obs);
+ ourLog.info(encoded);
+
+ p.parseResource(encoded);
+
+ try {
+ p.parseResource(encoded.replace("Observation", "observation"));
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("DataFormatException at [[row,col {unknown-source}]: [1,1]]: Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'",
+ e.getMessage());
+ }
+
+ try {
+ p.parseResource(encoded.replace("valueSampledData", "valueSampleddata"));
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Unknown element 'valueSampleddata' found during parse", e.getMessage());
+ }
+ }
+
+ /**
+ * See #339
+ *
+ * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
+ */
+ @Test
+ public void testXxe() {
+ //@formatter:off
+ String input =
+ "" +
+ "" +
+ "]>" +
+ "" +
+ "" +
+ "TEXT &xxe; TEXT" +
+ " " +
+ "" +
+ "" +
+ " " +
+ " ";
+ //@formatter:on
+
+ ourLog.info(input);
+
+ try {
+ ourCtx.newXmlParser().parseResource(Patient.class, input);
+ fail();
+ } catch (DataFormatException e) {
+ assertThat(e.toString(), containsString("Undeclared general entity"));
+ }
+
+ }
+
+ @Test
+ public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
+ String refVal = "http://my.org/FooBar";
+
+ Patient fhirPat = new Patient();
+ fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
+
+ IParser parser = ourCtx.newXmlParser();
+
+ String output = parser.encodeResourceToString(fhirPat);
+ System.out.println("output: " + output);
+
+ // Deserialize then check that valueReference value is still correct
+ fhirPat = parser.parseResource(Patient.class, output);
+
+ List extlst = fhirPat.getExtensionsByUrl("x1");
+ Assert.assertEquals(1, extlst.size());
+ Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
+ }
+
+ public static void compareXml(String content, String reEncoded) {
+ Diff d = DiffBuilder.compare(Input.fromString(content))
+ .withTest(Input.fromString(reEncoded))
+ .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))
+ .checkForSimilar()
+ .ignoreWhitespace()
+ .ignoreComments()
+ .withComparisonController(ComparisonControllers.Default)
+ .build();
+
+ assertTrue(d.toString(), !d.hasDifferences());
+ }
+
+ @ResourceDef(name = "Patient")
+ public static class TestPatientFor327 extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(name = "testCondition")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false)
+ private List testConditions = null;
+
+ public List getConditions() {
+ return this.testConditions;
+ }
+
+ public void setCondition(List ref) {
+ this.testConditions = ref;
+ }
+ }
+
+ private Matcher super String> stringContainsInOrder(java.lang.String... substrings) {
+ return Matchers.stringContainsInOrder(Arrays.asList(substrings));
+ }
+
+ private Matcher super String> stringContainsInOrder(List substrings) {
+ return Matchers.stringContainsInOrder(substrings);
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java
new file mode 100644
index 00000000000..9adf2c836d9
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/FhirInstanceValidatorTest.java
@@ -0,0 +1,136 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org;
+
+import java.io.IOException;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.validation.FhirValidator;
+import ca.uhn.fhir.validation.ValidationResult;
+import org.hl7.fhir.instance.hapi.validation.DefaultProfileValidationSupport;
+import org.hl7.fhir.instance.hapi.validation.FhirInstanceValidator;
+import org.hl7.fhir.instance.model.DateType;
+import org.hl7.fhir.instance.model.Observation;
+import org.hl7.fhir.instance.model.QuestionnaireResponse;
+import org.hl7.fhir.instance.model.StringType;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_HL7ORG_DSTU2;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class FhirInstanceValidatorTest {
+ private FhirInstanceValidator ourValidator = new FhirInstanceValidator(new DefaultProfileValidationSupport());
+ private FhirContext ourCtxHl7OrgDstu2 = FhirContext.forDstu2Hl7Org();
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorTest.class);
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ WRAP.option(),
+ HAPI_FHIR_VALIDATION_HL7ORG_DSTU2.option(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+
+ @Test
+ public void testQuestionnaireResponse() {
+ QuestionnaireResponse qr = new QuestionnaireResponse();
+ qr.setStatus(QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED);
+ qr.getGroup().addGroup().addQuestion().setLinkId("foo");
+ qr.getGroup().addQuestion().setLinkId("bar");
+
+ FhirValidator val = ourCtxHl7OrgDstu2.newValidator();
+
+ val.registerValidatorModule(ourValidator);
+
+ ValidationResult result = val.validateWithResult(qr);
+
+ String encoded = ourCtxHl7OrgDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome());
+ ourLog.info(encoded);
+
+ assertTrue(result.isSuccessful());
+ }
+
+ @Test
+ public void testObservation() {
+ Observation o = new Observation();
+ o.addIdentifier().setSystem("http://acme.org").setValue("1234");
+ o.setStatus(Observation.ObservationStatus.FINAL);
+ o.getCode().addCoding().setSystem("http://loinc.org").setCode("12345");
+ o.getEncounter().setReference("Encounter/1234");
+
+ FhirValidator val = ourCtxHl7OrgDstu2.newValidator();
+
+ val.registerValidatorModule(ourValidator);
+
+ ValidationResult result = val.validateWithResult(o);
+
+ String encoded = ourCtxHl7OrgDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome());
+ ourLog.info(encoded);
+
+ assertTrue(result.isSuccessful());
+ }
+
+ @Test
+ public void testParametersWithTwoParameters() {
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.addName().addGiven("James");
+ patient.setBirthDateElement(new DateType("2011-02-02"));
+
+ org.hl7.fhir.instance.model.Parameters input = new org.hl7.fhir.instance.model.Parameters();
+ input.addParameter().setName("mode").setValue(new StringType("create"));
+ input.addParameter().setName("resource").setResource(patient);
+
+ FhirValidator val = ourCtxHl7OrgDstu2.newValidator();
+
+ val.registerValidatorModule(ourValidator);
+
+ ValidationResult result = val.validateWithResult(input);
+
+ String encoded = ourCtxHl7OrgDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome());
+ ourLog.info(encoded);
+
+ assertTrue(result.isSuccessful());
+ assertThat(encoded, not(containsString("A parameter must have a value or a resource, but not both")));
+ }
+
+ @Test
+ public void testParametersHl7OrgDstu2() {
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.addName().addGiven("James");
+ patient.setBirthDateElement(new DateType("2011-02-02"));
+
+ org.hl7.fhir.instance.model.Parameters input = new org.hl7.fhir.instance.model.Parameters();
+ input.addParameter().setName("resource").setResource(patient);
+
+ FhirValidator val = ourCtxHl7OrgDstu2.newValidator();
+
+ val.registerValidatorModule(ourValidator);
+
+ ValidationResult result = val.validateWithResult(input);
+
+ ourLog.info(ourCtxHl7OrgDstu2.newJsonParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome()));
+ assertTrue(result.isSuccessful());
+ }
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java
new file mode 100644
index 00000000000..28e98cd4656
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/JsonParserHl7OrgDstu2Test.java
@@ -0,0 +1,1320 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.List;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import ca.uhn.fhir.narrative.INarrativeGenerator;
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.rest.api.Constants;
+import org.apache.commons.io.IOUtils;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.hamcrest.core.IsNot;
+import org.hamcrest.core.StringContains;
+import org.hamcrest.text.StringContainsInOrder;
+import org.hl7.fhir.instance.model.Address;
+import org.hl7.fhir.instance.model.Address.AddressUse;
+import org.hl7.fhir.instance.model.Address.AddressUseEnumFactory;
+import org.hl7.fhir.instance.model.Binary;
+import org.hl7.fhir.instance.model.Bundle;
+import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent;
+import org.hl7.fhir.instance.model.CodeableConcept;
+import org.hl7.fhir.instance.model.Conformance;
+import org.hl7.fhir.instance.model.Conformance.UnknownContentCode;
+import org.hl7.fhir.instance.model.DateTimeType;
+import org.hl7.fhir.instance.model.DateType;
+import org.hl7.fhir.instance.model.DecimalType;
+import org.hl7.fhir.instance.model.DiagnosticReport;
+import org.hl7.fhir.instance.model.EnumFactory;
+import org.hl7.fhir.instance.model.Enumeration;
+import org.hl7.fhir.instance.model.Extension;
+import org.hl7.fhir.instance.model.HumanName;
+import org.hl7.fhir.instance.model.Identifier.IdentifierUse;
+import org.hl7.fhir.instance.model.InstantType;
+import org.hl7.fhir.instance.model.List_;
+import org.hl7.fhir.instance.model.Narrative.NarrativeStatus;
+import org.hl7.fhir.instance.model.Observation;
+import org.hl7.fhir.instance.model.Organization;
+import org.hl7.fhir.instance.model.Patient;
+import org.hl7.fhir.instance.model.Patient.ContactComponent;
+import org.hl7.fhir.instance.model.PrimitiveType;
+import org.hl7.fhir.instance.model.Reference;
+import org.hl7.fhir.instance.model.Specimen;
+import org.hl7.fhir.instance.model.StringType;
+import org.hl7.fhir.instance.model.ValueSet;
+import org.hl7.fhir.instance.model.ValueSet.ConceptDefinitionComponent;
+import org.hl7.fhir.instance.model.ValueSet.ValueSetCodeSystemComponent;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.hl7.fhir.instance.model.api.INarrative;
+import org.hl7.fhir.instance.model.api.IPrimitiveType;
+import org.hl7.fhir.utilities.xhtml.XhtmlNode;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.xml.sax.SAXException;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_HL7ORG_DSTU2;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+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.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class JsonParserHl7OrgDstu2Test {
+
+ private FhirContext ourCtx = FhirContext.forDstu2Hl7Org();
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserHl7OrgDstu2Test.class);
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ WRAP.option(),
+ HAPI_FHIR_HL7ORG_DSTU2.option(),
+ mavenBundle().groupId("org.xmlunit").artifactId("xmlunit-core").versionAsInProject(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlEnabled() {
+ try {
+ String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}";
+ Bundle bundle = (Bundle) ourCtx.newJsonParser().parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ Patient o1 = (Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertEquals("http://lalaland.org", o1Id.getBaseUrl());
+ assertEquals("patient", o1Id.getResourceType());
+ assertEquals("pat1", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ } finally {
+ // ensure we cleanup ourCtx so other tests continue to work
+ ourCtx = FhirContext.forDstu2Hl7Org();
+ }
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() {
+ try {
+ String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}";
+ ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false);
+ Bundle bundle = (Bundle) ourCtx.newJsonParser().parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ Patient o1 = (Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertFalse(o1Id.hasBaseUrl());
+ assertEquals("Patient", o1Id.getResourceType());
+ assertEquals("patxuzos", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ } finally {
+ // ensure we cleanup ourCtx so other tests continue to work
+ ourCtx = FhirContext.forDstu2Hl7Org();
+ }
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() {
+ try {
+ String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}";
+ Bundle bundle = (Bundle) ourCtx.newJsonParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ Patient o1 = (Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertFalse(o1Id.hasBaseUrl());
+ assertEquals("Patient", o1Id.getResourceType());
+ assertEquals("patxuzos", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ } finally {
+ // ensure we cleanup ourCtx so other tests continue to work
+ ourCtx = FhirContext.forDstu2Hl7Org();
+ }
+ }
+
+ @Test
+ public void testEncodeUndeclaredExtensionWithEnumerationContent() {
+ IParser parser = ourCtx.newJsonParser();
+
+ Patient patient = new Patient();
+ patient.addAddress().setUse(AddressUse.HOME);
+ EnumFactory fact = new AddressUseEnumFactory();
+ PrimitiveType enumeration = new Enumeration(fact).setValue(AddressUse.HOME);
+ patient.addExtension().setUrl("urn:foo").setValue(enumeration);
+
+ String val = parser.encodeResourceToString(patient);
+ ourLog.info(val);
+ assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueCode\":\"home\"}]"));
+
+ MyPatientWithOneDeclaredEnumerationExtension actual = parser.parseResource(MyPatientWithOneDeclaredEnumerationExtension.class, val);
+ assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse());
+ Enumeration ref = actual.getFoo();
+ assertEquals("home", ref.getValue().toCode());
+
+ }
+
+ @Test
+ public void testEncodeNarrativeSuppressed() throws Exception {
+ Patient patient = new Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("THE DIV");
+ patient.addName().addFamily("FAMILY");
+ patient.getMaritalStatus().addCoding().setCode("D");
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSuppressNarratives(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("Patient"));
+ assertThat(encoded, stringContainsInOrder(Constants.TAG_SUBSETTED_SYSTEM, Constants.TAG_SUBSETTED_CODE));
+ assertThat(encoded, not(containsString("text")));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, containsString("maritalStatus"));
+ }
+
+ @Test
+ public void testEncodeAndParseExtensions() throws Exception {
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
+
+ Extension ext = new Extension();
+ ext.setUrl("http://example.com/extensions#someext");
+ ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
+ patient.getExtension().add(ext);
+
+ Extension parent = new Extension().setUrl("http://example.com#parent");
+ patient.getExtension().add(parent);
+ Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.getExtension().add(child1);
+ Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2"));
+ parent.getExtension().add(child2);
+
+ Extension modExt = new Extension();
+ modExt.setUrl("http://example.com/extensions#modext");
+ modExt.setValue(new DateType("1995-01-02"));
+ patient.getModifierExtension().add(modExt);
+
+ HumanName name = patient.addName();
+ name.addFamily("Blah");
+ StringType given = name.addGivenElement();
+ given.setValue("Joe");
+ Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given"));
+ given.getExtension().add(ext2);
+
+ StringType given2 = name.addGivenElement();
+ given2.setValue("Shmoe");
+ Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent");
+ given2.getExtension().add(given2ext);
+ given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD"));
+
+ String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(output);
+
+ String enc = ourCtx.newJsonParser().encodeResourceToString(patient);
+ assertThat(enc,
+ 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, 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.getExtension().get(0);
+ assertEquals("http://example.com/extensions#someext", ext.getUrl());
+ assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString());
+
+ parent = patient.getExtension().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", ((StringType) child1.getValue()).getValueAsString());
+ child2 = parent.getExtension().get(1);
+ assertEquals("http://example.com#child", child2.getUrl());
+ assertEquals("value2", ((StringType) child2.getValue()).getValueAsString());
+
+ modExt = parsed.getModifierExtension().get(0);
+ assertEquals("http://example.com/extensions#modext", modExt.getUrl());
+ assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString());
+
+ name = parsed.getName().get(0);
+
+ ext2 = name.getGiven().get(0).getExtension().get(0);
+ assertEquals("http://examples.com#givenext", ext2.getUrl());
+ assertEquals("given", ((StringType) ext2.getValue()).getValueAsString());
+
+ given2ext = name.getGiven().get(1).getExtension().get(0);
+ assertEquals("http://examples.com#givenext_parent", given2ext.getUrl());
+ assertNull(given2ext.getValue());
+ Extension given2ext2 = given2ext.getExtension().get(0);
+ assertEquals("http://examples.com#givenext_child", given2ext2.getUrl());
+ assertEquals("CHILD", ((StringType) 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();
+
+ InstantType pub = InstantType.now();
+ b.getMeta().setLastUpdatedElement(pub);
+ Thread.sleep(2);
+
+ Patient p1 = new Patient();
+ p1.addName().addFamily("Family1");
+ p1.setId("1");
+ BundleEntryComponent entry = b.addEntry();
+ entry.setResource(p1);
+
+ Patient p2 = new Patient();
+ p2.setId("Patient/2");
+ p2.addName().addFamily("Family2");
+ entry = b.addEntry();
+ entry.setResource(p2);
+
+ BundleEntryComponent deletedEntry = b.addEntry();
+ Patient dp = new Patient();
+ deletedEntry.setResource(dp);
+
+ dp.setId(("3"));
+ InstantType nowDt = InstantType.withCurrentTime();
+ dp.getMeta().setLastUpdatedElement(nowDt);
+
+ String bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(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("\"id\":\"2\"", "\"rel\":\"alternate\"", "\"href\":\"http://foo/bar\""));
+ // strings.addAll(Arrays.asList("\"deleted\":\"" + nowDt.getValueAsString() + "\"", "\"id\":\"Patient/3\""));
+
+ //@formatter:off
+ String[] strings = new String[] {
+ "\"resourceType\": \"Bundle\",",
+ "\"lastUpdated\": \"" + pub.getValueAsString() + "\"",
+ "\"entry\": [",
+ "\"resource\": {",
+ "\"id\": \"1\"",
+ "\"resource\": {",
+ "\"id\": \"2\"",
+ "\"resource\": {",
+ "\"id\": \"3\"",
+ "\"meta\": {",
+ "\"lastUpdated\": \"" + nowDt.getValueAsString() + "\""
+ };
+ //@formatter:off
+ assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(Arrays.asList(strings)));
+
+ b.getEntry().remove(2);
+ bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b);
+ assertThat(bundleString, not(containsString("deleted")));
+
+ }
+
+
+ @Test
+ public void testEncodeBundleCategory() {
+
+ Bundle b = new Bundle();
+ BundleEntryComponent e = b.addEntry();
+
+ Patient pt = new Patient();
+ pt.addIdentifier().setSystem("idsystem");
+ e.setResource(pt);
+
+ b.getMeta().addTag().setSystem("scheme").setCode("term").setDisplay("label");
+
+ String val = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(b);
+ ourLog.info(val);
+
+ assertThat(val, StringContains.containsString("\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"label\"}]"));
+ b = ourCtx.newJsonParser().parseResource(Bundle.class, val);
+ assertEquals(1, b.getMeta().getTag().size());
+ assertEquals("scheme", b.getMeta().getTag().get(0).getSystem());
+ assertEquals("term", b.getMeta().getTag().get(0).getCode());
+ assertEquals("label", b.getMeta().getTag().get(0).getDisplay());
+
+ assertNotNull(b.getEntry().get(0).getResource());
+ Patient p = (Patient) b.getEntry().get(0).getResource();
+ assertEquals("idsystem", p.getIdentifier().get(0).getSystem());
+
+ }
+
+
+ @Test
+ public void testEncodeBundleEntryCategory() {
+
+ Bundle b = new Bundle();
+ BundleEntryComponent e = b.addEntry();
+ e.setResource(new Patient());
+ e.getResource().getMeta().addTag().setSystem("scheme").setCode( "term").setDisplay( "label");
+
+ String val = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(b);
+ ourLog.info(val);
+
+ assertThat(val, StringContains.containsString("{\"resourceType\":\"Bundle\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"label\"}]}}}]}"));
+
+ b = ourCtx.newJsonParser().parseResource(Bundle.class, val);
+ assertEquals(1, b.getEntry().size());
+ assertEquals(1, b.getEntry().get(0).getResource().getMeta().getTag().size());
+ assertEquals("scheme", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getSystem());
+ assertEquals("term", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getCode());
+ assertEquals("label", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getDisplay());
+
+ }
+
+
+ @Test
+ public void testEncodeContained() {
+ IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true);
+
+ // Create an organization, note that the organization does not have an ID
+ Organization org = new Organization();
+ org.getNameElement().setValue("Contained Test Organization");
+
+ // Create a patient
+ Patient patient = new Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
+
+ // Put the organization as a reference in the patient resource
+ patient.getManagingOrganization().setResource(org);
+
+ String encoded = jsonParser.encodeResourceToString(patient);
+ ourLog.info(encoded);
+ assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\": [", "\"id\": \"1\"", "\"identifier\"", "\"reference\": \"#1\"")));
+
+ // Create a bundle with just the patient resource
+ Bundle b = new Bundle();
+ b.addEntry().setResource(patient);
+
+ // Encode the bundle
+ encoded = jsonParser.encodeResourceToString(b);
+ ourLog.info(encoded);
+ assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\": [", "\"id\": \"1\"", "\"identifier\"", "\"reference\": \"#1\"")));
+
+ // Re-parse the bundle
+ patient = (Patient) jsonParser.parseResource(jsonParser.encodeResourceToString(patient));
+ assertEquals("#1", patient.getManagingOrganization().getReference());
+
+ assertNotNull(patient.getManagingOrganization().getResource());
+ org = (Organization) patient.getManagingOrganization().getResource();
+ assertEquals("#1", org.getIdElement().getValue());
+ assertEquals("Contained Test Organization", org.getName());
+
+ // And re-encode a second time
+ encoded = jsonParser.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().clear();
+ patient.getManagingOrganization().setReference(null);
+ encoded = jsonParser.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().clear();
+ patient.getManagingOrganization().setReference(null);
+ patient.getManagingOrganization().getResource().setId(("#333"));
+ encoded = jsonParser.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.getNameElement().setValue("Contained Test Organization");
+
+ // Create a patient
+ Patient patient = new Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue( "253345");
+ patient.getManagingOrganization().setResource(org);
+
+ // Create a bundle with just the patient resource
+ Bundle b = new Bundle();
+ b.addEntry().setResource(patient);
+
+ // Encode the buntdle
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(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 testEncodeContainedResourcesMore() throws Exception {
+
+ DiagnosticReport rpt = new DiagnosticReport();
+ Specimen spm = new Specimen();
+ rpt.getText().setDivAsString("AAA");
+ rpt.addSpecimen().setResource(spm);
+
+ IParser p = ourCtx.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 testEncodeContainedWithNarrativeIsSuppresed() throws Exception {
+ IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
+
+ // Create an organization, note that the organization does not have an ID
+ Organization org = new Organization();
+ org.getNameElement().setValue("Contained Test Organization");
+ org.getText().setDivAsString("FOOBAR");
+
+ // Create a patient
+ Patient patient = new Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue( "253345");
+ patient.getText().setDivAsString("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 testEncodeDeclaredExtensionWithAddressContent() {
+ IParser parser = ourCtx.newJsonParser();
+
+ MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension();
+ patient.addAddress().setUse(AddressUse.HOME);
+ patient.setFoo(new Address().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(AddressUse.HOME, patient.getAddress().get(0).getUse());
+ Address ref = actual.getFoo();
+ assertEquals("line1", ref.getLine().get(0).getValue());
+
+ }
+
+ @Test
+ public void testEncodeDeclaredExtensionWithResourceContent() {
+ IParser parser = ourCtx.newJsonParser();
+
+ MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension();
+ patient.addAddress().setUse(AddressUse.HOME);
+ patient.setFoo(new Reference("Organization/123"));
+
+ String val = parser.encodeResourceToString(patient);
+ ourLog.info(val);
+ assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueReference\":{\"reference\":\"Organization/123\"}}]"));
+
+ MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
+ assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse());
+ Reference ref = actual.getFoo();
+ assertEquals("Organization/123", ref.getReference());
+
+ }
+
+ @Test
+ public void testEncodeExt() throws Exception {
+
+ ValueSet valueSet = new ValueSet();
+ valueSet.setId("123456");
+
+ ValueSetCodeSystemComponent define = valueSet.getCodeSystem();
+ ConceptDefinitionComponent code = define.addConcept();
+ code.setCode("someCode");
+ code.setDisplay("someDisplay");
+ code.addExtension().setUrl("urn:alt").setValue( new StringType("alt name"));
+
+
+ String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet);
+ ourLog.info(encoded);
+
+ assertThat(encoded, (containsString("123456")));
+ assertEquals(
+ "{\"resourceType\":\"ValueSet\",\"id\":\"123456\",\"codeSystem\":{\"concept\":[{\"extension\":[{\"url\":\"urn:alt\",\"valueString\":\"alt name\"}],\"code\":\"someCode\",\"display\":\"someDisplay\"}]}}",
+ encoded);
+
+ }
+
+ @Test
+ public void testEncodeExtensionInCompositeElement() {
+
+ Conformance c = new Conformance();
+ c.addRest().getSecurity().addExtension().setUrl("http://foo").setValue(new StringType("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.getAcceptUnknownElement().addExtension().setUrl( "http://foo").setValue( new StringType("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.getAcceptUnknownElement().setValue(UnknownContentCode.EXTENSIONS);
+ c.getAcceptUnknownElement().addExtension().setUrl("http://foo").setValue( new StringType("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\":\"extensions\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}");
+
+ }
+
+ @Test
+ public void testEncodeExtensionInResourceElement() {
+
+ Conformance c = new Conformance();
+ // c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringType("AAA"));
+ c.addExtension().setUrl("http://foo").setValue( new StringType("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 testEncodeExtensionOnEmptyElement() throws Exception {
+
+ ValueSet valueSet = new ValueSet();
+ valueSet.addUseContext().addExtension().setUrl("http://foo").setValue( new StringType("AAA"));
+
+ String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet);
+ assertThat(encoded, containsString("\"useContext\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"));
+
+ }
+
+
+ @Test
+ public void testEncodeExtensionWithResourceContent() {
+ IParser parser = ourCtx.newJsonParser();
+
+ Patient patient = new Patient();
+ patient.addAddress().setUse(AddressUse.HOME);
+ patient.addExtension().setUrl("urn:foo").setValue( new Reference("Organization/123"));
+
+ String val = parser.encodeResourceToString(patient);
+ ourLog.info(val);
+ assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueReference\":{\"reference\":\"Organization/123\"}}]"));
+
+ Patient actual = parser.parseResource(Patient.class, val);
+ assertEquals(AddressUse.HOME, patient.getAddress().get(0).getUse());
+ List ext = actual.getExtension();
+ assertEquals(1, ext.size());
+ Reference ref = (Reference) ext.get(0).getValue();
+ assertEquals("Organization/123", ref.getReference());
+
+ }
+
+ @Test
+ public void testEncodeIds() {
+ Patient pt = new Patient();
+ pt.addIdentifier().setSystem("sys").setValue( "val");
+
+ List_ list = new List_();
+ list.setId("listId");
+ list.addEntry().setItem(new Reference(pt)).setDeleted(true);
+
+ String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(list);
+ ourLog.info(enc);
+
+ assertThat(enc, containsString("\"id\": \"1\""));
+
+ List_ parsed = ourCtx.newJsonParser().parseResource(List_.class,enc);
+ assertEquals(Patient.class, parsed.getEntry().get(0).getItem().getResource().getClass());
+ }
+
+ @Test
+ public void testEncodeInvalidChildGoodException() {
+ Observation obs = new Observation();
+ obs.setValue(new DecimalType(112.22));
+
+ IParser p = ourCtx.newJsonParser();
+
+ try {
+ p.encodeResourceToString(obs);
+ } catch (DataFormatException e) {
+ assertThat(e.getMessage(), StringContains.containsString("DecimalType"));
+ }
+ }
+
+ @Test
+ public void testEncodeNarrativeBlockInBundle() throws Exception {
+ Patient p = new Patient();
+ p.addIdentifier().setSystem("foo").setValue("bar");
+ p.getText().setStatus(NarrativeStatus.GENERATED);
+ p.getText().setDivAsString("AAA");
+
+ Bundle b = new Bundle();
+ b.setTotal(123);
+ b.addEntry().setResource(p);
+
+ String str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b);
+ ourLog.info(str);
+ assertThat(str, StringContains.containsString("AAA"));
+
+ p.getText().setDivAsString("hello ");
+ str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(b);
+ ourLog.info(str);
+ // Backslashes need to be escaped because they are in a JSON value
+ assertThat(str, containsString(">hello<"));
+
+ }
+
+ @Test
+ public void testEncodeNonContained() {
+ Organization org = new Organization();
+ org.setId("Organization/65546");
+ org.getNameElement().setValue("Contained Test Organization");
+
+ Patient patient = new Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
+ patient.getManagingOrganization().setResource(org);
+
+ Bundle b = new Bundle();
+ b.addEntry().setResource(patient);
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(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 testEncodeResourceRef() throws DataFormatException {
+
+ Patient patient = new Patient();
+ patient.setManagingOrganization(new Reference());
+
+ IParser p = ourCtx.newJsonParser();
+ String str = p.encodeResourceToString(patient);
+ assertThat(str, IsNot.not(StringContains.containsString("managingOrganization")));
+
+ patient.setManagingOrganization(new Reference("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 Reference(org));
+ str = p.encodeResourceToString(patient);
+ assertThat(str, StringContains.containsString("\"contained\":[{\"resourceType\":\"Organization\""));
+
+ }
+
+ @Test
+ public void testEncodeSummary() throws Exception {
+ Patient patient = new Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("THE DIV");
+ patient.addName().addFamily("FAMILY");
+ patient.setMaritalStatus(new CodeableConcept().setText("D"));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("Patient"));
+ assertThat(encoded, stringContainsInOrder("\"tag\"",
+ "\"system\": \"" + Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\": \"" + Constants.TAG_SUBSETTED_CODE+"\","));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeSummary2() throws Exception {
+ Patient patient = new Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("THE DIV");
+ patient.addName().addFamily("FAMILY");
+ patient.setMaritalStatus(new CodeableConcept().setText("D"));
+
+ patient.getMeta().addTag().setSystem("foo").setCode("bar");
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("Patient"));
+ assertThat(encoded, stringContainsInOrder("\"tag\"",
+ "\"system\": \"foo\",", "\"code\": \"bar\"",
+ "\"system\": \"" + Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\": \"" + Constants.TAG_SUBSETTED_CODE+"\","));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeUndeclaredExtensionWithAddressContent() {
+ IParser parser = ourCtx.newJsonParser();
+
+ Patient patient = new Patient();
+ patient.addAddress().setUse(AddressUse.HOME);
+ patient.addExtension().setUrl("urn:foo").setValue(new Address().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(AddressUse.HOME, patient.getAddress().get(0).getUse());
+ Address ref = actual.getFoo();
+ assertEquals("line1", ref.getLine().get(0).getValue());
+
+ }
+
+ @Test
+ public void testEncodingNullExtension() {
+ Patient p = new Patient();
+ Extension extension = new Extension().setUrl("http://foo#bar");
+ p.getExtension().add(extension);
+ String str = ourCtx.newJsonParser().encodeResourceToString(p);
+
+ assertEquals("{\"resourceType\":\"Patient\"}", str);
+
+ extension.setValue(new StringType());
+
+ str = ourCtx.newJsonParser().encodeResourceToString(p);
+ assertEquals("{\"resourceType\":\"Patient\"}", str);
+
+ extension.setValue(new StringType(""));
+
+ str = ourCtx.newJsonParser().encodeResourceToString(p);
+ assertEquals("{\"resourceType\":\"Patient\"}", str);
+
+ }
+
+ @Test
+ public void testExtensionOnComposite() throws Exception {
+
+ Patient patient = new Patient();
+
+ HumanName name = patient.addName();
+ name.addFamily("Shmoe");
+ HumanName given = name.addGiven("Joe");
+ Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue( new StringType("Hello"));
+ given.getExtension().add(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.getName().get(0).getExtension().size());
+ Extension ext = parsed.getName().get(0).getExtension().get(0);
+ assertEquals("Hello", ((IPrimitiveType>)ext.getValue()).getValue());
+
+ }
+
+ @Test
+ public void testExtensionOnPrimitive() throws Exception {
+
+ Patient patient = new Patient();
+
+ HumanName name = patient.addName();
+ StringType family = name.addFamilyElement();
+ family.setValue("Shmoe");
+
+ family.addExtension().setUrl("http://examples.com#givenext").setValue( new StringType("Hello"));
+ 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.getName().get(0).getFamily().get(0).getExtension().size());
+ Extension ext = parsed.getName().get(0).getFamily().get(0).getExtension().get(0);
+ assertEquals("Hello", ((IPrimitiveType>) ext.getValue()).getValue());
+
+ }
+
+ @Test
+ public void testMoreExtensions() throws Exception {
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setUse(IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
+
+ Extension ext = new Extension();
+ ext.setUrl("http://example.com/extensions#someext");
+ ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
+
+ // Add the extension to the resource
+ patient.getExtension().add(ext);
+ // END SNIPPET: resourceExtension
+
+ // START SNIPPET: resourceStringExtension
+ HumanName name = patient.addName();
+ name.addFamily("Shmoe");
+ StringType given = name.addGivenElement();
+ given.setValue("Joe");
+ Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given"));
+ given.getExtension().add(ext2);
+
+ StringType given2 = name.addGivenElement();
+ given2.setValue("Shmoe");
+ Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent");
+ given2.getExtension().add(given2ext);
+ given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD"));
+ // END SNIPPET: resourceStringExtension
+
+ // START SNIPPET: subExtension
+ Extension parent = new Extension().setUrl("http://example.com#parent");
+ patient.getExtension().add(parent);
+
+ Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.getExtension().add(child1);
+
+ Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.getExtension().add(child2);
+ // END SNIPPET: subExtension
+
+ String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(output);
+
+ String enc = ourCtx.newJsonParser().encodeResourceToString(patient);
+ //@formatter:off
+ assertThat(enc, containsString(("{" +
+ "\"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\":\"value1\"" +
+ " }" +
+ " ]" +
+ " }" +
+ " ]").replace(" ", "")));
+ //@formatter:on
+
+ //@formatter:off
+ assertThat(enc, containsString((
+ " \"given\":[" +
+ " \"Joe\"," +
+ " \"Shmoe\"" +
+ " ]," +
+ " \"_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\"" +
+ " }" +
+ " ]" +
+ " }" +
+ " ]" +
+ " }" +
+ "").replace(" ", "")));
+ //@formatter:on
+ }
+
+ @Test
+ public void testNestedContainedResources() {
+
+ Observation A = new Observation();
+ A.getCode().setText("A");
+
+ Observation B = new Observation();
+ B.getCode().setText("B");
+ A.addRelated().setTarget(new Reference(B));
+
+ Observation C = new Observation();
+ C.getCode().setText("C");
+ B.addRelated().setTarget(new Reference(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.getCode().getTextElement().getValue());
+
+ Observation obsB = (Observation) obs.getRelated().get(0).getTarget().getResource();
+ assertEquals("B", obsB.getCode().getTextElement().getValue());
+
+ Observation obsC = (Observation) obsB.getRelated().get(0).getTarget().getResource();
+ assertEquals("C", obsC.getCode().getTextElement().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 testParseEmptyNarrative() throws Exception {
+ //@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);
+ XhtmlNode div = res.getText().getDiv();
+ String value = div.getValueAsString();
+
+ assertNull(value);
+ List childNodes = div.getChildNodes();
+ assertTrue(childNodes == null || childNodes.isEmpty());
+ }
+
+ @Test
+ public void testParseSimpleBundle() {
+ String bundle = "{\"resourceType\":\"Bundle\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"identifier\":[{\"system\":\"idsystem\"}]}}]}";
+ Bundle b = ourCtx.newJsonParser().parseResource(Bundle.class, bundle);
+
+ assertNotNull(b.getEntry().get(0).getResource());
+ Patient p = (Patient) b.getEntry().get(0).getResource();
+ assertEquals("idsystem", p.getIdentifier().get(0).getSystem());
+ }
+
+ @Test
+ public void testParseSingleQuotes() {
+ ourCtx.newJsonParser().parseResource(Bundle.class, "{ \"resourceType\": \"Bundle\" }");
+ ourCtx.newJsonParser().parseResource(Bundle.class, "{ 'resourceType': 'Bundle' }");
+ }
+
+ @Test
+ public void testSimpleParse() throws DataFormatException, IOException {
+
+ String msg = IOUtils.toString(JsonParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.json"));
+ IParser p = ourCtx.newJsonParser();
+ // ourLog.info("Reading in message: {}", msg);
+ Patient res = p.parseResource(Patient.class, msg);
+
+ assertEquals(2, res.getExtension().size());
+ assertEquals(1, res.getModifierExtension().size());
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res);
+ ourLog.info(encoded);
+
+ }
+
+ @Test
+ public void testParsePrimitiveExtension() {
+ //@formatter:off
+ String input = "{\n" +
+ " \"resourceType\":\"Patient\",\n" +
+ " \"contact\":[\n" +
+ " {\n" +
+ " \"name\":{\n" +
+ " \"family\":[\n" +
+ " \"du\",\n" +
+ " \"Marché\"\n" +
+ " ],\n" +
+ " \"_family\":[\n" +
+ " {\n" +
+ " \"extension\":[\n" +
+ " {\n" +
+ " \"url\":\"http://hl7.org/fhir/Profile/iso-21090#qualifier\",\n" +
+ " \"valueCode\":\"VV\"\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " null\n" +
+ " ]\n" +
+ " }\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ //@formatter:off
+
+ Patient p = ourCtx.newJsonParser().parseResource(Patient.class, input);
+ ContactComponent contact = p.getContact().get(0);
+ StringType family = contact.getName().getFamily().get(0);
+
+ assertEquals("du", family.getValueAsString());
+ assertEquals(1, family.getExtension().size());
+ }
+
+
+ @Test
+ public void testSimpleResourceEncodeWithCustomType() throws IOException, SAXException {
+
+ String jsonString = IOUtils.toString(JsonParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.json"), Charset.forName("UTF-8"));
+ MyObservationWithExtensions obs = ourCtx.newJsonParser().parseResource(MyObservationWithExtensions.class, jsonString);
+
+ {
+ ContactComponent contact = obs.getContact().get(0);
+ StringType family = contact.getName().getFamily().get(0);
+ assertEquals("du", family.getValueAsString());
+ assertEquals(1, family.getExtension().size());
+ }
+
+ assertEquals(0, obs.getExtension().size());
+ assertEquals("aaaa", obs.getExtAtt().getContentType());
+ assertEquals("str1", obs.getMoreExt().getStr1().getValue());
+ assertEquals("2011-01-02", obs.getModExt().getValueAsString());
+
+ List undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getExtension();
+ Extension undeclaredExtension = undeclaredExtensions.get(0);
+ assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl());
+
+ IParser xmlParser = ourCtx.newXmlParser();
+ String encoded = xmlParser.encodeResourceToString(obs);
+ encoded = encoded.replaceAll("", "").replace("\n", "").replace("\r", "").replaceAll(">\\s+<", "><");
+
+ String xmlString = IOUtils.toString(JsonParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.xml"), Charset.forName("UTF-8"));
+ xmlString = xmlString.replaceAll("", "").replace("\n", "").replace("\r", "").replaceAll(">\\s+<", "><");
+
+ ourLog.info("Expected: " + xmlString);
+ ourLog.info("Actual : " + encoded);
+
+ String expected = (xmlString);
+ String actual = (encoded.trim());
+
+ XmlParserHl7OrgDstu2Test.compareXml(expected, actual);
+ }
+
+
+ @Test
+ public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
+ String refVal = "http://my.org/FooBar";
+
+ Patient fhirPat = new Patient();
+ fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
+
+ IParser parser = ourCtx.newJsonParser();
+
+ String output = parser.encodeResourceToString(fhirPat);
+ System.out.println("output: " + output);
+
+ // Deserialize then check that valueReference value is still correct
+ fhirPat = parser.parseResource(Patient.class, output);
+
+ List extlst = fhirPat.getExtension();
+ Assert.assertEquals(1, extlst.size());
+ Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
+ }
+
+ @ResourceDef(name = "Patient")
+ public static class MyPatientWithOneDeclaredAddressExtension extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(order = 0, name = "foo")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false)
+ private Address myFoo;
+
+ public Address getFoo() {
+ return myFoo;
+ }
+
+ public void setFoo(Address theFoo) {
+ myFoo = theFoo;
+ }
+
+ }
+
+ @ResourceDef(name = "Patient")
+ public static class MyPatientWithOneDeclaredExtension extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(order = 0, name = "foo")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false)
+ private Reference myFoo;
+
+ public Reference getFoo() {
+ return myFoo;
+ }
+
+ public void setFoo(Reference theFoo) {
+ myFoo = theFoo;
+ }
+
+ }
+
+ private Matcher super String> stringContainsInOrder(java.lang.String... substrings) {
+ return Matchers.stringContainsInOrder(Arrays.asList(substrings));
+ }
+
+ private Matcher super String> stringContainsInOrder(List substrings) {
+ return Matchers.stringContainsInOrder(substrings);
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java
new file mode 100644
index 00000000000..f9b030253d9
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyObservationWithExtensions.java
@@ -0,0 +1,106 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org;
+
+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.util.ElementUtil;
+import org.hl7.fhir.instance.model.Attachment;
+import org.hl7.fhir.instance.model.BackboneElement;
+import org.hl7.fhir.instance.model.DateType;
+import org.hl7.fhir.instance.model.Patient;
+import org.hl7.fhir.instance.model.StringType;
+import org.hl7.fhir.instance.model.api.IBaseBackboneElement;
+
+
+@ResourceDef(name="Patient")
+public class MyObservationWithExtensions extends Patient {
+
+ @Extension(url = "urn:patientext:att", definedLocally = false, isModifier = false)
+ @Child(name = "extAtt", order = 0)
+ private Attachment 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 DateType myModExt;
+
+ public Attachment getExtAtt() {
+ return myExtAtt;
+ }
+
+ public MoreExt getMoreExt() {
+ return myMoreExt;
+ }
+
+ public void setMoreExt(MoreExt theMoreExt) {
+ myMoreExt = theMoreExt;
+ }
+
+ public DateType getModExt() {
+ return myModExt;
+ }
+
+ public void setModExt(DateType theModExt) {
+ myModExt = theModExt;
+ }
+
+ public void setExtAtt(Attachment 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 BackboneElement implements IBaseBackboneElement {
+
+ @Extension(url = "urn:patientext:moreext:1", definedLocally = false, isModifier = false)
+ @Child(name = "str1", order = 0)
+ private StringType myStr1;
+
+ @Extension(url = "urn:patientext:moreext:2", definedLocally = false, isModifier = false)
+ @Child(name = "str2", order = 1)
+ private StringType myStr2;
+
+ public StringType getStr1() {
+ return myStr1;
+ }
+
+ public void setStr1(StringType theStr1) {
+ myStr1 = theStr1;
+ }
+
+ public StringType getStr2() {
+ return myStr2;
+ }
+
+ public void setStr2(StringType theStr2) {
+ myStr2 = theStr2;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return ElementUtil.isEmpty(myStr1, myStr2);
+ }
+
+ @Override
+ public BackboneElement copy() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java
new file mode 100644
index 00000000000..d0d6820a724
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyOrganizationDstu2.java
@@ -0,0 +1,11 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org;
+
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import org.hl7.fhir.instance.model.Organization;
+
+@ResourceDef()
+public class MyOrganizationDstu2 extends Organization {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java
new file mode 100644
index 00000000000..c76e2bbf8fb
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientHl7Org.java
@@ -0,0 +1,64 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org;
+
+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 org.hl7.fhir.instance.model.DateTimeType;
+import org.hl7.fhir.instance.model.Patient;
+import org.hl7.fhir.instance.model.Reference;
+import org.hl7.fhir.instance.model.StringType;
+
+
+@ResourceDef()
+public class MyPatientHl7Org extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @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 StringType 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={
+ MyOrganizationDstu2.class })
+ @Description(
+ shortDefinition="Organization that is the custodian of the patient record",
+ formalDefinition="Organization that is the custodian of the patient record"
+ )
+ private Reference myManagingOrganization;
+
+
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty() && myPetName.isEmpty();
+ }
+
+
+ public List getImportantDates() {
+ if (myImportantDates==null) {
+ myImportantDates = new ArrayList();
+ }
+ return myImportantDates;
+ }
+
+ public StringType getPetName() {
+ return myPetName;
+ }
+
+ public void setImportantDates(List theImportantDates) {
+ myImportantDates = theImportantDates;
+ }
+
+ public void setPetName(StringType thePetName) {
+ myPetName = thePetName;
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java
new file mode 100644
index 00000000000..2f62b1b27fe
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/MyPatientWithOneDeclaredEnumerationExtension.java
@@ -0,0 +1,26 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org;
+
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import org.hl7.fhir.instance.model.Address.AddressUse;
+import org.hl7.fhir.instance.model.Enumeration;
+import org.hl7.fhir.instance.model.Patient;
+
+@ResourceDef(name = "Patient")
+public class MyPatientWithOneDeclaredEnumerationExtension extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(order = 0, name = "foo")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false)
+ private Enumeration myFoo;
+
+ public Enumeration getFoo() {
+ return myFoo;
+ }
+
+ public void setFoo(Enumeration theFoo) {
+ myFoo = theFoo;
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java
new file mode 100644
index 00000000000..5f8241084cf
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/ResourceWithExtensionsA.java
@@ -0,0 +1,206 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org;
+
+import java.util.List;
+import ca.uhn.fhir.model.api.annotation.Block;
+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 org.hl7.fhir.instance.model.BackboneElement;
+import org.hl7.fhir.instance.model.CodeableConcept;
+import org.hl7.fhir.instance.model.DateType;
+import org.hl7.fhir.instance.model.DomainResource;
+import org.hl7.fhir.instance.model.Identifier;
+import org.hl7.fhir.instance.model.ResourceType;
+import org.hl7.fhir.instance.model.StringType;
+
+@ResourceDef(name = "ResourceWithExtensionsA", id="0001")
+public class ResourceWithExtensionsA extends DomainResource {
+
+ /*
+ * NB: several unit tests depend on the structure here
+ * so check the unit tests immediately after any changes
+ */
+
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(name = "foo1", type = StringType.class, order = 0, min = 0, max = Child.MAX_UNLIMITED)
+ @Extension(url = "http://foo/#f1", definedLocally=true, isModifier=false)
+ private List myFoo1;
+
+ @Child(name = "foo2", type = StringType.class, order = 1, min = 0, max = 1)
+ @Extension(url = "http://foo/#f2", definedLocally=true, isModifier=true)
+ private StringType myFoo2;
+
+ @Child(name = "bar1", type = Bar1.class, order = 2, min = 1, max = Child.MAX_UNLIMITED)
+ @Extension(url = "http://bar/#b1", definedLocally=true, isModifier=false)
+ private List myBar1;
+
+ @Child(name = "bar2", type = Bar1.class, order = 3, min = 1, max = Child.MAX_UNLIMITED)
+ @Extension(url = "http://bar/#b2", definedLocally=true, isModifier=false)
+ private Bar1 myBar2;
+
+ @Child(name="baz", type = CodeableConcept.class, order = 4)
+ @Extension(url= "http://baz/#baz", definedLocally=true, isModifier=false)
+ @Description(shortDefinition = "Contains a codeable concept")
+ private CodeableConcept myBaz;
+
+ @Child(name = "identifier", type = Identifier.class, order = 0, min = 0, max = Child.MAX_UNLIMITED)
+ private List myIdentifier;
+
+ public List getBar1() {
+ return myBar1;
+ }
+
+ public Bar1 getBar2() {
+ return myBar2;
+ }
+
+ public List getFoo1() {
+ return myFoo1;
+ }
+
+ public StringType getFoo2() {
+ return myFoo2;
+ }
+
+ public CodeableConcept getBaz() { return myBaz; }
+
+ public List getIdentifier() {
+ return myIdentifier;
+ }
+
+ public void setBar1(List theBar1) {
+ myBar1 = theBar1;
+ }
+
+ public void setBar2(Bar1 theBar2) {
+ myBar2 = theBar2;
+ }
+
+ public void setFoo1(List theFoo1) {
+ myFoo1 = theFoo1;
+ }
+
+ public void setFoo2(StringType theFoo2) {
+ myFoo2 = theFoo2;
+ }
+
+ public void setBaz(CodeableConcept myBaz) { this.myBaz = myBaz; }
+
+ public void setIdentifier(List theValue) {
+ myIdentifier = theValue;
+ }
+
+ @Block(name = "Bar1")
+ public static class Bar1 extends BackboneElement {
+
+ public Bar1() {
+ super();
+ }
+
+ @Child(name = "bar11", type = DateType.class, order = 0, min = 0, max = Child.MAX_UNLIMITED)
+ @Extension(url = "http://bar/#b1/1", definedLocally=true, isModifier=false)
+ private List myBar11;
+
+ @Child(name = "bar12", type = DateType.class, order = 1, min = 0, max = Child.MAX_UNLIMITED)
+ @Extension(url = "http://bar/#b1/2", definedLocally=true, isModifier=false)
+ private List myBar12;
+
+ @Override
+ public boolean isEmpty() {
+ return false; // not implemented
+ }
+
+ public List getBar11() {
+ return myBar11;
+ }
+
+ public List getBar12() {
+ return myBar12;
+ }
+
+ public void setBar11(List theBar11) {
+ myBar11 = theBar11;
+ }
+
+ public void setBar12(List theBar12) {
+ myBar12 = theBar12;
+ }
+
+
+ @Override
+ public BackboneElement copy() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+ }
+
+ @Block(name = "Bar2")
+ public static class Bar2 extends BackboneElement {
+
+ @Child(name = "bar121", type = DateType.class, order = 0, min = 0, max = Child.MAX_UNLIMITED)
+ @Extension(url = "http://bar/#b1/2/1", definedLocally=true, isModifier=false)
+ private List myBar121;
+
+ @Child(name = "bar122", type = DateType.class, order = 1, min = 0, max = Child.MAX_UNLIMITED)
+ @Extension(url = "http://bar/#b1/2/2", definedLocally=true, isModifier=false)
+ private List myBar122;
+
+ @Override
+ public boolean isEmpty() {
+ return false; // not implemented
+ }
+
+
+ public List getBar121() {
+ return myBar121;
+ }
+
+ public List getBar122() {
+ return myBar122;
+ }
+
+ public void setBar121(List theBar121) {
+ myBar121 = theBar121;
+ }
+
+ public void setBar122(List theBar122) {
+ myBar122 = theBar122;
+ }
+
+ @Override
+ public BackboneElement copy() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false; // not implemented
+ }
+
+
+ @Override
+ public DomainResource copy() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ResourceType getResourceType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java
new file mode 100644
index 00000000000..ea8c81ed73b
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu2hl7org/XmlParserHl7OrgDstu2Test.java
@@ -0,0 +1,1521 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu2hl7org;
+
+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.List;
+import java.util.UUID;
+import ca.uhn.fhir.context.ConfigurationException;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.api.AddProfileTagEnum;
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import ca.uhn.fhir.narrative.INarrativeGenerator;
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.rest.api.Constants;
+import org.apache.commons.io.IOUtils;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.hamcrest.core.IsNot;
+import org.hamcrest.core.StringContains;
+import org.hamcrest.text.StringContainsInOrder;
+import org.hl7.fhir.instance.model.Address;
+import org.hl7.fhir.instance.model.CodeableConcept;
+import org.hl7.fhir.instance.model.Composition;
+import org.hl7.fhir.instance.model.DiagnosticReport;
+import org.hl7.fhir.instance.model.EnumFactory;
+import org.hl7.fhir.instance.model.Enumeration;
+import org.hl7.fhir.instance.model.InstantType;
+import org.hl7.fhir.instance.model.Narrative;
+import org.hl7.fhir.instance.model.Organization;
+import org.hl7.fhir.instance.model.Patient;
+import org.hl7.fhir.instance.model.PrimitiveType;
+import org.hl7.fhir.instance.model.Reference;
+import org.hl7.fhir.instance.model.Resource;
+import org.hl7.fhir.instance.model.Specimen;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.hl7.fhir.instance.model.api.INarrative;
+import org.hl7.fhir.instance.model.api.IPrimitiveType;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.xml.sax.SAXException;
+import org.xmlunit.builder.DiffBuilder;
+import org.xmlunit.builder.Input;
+import org.xmlunit.diff.ComparisonControllers;
+import org.xmlunit.diff.DefaultNodeMatcher;
+import org.xmlunit.diff.Diff;
+import org.xmlunit.diff.ElementSelectors;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_HL7ORG_DSTU2;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+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.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class XmlParserHl7OrgDstu2Test {
+
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserHl7OrgDstu2Test.class);
+ private FhirContext ourCtx = FhirContext.forDstu2Hl7Org();
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ WRAP.option(),
+ HAPI_FHIR_HL7ORG_DSTU2.option(),
+ mavenBundle().groupId("org.xmlunit").artifactId("xmlunit-core").versionAsInProject(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlEnabled() {
+ String tmp = " ";
+ org.hl7.fhir.instance.model.Bundle bundle = (org.hl7.fhir.instance.model.Bundle) ourCtx.newXmlParser().parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ org.hl7.fhir.instance.model.Patient o1 = (org.hl7.fhir.instance.model.Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertEquals("http://lalaland.org", o1Id.getBaseUrl());
+ assertEquals("patient", o1Id.getResourceType());
+ assertEquals("pat1", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() {
+ String tmp = " ";
+ ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false);
+ org.hl7.fhir.instance.model.Bundle bundle = (org.hl7.fhir.instance.model.Bundle) ourCtx.newXmlParser().parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ org.hl7.fhir.instance.model.Patient o1 = (org.hl7.fhir.instance.model.Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertFalse(o1Id.hasBaseUrl());
+ assertEquals("Patient", o1Id.getResourceType());
+ assertEquals("patxuzos", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() {
+ String tmp = " ";
+ org.hl7.fhir.instance.model.Bundle bundle = (org.hl7.fhir.instance.model.Bundle) ourCtx.newXmlParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ org.hl7.fhir.instance.model.Patient o1 = (org.hl7.fhir.instance.model.Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertFalse(o1Id.hasBaseUrl());
+ assertEquals("Patient", o1Id.getResourceType());
+ assertEquals("patxuzos", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ }
+
+ @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 testContainedResourceInExtensionUndeclared() {
+ org.hl7.fhir.instance.model.Patient p = new org.hl7.fhir.instance.model.Patient();
+ p.addName().addFamily("PATIENT");
+
+ Organization o = new Organization();
+ o.setName("ORG");
+ p.addExtension().setUrl("urn:foo").setValue(new org.hl7.fhir.instance.model.Reference(o));
+
+ String str = ourCtx.newXmlParser().encodeResourceToString(p);
+ ourLog.info(str);
+
+ p = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, str);
+ assertEquals("PATIENT", p.getName().get(0).getFamily().get(0).getValue());
+
+ List exts = p.getExtension();
+ assertEquals(1, exts.size());
+ org.hl7.fhir.instance.model.Reference rr = (org.hl7.fhir.instance.model.Reference) exts.get(0).getValue();
+ o = (Organization) rr.getResource();
+ assertEquals("ORG", o.getName());
+ }
+
+ @Test
+ public void testDuplicateContainedResources() {
+
+ org.hl7.fhir.instance.model.Observation resA = new org.hl7.fhir.instance.model.Observation();
+ resA.getCode().setText("A");
+
+ org.hl7.fhir.instance.model.Observation resB = new org.hl7.fhir.instance.model.Observation();
+ resB.getCode().setText("B");
+ resB.addRelated().setTarget(new org.hl7.fhir.instance.model.Reference(resA));
+ resB.addRelated().setTarget(new org.hl7.fhir.instance.model.Reference(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 testEncodeAndParseContained() {
+ IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
+
+ // Create an organization, note that the organization does not have an ID
+ Organization org = new Organization();
+ org.getNameElement().setValue("Contained Test Organization");
+
+ // Create a patient
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("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
+ org.hl7.fhir.instance.model.Bundle b = new org.hl7.fhir.instance.model.Bundle();
+ b.addEntry().setResource(patient);
+
+ // Encode the bundle
+ encoded = xmlParser.encodeResourceToString(b);
+ ourLog.info(encoded);
+ assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", " ")));
+ assertThat(encoded, containsString(""));
+ assertThat(encoded, stringContainsInOrder(Arrays.asList("", " ")));
+ assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", " ", ""))));
+
+ // Re-parse the bundle
+ patient = (org.hl7.fhir.instance.model.Patient) xmlParser.parseResource(xmlParser.encodeResourceToString(patient));
+ assertEquals("#1", patient.getManagingOrganization().getReferenceElement().getValue());
+
+ assertNotNull(patient.getManagingOrganization().getResource());
+ org = (Organization) patient.getManagingOrganization().getResource();
+ assertEquals("#1", org.getIdElement().getValue());
+ assertEquals("Contained Test Organization", org.getName());
+
+ // 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().clear();
+ patient.getManagingOrganization().setReference(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().clear();
+ patient.getManagingOrganization().setReference(null);
+ patient.getManagingOrganization().getResource().setId(("#333"));
+ encoded = xmlParser.encodeResourceToString(patient);
+ ourLog.info(encoded);
+ assertThat(encoded, stringContainsInOrder(Arrays.asList("", "",
+ " ", "")));
+ assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", ""))));
+
+ }
+
+ @Test
+ public void testEncodeAndParseExtensions() throws Exception {
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.addIdentifier().setUse(org.hl7.fhir.instance.model.Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
+
+ org.hl7.fhir.instance.model.Extension ext = new org.hl7.fhir.instance.model.Extension();
+ ext.setUrl("http://example.com/extensions#someext");
+ ext.setValue(new org.hl7.fhir.instance.model.DateTimeType("2011-01-02T11:13:15"));
+ patient.getExtension().add(ext);
+
+ org.hl7.fhir.instance.model.Extension parent = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#parent");
+ patient.getExtension().add(parent);
+ org.hl7.fhir.instance.model.Extension child1 = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.instance.model.StringType("value1"));
+ parent.getExtension().add(child1);
+ org.hl7.fhir.instance.model.Extension child2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.instance.model.StringType("value2"));
+ parent.getExtension().add(child2);
+
+ org.hl7.fhir.instance.model.Extension modExt = new org.hl7.fhir.instance.model.Extension();
+ modExt.setUrl("http://example.com/extensions#modext");
+ modExt.setValue(new org.hl7.fhir.instance.model.DateType("1995-01-02"));
+ patient.getModifierExtension().add(modExt);
+
+ org.hl7.fhir.instance.model.HumanName name = patient.addName();
+ name.addFamily("Blah");
+ org.hl7.fhir.instance.model.StringType given = name.addGivenElement();
+ given.setValue("Joe");
+ org.hl7.fhir.instance.model.Extension ext2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.instance.model.StringType("given"));
+ given.getExtension().add(ext2);
+
+ org.hl7.fhir.instance.model.StringType given2 = name.addGivenElement();
+ given2.setValue("Shmoe");
+ org.hl7.fhir.instance.model.Extension given2ext = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext_parent");
+ given2.getExtension().add(given2ext);
+ given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new org.hl7.fhir.instance.model.StringType("CHILD"));
+
+ 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(
+ " "));
+ assertThat(enc, containsString(
+ " "));
+ assertThat(enc, containsString(
+ " "));
+
+ /*
+ * Now parse this back
+ */
+
+ org.hl7.fhir.instance.model.Patient parsed = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, enc);
+ ext = parsed.getExtension().get(0);
+ assertEquals("http://example.com/extensions#someext", ext.getUrl());
+ assertEquals("2011-01-02T11:13:15", ((org.hl7.fhir.instance.model.DateTimeType) ext.getValue()).getValueAsString());
+
+ parent = patient.getExtension().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", ((org.hl7.fhir.instance.model.StringType) child1.getValue()).getValueAsString());
+ child2 = parent.getExtension().get(1);
+ assertEquals("http://example.com#child", child2.getUrl());
+ assertEquals("value2", ((org.hl7.fhir.instance.model.StringType) child2.getValue()).getValueAsString());
+
+ modExt = parsed.getModifierExtension().get(0);
+ assertEquals("http://example.com/extensions#modext", modExt.getUrl());
+ assertEquals("1995-01-02", ((org.hl7.fhir.instance.model.DateType) modExt.getValue()).getValueAsString());
+
+ name = parsed.getName().get(0);
+
+ ext2 = name.getGiven().get(0).getExtension().get(0);
+ assertEquals("http://examples.com#givenext", ext2.getUrl());
+ assertEquals("given", ((org.hl7.fhir.instance.model.StringType) ext2.getValue()).getValueAsString());
+
+ given2ext = name.getGiven().get(1).getExtension().get(0);
+ assertEquals("http://examples.com#givenext_parent", given2ext.getUrl());
+ assertNull(given2ext.getValue());
+ org.hl7.fhir.instance.model.Extension given2ext2 = given2ext.getExtension().get(0);
+ assertEquals("http://examples.com#givenext_child", given2ext2.getUrl());
+ assertEquals("CHILD", ((org.hl7.fhir.instance.model.StringType) given2ext2.getValue()).getValue());
+
+ }
+
+ @Test
+ public void testEncodeBinaryResource() {
+
+ org.hl7.fhir.instance.model.Binary patient = new org.hl7.fhir.instance.model.Binary();
+ patient.setContentType("foo");
+ patient.setContent(new byte[] { 1, 2, 3, 4 });
+
+ String val = ourCtx.newXmlParser().encodeResourceToString(patient);
+ assertEquals(
+ " ",
+ val);
+
+ }
+
+ @Test
+ public void testEncodeBinaryWithNoContentType() {
+ org.hl7.fhir.instance.model.Binary b = new org.hl7.fhir.instance.model.Binary();
+ b.setContent(new byte[] { 1, 2, 3, 4 });
+
+ String output = ourCtx.newXmlParser().encodeResourceToString(b);
+ ourLog.info(output);
+
+ assertEquals(" ", output);
+ }
+
+ @Test
+ public void testEncodeBoundCode() {
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.addAddress().setUse(Address.AddressUse.HOME);
+
+ patient.getGenderElement().setValue(org.hl7.fhir.instance.model.Enumerations.AdministrativeGender.MALE);
+
+ String val = ourCtx.newXmlParser().encodeResourceToString(patient);
+ ourLog.info(val);
+
+ assertThat(val, containsString("home"));
+ assertThat(val, containsString("male"));
+ }
+
+ @Test
+ public void testEncodeBundle() throws InterruptedException {
+ org.hl7.fhir.instance.model.Bundle b = new org.hl7.fhir.instance.model.Bundle();
+ b.getMeta().addTag().setSystem("http://hl7.org/fhir/tag").setCode("http://hl7.org/fhir/tag/message")
+ .setDisplay("Message");
+
+ InstantType pub = InstantType.withCurrentTime();
+ b.getMeta().setLastUpdatedElement(pub);
+
+ org.hl7.fhir.instance.model.Patient p1 = new org.hl7.fhir.instance.model.Patient();
+ p1.addName().addFamily("Family1");
+ org.hl7.fhir.instance.model.Bundle.BundleEntryComponent entry = b.addEntry();
+ p1.getIdElement().setValue("1");
+ entry.setResource(p1);
+
+ org.hl7.fhir.instance.model.Patient p2 = new org.hl7.fhir.instance.model.Patient();
+ p2.addName().addFamily("Family2");
+ entry = b.addEntry();
+ p2.getIdElement().setValue("2");
+ entry.setResource(p2);
+
+ String bundleString = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
+ ourLog.info(bundleString);
+
+ // @formatter:on
+ String[] strings = { "",
+ " ", "",
+ "", "", "" };
+ // @formatter:off
+
+ assertThat(bundleString, stringContainsInOrder(strings));
+ }
+
+ @Test
+ public void testEncodeBundleCategory() {
+
+ org.hl7.fhir.instance.model.Bundle b = new org.hl7.fhir.instance.model.Bundle();
+ org.hl7.fhir.instance.model.Bundle.BundleEntryComponent e = b.addEntry();
+ e.setResource(new org.hl7.fhir.instance.model.Patient());
+ e.getResource().getMeta().addTag().setSystem("scheme").setCode("term").setDisplay("label");
+
+ String val = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
+ ourLog.info(val);
+
+ // @formatter:off
+ assertThat(val, stringContainsInOrder("", "", "",
+ "", "
"));
+ // @formatter:on
+
+ b = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Bundle.class, val);
+ assertEquals(1, b.getEntry().size());
+ assertEquals(1, b.getEntry().get(0).getResource().getMeta().getTag().size());
+ assertEquals("scheme", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getSystem());
+ assertEquals("term", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getCode());
+ assertEquals("label", b.getEntry().get(0).getResource().getMeta().getTag().get(0).getDisplay());
+ }
+
+ private Matcher super String> stringContainsInOrder(java.lang.String... substrings) {
+ return Matchers.stringContainsInOrder(Arrays.asList(substrings));
+ }
+
+ private Matcher super String> stringContainsInOrder(List substrings) {
+ return Matchers.stringContainsInOrder(substrings);
+ }
+
+ @Test
+ public void testEncodeContainedAndIncludedResources() {
+
+ DiagnosticReport rpt = new DiagnosticReport();
+ rpt.getCode().setText("Report");
+
+ Specimen spm = new Specimen();
+ spm.addIdentifier().setValue("Report1ContainedSpecimen1");
+ rpt.addSpecimen().setResource(spm);
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
+ String str = p.encodeResourceToString(rpt);
+
+ ourLog.info(str);
+
+ }
+
+ @Test
+ public void testEncodeContainedResources() throws Exception {
+
+ DiagnosticReport rpt = new DiagnosticReport();
+ Specimen spm = new Specimen();
+ spm.addIdentifier().setSystem("urn").setValue("123");
+ rpt.getText().setDivAsString("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, stringContainsInOrder("", " "));
+ assertThat(str, IsNot.not(StringContains.containsString("")));
+
+ }
+
+ @Test
+ public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception {
+ IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
+
+ // Create an organization, note that the organization does not have an ID
+ Organization org = new Organization();
+ org.getNameElement().setValue("Contained Test Organization");
+ org.getText().setDivAsString("FOOBAR");
+
+ // Create a patient
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
+ patient.getText().setDivAsString("BARFOO");
+ patient.getManagingOrganization().setResource(org);
+
+ String encoded = parser.encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder("",
+ "BARFOO", "", "", "", " "));
+
+ MyPatientWithOneDeclaredAddressExtension actual = parser
+ .parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
+ assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse());
+ Address ref = actual.getFoo();
+ assertEquals("line1", ref.getLine().get(0).getValue());
+
+ }
+
+ @Test
+ public void testEncodeDeclaredExtensionWithResourceContent() {
+ IParser parser = ourCtx.newXmlParser();
+
+ MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension();
+ patient.addAddress().setUse(Address.AddressUse.HOME);
+ patient.setFoo(new org.hl7.fhir.instance.model.Reference("Organization/123"));
+
+ String val = parser.encodeResourceToString(patient);
+ ourLog.info(val);
+ assertThat(val, StringContains.containsString(
+ " "));
+
+ MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
+ assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse());
+ org.hl7.fhir.instance.model.Reference ref = actual.getFoo();
+ assertEquals("Organization/123", ref.getReferenceElement().getValue());
+
+ }
+
+ /**
+ * #158
+ */
+ @Test
+ public void testEncodeEmptyTag() {
+ org.hl7.fhir.instance.model.Patient p = new org.hl7.fhir.instance.model.Patient();
+ p.getMeta().addTag();
+
+ String encoded = ourCtx.newXmlParser().encodeResourceToString(p);
+ assertThat(encoded, not(containsString("tag")));
+
+ // With tag
+
+ p = new org.hl7.fhir.instance.model.Patient();
+ p.getMeta().addTag().setSystem("sys").setCode("code");
+
+ encoded = ourCtx.newXmlParser().encodeResourceToString(p);
+ assertThat(encoded, (containsString("tag")));
+ }
+
+ @Test
+ public void testEncodeEscapedChars() {
+
+ org.hl7.fhir.instance.model.Patient p = new org.hl7.fhir.instance.model.Patient();
+ p.addName().addFamily("and <>&ü");
+
+ String enc = ourCtx.newXmlParser().encodeResourceToString(p);
+ ourLog.info(enc);
+
+ p = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, enc);
+ assertEquals("and <>&ü", p.getName().get(0).getFamily().get(0).getValue());
+
+ p = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class,
+ " ");
+ assertEquals("quot \"", p.getName().get(0).getFamily().get(0).getValue());
+
+ }
+
+ @Test
+ public void testEncodeEscapedExtendedChars() {
+ org.hl7.fhir.instance.model.Patient p = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class,
+ " ");
+ assertEquals("uuml ü", p.getName().get(0).getFamily().get(0).getValue());
+ }
+
+ @Test
+ public void testEncodeExtensionUndeclaredNonModifier() {
+ org.hl7.fhir.instance.model.Observation obs = new org.hl7.fhir.instance.model.Observation();
+ obs.setId("1");
+ obs.getMeta().addProfile("http://profile");
+ org.hl7.fhir.instance.model.Extension ext = obs.addExtension();
+ ext.setUrl("http://exturl").setValue(new org.hl7.fhir.instance.model.StringType("ext_url_value"));
+
+ obs.getCode().setText("CODE");
+
+ IParser parser = ourCtx.newXmlParser();
+
+ String output = parser.setPrettyPrint(true).encodeResourceToString(obs);
+ ourLog.info(output);
+
+ // @formatter:off
+ assertThat(output, stringContainsInOrder("", "", "",
+ "", "", ""));
+ assertThat(output, not(stringContainsInOrder("")));
+ // @formatter:on
+
+ obs = parser.parseResource(org.hl7.fhir.instance.model.Observation.class, output);
+ assertEquals(1, obs.getExtension().size());
+ assertEquals("http://exturl", obs.getExtension().get(0).getUrl());
+ assertEquals("ext_url_value", ((org.hl7.fhir.instance.model.StringType) obs.getExtension().get(0).getValue()).getValue());
+ }
+
+ @Test
+ public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() {
+ org.hl7.fhir.instance.model.Observation obs = new org.hl7.fhir.instance.model.Observation();
+ obs.setId("1");
+ obs.getMeta().addProfile("http://profile");
+ org.hl7.fhir.instance.model.Extension ext = obs.addExtension();
+ ext.setUrl("http://exturl");
+
+ org.hl7.fhir.instance.model.Extension subExt = ext.addExtension();
+ subExt.setUrl("http://subext").setValue(new org.hl7.fhir.instance.model.StringType("sub_ext_value"));
+
+ obs.getCode().setText("CODE");
+
+ IParser parser = ourCtx.newXmlParser();
+
+ String output = parser.setPrettyPrint(true).encodeResourceToString(obs);
+ ourLog.info(output);
+
+ // @formatter:off
+ assertThat(output,
+ stringContainsInOrder("", "", "",
+ "", "",
+ "", ""));
+ assertThat(output, not(stringContainsInOrder("")));
+ // @formatter:on
+
+ obs = parser.parseResource(org.hl7.fhir.instance.model.Observation.class, output);
+ assertEquals(1, obs.getExtension().size());
+ assertEquals("http://exturl", obs.getExtension().get(0).getUrl());
+ assertEquals(1, obs.getExtension().get(0).getExtension().size());
+ assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl());
+ assertEquals("sub_ext_value", ((org.hl7.fhir.instance.model.StringType) obs.getExtension().get(0).getExtension().get(0).getValue()).getValue());
+ }
+
+ /**
+ * See #327
+ */
+ @Test
+ public void testEncodeExtensionWithContainedResource() {
+
+ TestPatientFor327 patient = new TestPatientFor327();
+ patient.setBirthDateElement(new org.hl7.fhir.instance.model.DateType("2016-04-14"));
+
+ List conditions = new ArrayList();
+ org.hl7.fhir.instance.model.Condition condition = new org.hl7.fhir.instance.model.Condition();
+ condition.addBodySite().setText("BODY SITE");
+ conditions.add(new org.hl7.fhir.instance.model.Reference(condition));
+ patient.setCondition(conditions);
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ //@formatter:off
+ assertThat(encoded, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ " "
+ ));
+ //@formatter:on
+ }
+
+ @Test
+ public void testEncodeExtensionWithResourceContent() {
+ IParser parser = ourCtx.newXmlParser();
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.addAddress().setUse(Address.AddressUse.HOME);
+ patient.addExtension().setUrl("urn:foo").setValue(new org.hl7.fhir.instance.model.Reference().setReference("Organization/123"));
+
+ String val = parser.encodeResourceToString(patient);
+ ourLog.info(val);
+ assertThat(val, StringContains.containsString(
+ " "));
+
+ org.hl7.fhir.instance.model.Patient actual = parser.parseResource(org.hl7.fhir.instance.model.Patient.class, val);
+ assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse());
+ List ext = actual.getExtension();
+ assertEquals(1, ext.size());
+ org.hl7.fhir.instance.model.Reference ref = (org.hl7.fhir.instance.model.Reference) ext.get(0).getValue();
+ assertEquals("Organization/123", ref.getReferenceElement().getValue());
+
+ }
+
+ @Test
+ public void testEncodeInvalidChildGoodException() {
+ org.hl7.fhir.instance.model.Observation obs = new org.hl7.fhir.instance.model.Observation();
+ obs.setValue(new org.hl7.fhir.instance.model.DecimalType(112.22));
+
+ IParser p = ourCtx.newJsonParser();
+
+ try {
+ p.encodeResourceToString(obs);
+ } catch (DataFormatException e) {
+ assertThat(e.getMessage(), StringContains.containsString("DecimalType"));
+ }
+ }
+
+ @Test
+ public void testEncodeNarrativeSuppressed() throws Exception {
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("THE DIV");
+ patient.addName().addFamily("FAMILY");
+ patient.getMaritalStatus().addCoding().setCode("D");
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).setSuppressNarratives(true)
+ .encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("", " ",
+ "
", ""));
+ assertThat(encoded, not(containsString("text")));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, containsString("maritalStatus"));
+ }
+
+ @Test
+ public void testEncodeNonContained() {
+ // Create an organization
+ Organization org = new Organization();
+ org.setId("Organization/65546");
+ org.getNameElement().setValue("Contained Test Organization");
+
+ // Create a patient
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("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
+ org.hl7.fhir.instance.model.Bundle b = new org.hl7.fhir.instance.model.Bundle();
+ b.addEntry().setResource(org);
+ b.addEntry().setResource(patient);
+
+ // Encode the buntdle
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
+ ourLog.info(encoded);
+ assertThat(encoded, not(containsString("")));
+ assertThat(encoded, stringContainsInOrder("", " "));
+ assertThat(encoded, containsString(""));
+ assertThat(encoded, stringContainsInOrder("", " "));
+
+ encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+ assertThat(encoded, not(containsString("")));
+ assertThat(encoded, containsString(""));
+
+ }
+
+ @Test
+ public void testEncodePrettyPrint() throws Exception {
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.getText().setDivAsString("\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 testEncodeResourceRef() throws DataFormatException {
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.setManagingOrganization(new org.hl7.fhir.instance.model.Reference());
+
+ IParser p = ourCtx.newXmlParser();
+ String str = p.encodeResourceToString(patient);
+ assertThat(str, IsNot.not(StringContains.containsString("managingOrganization")));
+
+ org.hl7.fhir.instance.model.Reference ref = new org.hl7.fhir.instance.model.Reference();
+ 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 org.hl7.fhir.instance.model.Reference(org));
+ str = p.encodeResourceToString(patient);
+ assertThat(str, StringContains.containsString("THE DIV
", ""));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeSummary2() throws Exception {
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("", ""));
+ assertThat(encoded, stringContainsInOrder("", " ",
+ "
", " "));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeUndeclaredExtensionWithAddressContent() {
+ IParser parser = ourCtx.newXmlParser();
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.addAddress().setUse(Address.AddressUse.HOME);
+ patient.addExtension().setUrl("urn:foo").setValue(new Address().addLine("line1"));
+
+ String val = parser.encodeResourceToString(patient);
+ ourLog.info(val);
+ assertThat(val, StringContains
+ .containsString(" "));
+
+ MyPatientWithOneDeclaredAddressExtension actual = parser
+ .parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
+ assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse());
+ Address ref = actual.getFoo();
+ assertEquals("line1", ref.getLine().get(0).getValue());
+
+ }
+
+ @Test
+ public void testEncodeUndeclaredExtensionWithEnumerationContent() {
+ IParser parser = ourCtx.newXmlParser();
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.addAddress().setUse(Address.AddressUse.HOME);
+ EnumFactory fact = new Address.AddressUseEnumFactory();
+ PrimitiveType enumeration = new Enumeration(fact).setValue(Address.AddressUse.HOME);
+ patient.addExtension().setUrl("urn:foo").setValue(enumeration);
+
+ String val = parser.encodeResourceToString(patient);
+ ourLog.info(val);
+ assertThat(val,
+ StringContains.containsString(" "));
+
+ MyPatientWithOneDeclaredEnumerationExtension actual = parser
+ .parseResource(MyPatientWithOneDeclaredEnumerationExtension.class, val);
+ assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse());
+ Enumeration ref = actual.getFoo();
+ assertEquals("home", ref.getValue().toCode());
+
+ }
+
+ @Test
+ public void testEncodingNullExtension() {
+ org.hl7.fhir.instance.model.Patient p = new org.hl7.fhir.instance.model.Patient();
+ org.hl7.fhir.instance.model.Extension extension = new org.hl7.fhir.instance.model.Extension().setUrl("http://foo#bar");
+ p.getExtension().add(extension);
+ String str = ourCtx.newXmlParser().encodeResourceToString(p);
+
+ assertEquals("", str);
+
+ extension.setValue(new org.hl7.fhir.instance.model.StringType());
+
+ str = ourCtx.newXmlParser().encodeResourceToString(p);
+ assertEquals("", str);
+
+ extension.setValue(new org.hl7.fhir.instance.model.StringType(""));
+
+ str = ourCtx.newXmlParser().encodeResourceToString(p);
+ assertEquals("", str);
+
+ }
+
+ @Test
+ public void testExtensionOnComposite() throws Exception {
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+
+ org.hl7.fhir.instance.model.HumanName name = patient.addName();
+ name.addFamily("Shmoe");
+ org.hl7.fhir.instance.model.HumanName given = name.addGiven("Joe");
+ org.hl7.fhir.instance.model.Extension ext2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.instance.model.StringType("Hello"));
+ given.getExtension().add(ext2);
+ String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(output);
+
+ String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
+ assertThat(enc, containsString(
+ " "));
+
+ org.hl7.fhir.instance.model.Patient parsed = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, new StringReader(enc));
+ assertEquals(1, parsed.getName().get(0).getExtension().size());
+ org.hl7.fhir.instance.model.Extension ext = parsed.getName().get(0).getExtension().get(0);
+ assertEquals("Hello", ((IPrimitiveType>) ext.getValue()).getValue());
+
+ }
+
+ @Test
+ public void testExtensionOnPrimitive() throws Exception {
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+
+ org.hl7.fhir.instance.model.HumanName name = patient.addName();
+ org.hl7.fhir.instance.model.StringType family = name.addFamilyElement();
+ family.setValue("Shmoe");
+
+ org.hl7.fhir.instance.model.Extension ext2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.instance.model.StringType("Hello"));
+ family.getExtension().add(ext2);
+ String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(output);
+
+ String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
+ assertThat(enc, containsString(
+ " "));
+
+ org.hl7.fhir.instance.model.Patient parsed = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, new StringReader(enc));
+ assertEquals(1, parsed.getName().get(0).getFamily().get(0).getExtension().size());
+ org.hl7.fhir.instance.model.Extension ext = parsed.getName().get(0).getFamily().get(0).getExtension().get(0);
+ assertEquals("Hello", ((IPrimitiveType>) ext.getValue()).getValue());
+
+ }
+
+ @Test
+ public void testExtensions() throws DataFormatException {
+
+ MyPatientHl7Org patient = new MyPatientHl7Org();
+ patient.setPetName(new org.hl7.fhir.instance.model.StringType("Fido"));
+ patient.getImportantDates().add(new org.hl7.fhir.instance.model.DateTimeType("2010-01-02"));
+ patient.getImportantDates().add(new org.hl7.fhir.instance.model.DateTimeType("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 Exception {
+
+ // @formatter:off
+ String msg = ""
+ + "John Cardinal: 444333333 "
+ + " "
+ + ""
+ + " "
+ + " "
+ + " "
+ + "" + ""
+ + " ";
+ // @formatter:on
+
+ org.hl7.fhir.instance.model.Patient patient = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, msg);
+
+ assertEquals(Narrative.NarrativeStatus.GENERATED, patient.getText().getStatus());
+ assertThat(patient.getText().getDiv().getValueAsString(), containsString(">John Cardinal: 444333333 <"));
+ assertEquals("PRP1660", patient.getIdentifier().get(0).getValue());
+
+ String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
+
+ ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient));
+
+ ourLog.info("Expected: {}", msg);
+ ourLog.info("Actual: {}", encoded);
+
+ compareXml(msg, encoded);
+
+ }
+
+ @Test
+ public void testLoadAndEncodeDeclaredExtensions()
+ throws ConfigurationException, DataFormatException, SAXException, IOException {
+ IParser p = ourCtx.newXmlParser();
+ ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.NEVER);
+
+ // @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" + " \n"
+ + " ";
+ // @formatter:on
+
+ ResourceWithExtensionsA resource = (ResourceWithExtensionsA) p.parseResource(ResourceWithExtensionsA.class, msg);
+ assertEquals("IdentifierLabel", resource.getIdentifier().get(0).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.setPrettyPrint(true).encodeResourceToString(resource);
+ ourLog.info(encoded);
+
+ compareXml(msg, encoded);
+ }
+
+ @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" + " \n"
+ + " ";
+ // @formatter:on
+
+ org.hl7.fhir.instance.model.Patient resource = (org.hl7.fhir.instance.model.Patient) p.parseResource(msg);
+ assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getValue());
+ assertEquals("Foo1Value", ((IPrimitiveType>) resource.getExtension().get(0).getValue()).getValueAsString());
+ assertEquals("Foo1Value2", ((IPrimitiveType>) resource.getExtension().get(1).getValue()).getValueAsString());
+ assertEquals("Foo2Value1",
+ ((IPrimitiveType>) resource.getModifierExtension().get(0).getValue()).getValueAsString());
+
+ assertEquals("2013-01-01",
+ ((IPrimitiveType>) resource.getExtension().get(2).getExtension().get(0).getValue()).getValueAsString());
+ assertEquals("2013-01-02",
+ ((IPrimitiveType>) resource.getExtension().get(2).getExtension().get(1).getExtension().get(0).getValue())
+ .getValueAsString());
+
+ String encoded = p.encodeResourceToString(resource);
+ ourLog.info(encoded);
+
+ compareXml(msg, encoded);
+ }
+
+ @Test
+ public void testMoreExtensions() throws Exception {
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.Patient();
+ patient.addIdentifier().setUse(org.hl7.fhir.instance.model.Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
+
+ org.hl7.fhir.instance.model.Extension ext = new org.hl7.fhir.instance.model.Extension();
+ ext.setUrl("http://example.com/extensions#someext");
+ ext.setValue(new org.hl7.fhir.instance.model.DateTimeType("2011-01-02T11:13:15"));
+
+ // Add the extension to the resource
+ patient.getExtension().add(ext);
+ // END SNIPPET: resourceExtension
+
+ // START SNIPPET: resourceStringExtension
+ org.hl7.fhir.instance.model.HumanName name = patient.addName();
+ name.addFamily("Shmoe");
+ org.hl7.fhir.instance.model.StringType given = name.addGivenElement();
+ given.setValue("Joe");
+ org.hl7.fhir.instance.model.Extension ext2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext").setValue(new org.hl7.fhir.instance.model.StringType("given"));
+ given.getExtension().add(ext2);
+
+ org.hl7.fhir.instance.model.StringType given2 = name.addGivenElement();
+ given2.setValue("Shmoe");
+ org.hl7.fhir.instance.model.Extension given2ext = new org.hl7.fhir.instance.model.Extension().setUrl("http://examples.com#givenext_parent");
+ given2.getExtension().add(given2ext);
+ given2ext.addExtension().setUrl("http://examples.com#givenext_child").setValue(new org.hl7.fhir.instance.model.StringType("CHILD"));
+ // END SNIPPET: resourceStringExtension
+
+ // START SNIPPET: subExtension
+ org.hl7.fhir.instance.model.Extension parent = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#parent");
+ patient.getExtension().add(parent);
+
+ org.hl7.fhir.instance.model.Extension child1 = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.instance.model.StringType("value1"));
+ parent.getExtension().add(child1);
+
+ org.hl7.fhir.instance.model.Extension child2 = new org.hl7.fhir.instance.model.Extension().setUrl("http://example.com#child").setValue(new org.hl7.fhir.instance.model.StringType("value1"));
+ parent.getExtension().add(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(
+ " "));
+ assertThat(enc, containsString(
+ " "));
+ }
+
+ // Narrative generation not currently supported for HL7org structures
+ public void testNarrativeGeneration() throws DataFormatException, IOException {
+
+ org.hl7.fhir.instance.model.Patient patient = new org.hl7.fhir.instance.model.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("help");
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ theNarrative.setStatusAsString("generated");
+ }
+
+ };
+
+ FhirContext context = ourCtx;
+ context.setNarrativeGenerator(gen);
+ IParser p = context.newXmlParser();
+ String str = p.encodeResourceToString(patient);
+
+ ourLog.info(str);
+
+ assertThat(str, StringContains.containsString(",\"text\":{\"status\":\"generated\",\"div\":\"help\"},"));
+ }
+
+ @Test
+ public void testNestedContainedResources() {
+
+ org.hl7.fhir.instance.model.Observation A = new org.hl7.fhir.instance.model.Observation();
+ A.getCode().setText("A");
+
+ org.hl7.fhir.instance.model.Observation B = new org.hl7.fhir.instance.model.Observation();
+ B.getCode().setText("B");
+ A.addRelated().setTarget(new org.hl7.fhir.instance.model.Reference(B));
+
+ org.hl7.fhir.instance.model.Observation C = new org.hl7.fhir.instance.model.Observation();
+ C.getCode().setText("C");
+ B.addRelated().setTarget(new org.hl7.fhir.instance.model.Reference(C));
+
+ String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(A);
+ ourLog.info(str);
+
+ assertThat(str,
+ stringContainsInOrder(Arrays.asList("", "", "")));
+ assertThat(str, stringContainsInOrder(Arrays.asList("", " ", "", " ")));
+
+ org.hl7.fhir.instance.model.Observation obs = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Observation.class, str);
+ assertEquals("A", obs.getCode().getText());
+
+ org.hl7.fhir.instance.model.Observation obsB = (org.hl7.fhir.instance.model.Observation) obs.getRelated().get(0).getTarget().getResource();
+ assertEquals("B", obsB.getCode().getText());
+
+ org.hl7.fhir.instance.model.Observation obsC = (org.hl7.fhir.instance.model.Observation) obsB.getRelated().get(0).getTarget().getResource();
+ assertEquals("C", obsC.getCode().getText());
+
+ }
+
+ @Test
+ public void testParseBinaryResource() {
+
+ org.hl7.fhir.instance.model.Binary val = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Binary.class,
+ " ");
+ assertEquals("foo", val.getContentType());
+ assertArrayEquals(new byte[] { 1, 2, 3, 4 }, val.getContent());
+
+ }
+
+ /**
+ * Thanks to Alexander Kley!
+ */
+ @Test
+ public void testParseContainedBinaryResource() throws Exception {
+ byte[] bin = new byte[] { 0, 1, 2, 3, 4 };
+ final org.hl7.fhir.instance.model.Binary binary = new org.hl7.fhir.instance.model.Binary();
+ binary.setContentType("PatientConsent").setContent(bin);
+ // binary.setId(UUID.randomUUID().toString());
+
+ org.hl7.fhir.instance.model.DocumentManifest manifest = new org.hl7.fhir.instance.model.DocumentManifest();
+ // manifest.setId(UUID.randomUUID().toString());
+ CodeableConcept cc = new CodeableConcept();
+ cc.addCoding().setSystem("mySystem").setCode("PatientDocument");
+ manifest.setType(cc);
+ manifest.setMasterIdentifier(new org.hl7.fhir.instance.model.Identifier().setSystem("mySystem").setValue(UUID.randomUUID().toString()));
+ manifest.addContent().setP(new org.hl7.fhir.instance.model.Reference(binary));
+ manifest.setStatus(org.hl7.fhir.instance.model.Enumerations.DocumentReferenceStatus.CURRENT);
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest);
+ ourLog.info(encoded);
+ assertThat(encoded,
+ StringContainsInOrder.stringContainsInOrder(Arrays.asList("contained>", "")));
+
+ org.hl7.fhir.instance.model.DocumentManifest actual = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.DocumentManifest.class, encoded);
+ assertEquals(1, actual.getContained().size());
+ assertEquals(1, actual.getContent().size());
+
+ /*
+ * If this fails, the child named "p" in DocumentManifest is missing the
+ * type IBaseResource in its definition... This isn't being auto added right
+ * now, need to figure out why
+ *
+ * @Child(name = "p", type = {Attachment.class, IBaseResource.class},
+ * order=1, min=1, max=1, modifier=false, summary=true)
+ */
+ assertNotNull(actual.getContent().get(0).getPReference().getResource());
+
+ }
+
+ @Test
+ public void testParseEncodeNarrative() {
+
+ String input = " Donald null DUCK Identifier 7000135 Address 10 Duxon Street
VICTORIA BC Can Date of birth 01 June 1980
";
+ IBaseResource 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"))));
+
+ }
+
+ @Test
+ public void testParseLanguage() {
+ String input = " 海生 王 Identifier URNo Address 99 Houston Road
BENTLEIGH Victoria Date of birth 01 January 1997
";
+ org.hl7.fhir.instance.model.Patient pt = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, input);
+
+ assertEquals("zh-CN", pt.getLanguage());
+ }
+
+ @Test
+ public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException {
+ IParser p = ourCtx.newXmlParser();
+
+ // @formatter:off
+ String msg = "" + "\n"
+ + " \n" + " \n" + " \n" + " ";
+ // @formatter:on
+
+ org.hl7.fhir.instance.model.Patient resource = (org.hl7.fhir.instance.model.Patient) p.parseResource(msg);
+ assertEquals("IdentifierLabel", resource.getIdentifier().get(0).getValue());
+ }
+
+ @Test
+ public void testReEncode() throws SAXException, IOException {
+
+ // @formatter:off
+ String msg = ""
+ + " "
+ + " ";
+ // @formatter:on
+
+ org.hl7.fhir.instance.model.Patient patient1 = ourCtx.newXmlParser().parseResource(org.hl7.fhir.instance.model.Patient.class, msg);
+ String encoded1 = ourCtx.newXmlParser().encodeResourceToString(patient1);
+
+ ourLog.info("Expected: {}", msg);
+ ourLog.info("Actual: {}", encoded1);
+
+ compareXml(msg, encoded1);
+ }
+
+ @Test
+ public void testSimpleResourceEncode() throws IOException, SAXException {
+
+ String xmlString = IOUtils.toString(
+ XmlParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.json"),
+ Charset.forName("UTF-8"));
+ org.hl7.fhir.instance.model.Patient obs = ourCtx.newJsonParser().parseResource(org.hl7.fhir.instance.model.Patient.class, xmlString);
+
+ List undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getExtension();
+ org.hl7.fhir.instance.model.Extension undeclaredExtension = undeclaredExtensions.get(0);
+ assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl());
+
+ 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(
+ XmlParserHl7OrgDstu2Test.class.getResourceAsStream("/example-patient-general-hl7orgdstu2.xml"),
+ Charset.forName("UTF-8"));
+
+ String expected = (jsonString);
+ String actual = (encoded.trim());
+
+ compareXml(expected, actual);
+ }
+
+ @Test
+ public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
+ String refVal = "http://my.org/FooBar";
+
+ org.hl7.fhir.instance.model.Patient fhirPat = new org.hl7.fhir.instance.model.Patient();
+ fhirPat.addExtension().setUrl("x1").setValue(new org.hl7.fhir.instance.model.Reference(refVal));
+
+ IParser parser = ourCtx.newXmlParser();
+
+ String output = parser.encodeResourceToString(fhirPat);
+ System.out.println("output: " + output);
+
+ // Deserialize then check that valueReference value is still correct
+ fhirPat = parser.parseResource(org.hl7.fhir.instance.model.Patient.class, output);
+
+ List extlst = fhirPat.getExtension();
+ Assert.assertEquals(1, extlst.size());
+ Assert.assertEquals(refVal, ((org.hl7.fhir.instance.model.Reference) extlst.get(0).getValue()).getReference());
+ }
+
+ @ResourceDef(name = "Patient")
+ public static class TestPatientFor327 extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(name = "testCondition")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false)
+ private List testConditions = null;
+
+ public List getConditions() {
+ return this.testConditions;
+ }
+
+ public void setCondition(List ref) {
+ this.testConditions = ref;
+ }
+ }
+
+ public static void compareXml(String content, String reEncoded) {
+ Diff d = DiffBuilder.compare(Input.fromString(content))
+ .withTest(Input.fromString(reEncoded))
+ .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))
+ .checkForSimilar()
+ .ignoreWhitespace()
+ .ignoreComments()
+ .withComparisonController(ComparisonControllers.Default)
+ .build();
+
+ assertTrue(d.toString(), !d.hasDifferences());
+ }
+
+ @ResourceDef(name = "Patient")
+ public static class MyPatientWithOneDeclaredAddressExtension extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(order = 0, name = "foo")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false)
+ private Address myFoo;
+
+ public Address getFoo() {
+ return myFoo;
+ }
+
+ public void setFoo(Address theFoo) {
+ myFoo = theFoo;
+ }
+
+ }
+
+ @ResourceDef(name = "Patient")
+ public static class MyPatientWithOneDeclaredExtension extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(order = 0, name = "foo")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "urn:foo", definedLocally = true, isModifier = false)
+ private Reference myFoo;
+
+ public Reference getFoo() {
+ return myFoo;
+ }
+
+ public void setFoo(Reference theFoo) {
+ myFoo = theFoo;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java
new file mode 100644
index 00000000000..37edb7a955f
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomDiagnosticReport.java
@@ -0,0 +1,13 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import org.hl7.fhir.dstu3.model.DiagnosticReport;
+
+@ResourceDef(name = "DiagnosticReport", profile = CustomDiagnosticReport.PROFILE)
+public class CustomDiagnosticReport extends DiagnosticReport {
+
+ public static final String PROFILE = "http://custom_DiagnosticReport";
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java
new file mode 100644
index 00000000000..470ba8690da
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomObservation.java
@@ -0,0 +1,13 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import org.hl7.fhir.dstu3.model.Observation;
+
+@ResourceDef(name = "Observation", profile = CustomObservation.PROFILE)
+public class CustomObservation extends Observation {
+
+ public static final String PROFILE = "http://custom_Observation";
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java
new file mode 100644
index 00000000000..e4baa629e05
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/CustomPatientDstu3.java
@@ -0,0 +1,29 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+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 org.hl7.fhir.dstu3.model.BooleanType;
+import org.hl7.fhir.dstu3.model.Patient;
+
+@ResourceDef(name = "Patient", profile = "Patient")
+public class CustomPatientDstu3 extends Patient {
+
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(name = "homeless", order = 1)
+ @Extension(url = "/StructureDefinition/homeless", definedLocally = true, isModifier = false)
+ @Description(shortDefinition = "The patient being homeless, true if homeless")
+ private BooleanType homeless;
+
+
+ public BooleanType getHomeless() {
+ return homeless;
+ }
+
+ public void setHomeless(final BooleanType homeless) {
+ this.homeless = homeless;
+ }
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java
new file mode 100644
index 00000000000..1e3ff368610
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3JsonParserTest.java
@@ -0,0 +1,1700 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.UUID;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.parser.LenientErrorHandler;
+import ca.uhn.fhir.parser.StrictErrorHandler;
+import com.google.common.collect.Sets;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.hl7.fhir.dstu3.model.AuditEvent;
+import org.hl7.fhir.dstu3.model.Basic;
+import org.hl7.fhir.dstu3.model.Binary;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.CapabilityStatement;
+import org.hl7.fhir.dstu3.model.Claim;
+import org.hl7.fhir.dstu3.model.Coding;
+import org.hl7.fhir.dstu3.model.Condition;
+import org.hl7.fhir.dstu3.model.Coverage;
+import org.hl7.fhir.dstu3.model.DateTimeType;
+import org.hl7.fhir.dstu3.model.DateType;
+import org.hl7.fhir.dstu3.model.DecimalType;
+import org.hl7.fhir.dstu3.model.DocumentManifest;
+import org.hl7.fhir.dstu3.model.Enumerations;
+import org.hl7.fhir.dstu3.model.ExplanationOfBenefit;
+import org.hl7.fhir.dstu3.model.Extension;
+import org.hl7.fhir.dstu3.model.HumanName;
+import org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.dstu3.model.Identifier;
+import org.hl7.fhir.dstu3.model.Linkage;
+import org.hl7.fhir.dstu3.model.Observation;
+import org.hl7.fhir.dstu3.model.Parameters;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.dstu3.model.Quantity;
+import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
+import org.hl7.fhir.dstu3.model.Reference;
+import org.hl7.fhir.dstu3.model.SampledData;
+import org.hl7.fhir.dstu3.model.SimpleQuantity;
+import org.hl7.fhir.dstu3.model.StringType;
+import org.hl7.fhir.dstu3.model.UriType;
+import org.hl7.fhir.dstu3.model.ValueSet;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU3;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.apache.commons.lang3.StringUtils.countMatches;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+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.junit.Assert.fail;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class Dstu3JsonParserTest {
+
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu3JsonParserTest.class);
+ private FhirContext ourCtx = FhirContext.forDstu3();
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ WRAP.option(),
+ HAPI_FHIR_DSTU3.option(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+
+ @Test
+ public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
+ String refVal = "http://my.org/FooBar";
+
+ Patient fhirPat = new Patient();
+ fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
+
+ IParser parser = ourCtx.newJsonParser();
+
+ String output = parser.encodeResourceToString(fhirPat);
+ System.out.println("output: " + output);
+
+ // Deserialize then check that valueReference value is still correct
+ fhirPat = parser.parseResource(Patient.class, output);
+
+ List extlst = fhirPat.getExtensionsByUrl("x1");
+ Assert.assertEquals(1, extlst.size());
+ Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
+ }
+
+ /**
+ * See #544
+ */
+ @Test
+ public void testBundleStitchReferencesByUuid() throws Exception {
+ Bundle bundle = new Bundle();
+
+ DocumentManifest dm = new DocumentManifest();
+ dm.getSubject().setReference("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3");
+ bundle.addEntry().setResource(dm);
+
+ Patient patient = new Patient();
+ patient.addName().setFamily("FAMILY");
+ bundle.addEntry().setResource(patient).setFullUrl("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3");
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle);
+ ourLog.info(encoded);
+
+ bundle = ourCtx.newJsonParser().parseResource(Bundle.class, encoded);
+ dm = (DocumentManifest) bundle.getEntry().get(0).getResource();
+
+ assertEquals("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3", dm.getSubject().getReference());
+
+ Patient subject = (Patient) dm.getSubject().getResource();
+ assertNotNull(subject);
+ assertEquals("FAMILY", subject.getNameFirstRep().getFamily());
+ }
+
+ /**
+ * Test for the url generated based on the server config
+ */
+ @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 StringType("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().getValue());
+ assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue());
+ }
+
+ @Test
+ public void testCustomUrlExtensioninBundle() {
+ final String expected = "{\"resourceType\":\"Bundle\",\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://www.example.com/petname\",\"valueString\":\"myName\"}]}}]}";
+
+ final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
+ patient.setPetName(new StringType("myName"));
+
+ final Bundle bundle = new Bundle();
+ final Bundle.BundleEntryComponent entry = new Bundle.BundleEntryComponent();
+ entry.setResource(patient);
+ bundle.addEntry(entry);
+
+ final IParser jsonParser = ourCtx.newJsonParser();
+ jsonParser.setServerBaseUrl("http://www.example.com");
+
+ final String parsedBundle = jsonParser.encodeResourceToString(bundle);
+ System.out.println(parsedBundle);
+ assertEquals(expected, parsedBundle);
+
+ // Parse with string
+ Bundle newBundle = jsonParser.parseResource(Bundle.class, parsedBundle);
+ assertNotNull(newBundle);
+ assertEquals(1, newBundle.getEntry().size());
+ Patient newPatient = (Patient) newBundle.getEntry().get(0).getResource();
+ assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue());
+
+ // Parse with stream
+ newBundle = jsonParser.parseResource(Bundle.class, new StringReader(parsedBundle));
+ assertNotNull(newBundle);
+ assertEquals(1, newBundle.getEntry().size());
+ newPatient = (Patient) newBundle.getEntry().get(0).getResource();
+ assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue());
+
+ }
+
+ /**
+ * See #276
+ */
+ @Test
+ public void testDoubleEncodingContainedResources() throws Exception {
+ Patient patient = new Patient();
+ patient.setId("#patient-1");
+ patient.setActive(true);
+
+ Coverage coverage = new Coverage();
+ coverage.setId("#coverage-1");
+ coverage.getBeneficiary().setResource(patient);
+
+ Claim resource = new Claim();
+ resource.getContained().add(patient);
+ resource.getContained().add(coverage);
+ resource.getPatient().setReference("#patient-1");
+ resource.addInsurance().getCoverage().setReference("#coverage-1");
+
+ IParser p = ourCtx.newJsonParser().setPrettyPrint(true);
+ String encoded = p.encodeResourceToString(resource);
+ ourLog.info(encoded);
+
+ assertEquals(3, countMatches(encoded, "resourceType"));
+ }
+
+ @Test
+ public void testEncodeAndParseExtensions() throws Exception {
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
+
+ Extension ext = new Extension();
+ ext.setUrl("http://example.com/extensions#someext");
+ ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
+ patient.addExtension(ext);
+
+ Extension parent = new Extension().setUrl("http://example.com#parent");
+ patient.addExtension(parent);
+ Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.addExtension(child1);
+ Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2"));
+ parent.addExtension(child2);
+
+ Extension modExt = new Extension();
+ modExt.setUrl("http://example.com/extensions#modext");
+ modExt.setValue(new DateType("1995-01-02"));
+ patient.addModifierExtension(modExt);
+
+ HumanName name = patient.addName();
+ name.setFamily("Blah");
+ StringType given = name.addGivenElement();
+ given.setValue("Joe");
+ Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given"));
+ given.addExtension(ext2);
+
+ StringType given2 = name.addGivenElement();
+ given2.setValue("Shmoe");
+ Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent");
+ given2.addExtension(given2ext);
+ given2ext.addExtension(new Extension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD")));
+
+ String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(output);
+
+ String enc = ourCtx.newJsonParser().encodeResourceToString(patient);
+ assertThat(enc, 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, 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.getExtension().get(0);
+ assertEquals("http://example.com/extensions#someext", ext.getUrl());
+ assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString());
+
+ parent = patient.getExtension().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", ((StringType) child1.getValue()).getValueAsString());
+ child2 = parent.getExtension().get(1);
+ assertEquals("http://example.com#child", child2.getUrl());
+ assertEquals("value2", ((StringType) child2.getValue()).getValueAsString());
+
+ modExt = parsed.getModifierExtension().get(0);
+ assertEquals("http://example.com/extensions#modext", modExt.getUrl());
+ assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString());
+
+ name = parsed.getName().get(0);
+
+ ext2 = name.getGiven().get(0).getExtension().get(0);
+ assertEquals("http://examples.com#givenext", ext2.getUrl());
+ assertEquals("given", ((StringType) ext2.getValue()).getValueAsString());
+
+ given2ext = name.getGiven().get(1).getExtension().get(0);
+ assertEquals("http://examples.com#givenext_parent", given2ext.getUrl());
+ assertNull(given2ext.getValue());
+ Extension given2ext2 = given2ext.getExtension().get(0);
+ assertEquals("http://examples.com#givenext_child", given2ext2.getUrl());
+ assertEquals("CHILD", ((StringType) given2ext2.getValue()).getValue());
+
+ }
+
+ private Matcher super String> stringContainsInOrder(java.lang.String... substrings) {
+ return Matchers.stringContainsInOrder(Arrays.asList(substrings));
+ }
+
+ @Test
+ public void testEncodeAndParseMetaProfileAndTags() {
+ Patient p = new Patient();
+ p.addName().setFamily("FAMILY");
+
+ p.getMeta().addProfile("http://foo/Profile1");
+ p.getMeta().addProfile("http://foo/Profile2");
+
+ p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1");
+ p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2");
+
+ p.getMeta().addSecurity().setSystem("sec_scheme1").setCode("sec_term1").setDisplay("sec_label1");
+ p.getMeta().addSecurity().setSystem("sec_scheme2").setCode("sec_term2").setDisplay("sec_label2");
+
+ String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+
+ //@formatter:off
+ assertThat(enc, stringContainsInOrder("\"meta\": {",
+ "\"profile\": [",
+ "\"http://foo/Profile1\",",
+ "\"http://foo/Profile2\"",
+ "],",
+ "\"security\": [",
+ "{",
+ "\"system\": \"sec_scheme1\",",
+ "\"code\": \"sec_term1\",",
+ "\"display\": \"sec_label1\"",
+ "},",
+ "{",
+ "\"system\": \"sec_scheme2\",",
+ "\"code\": \"sec_term2\",",
+ "\"display\": \"sec_label2\"",
+ "}",
+ "],",
+ "\"tag\": [",
+ "{",
+ "\"system\": \"scheme1\",",
+ "\"code\": \"term1\",",
+ "\"display\": \"label1\"",
+ "},",
+ "{",
+ "\"system\": \"scheme2\",",
+ "\"code\": \"term2\",",
+ "\"display\": \"label2\"",
+ "}",
+ "]",
+ "},"));
+ //@formatter:on
+
+ Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc);
+
+ List gotLabels = parsed.getMeta().getProfile();
+ assertEquals(2, gotLabels.size());
+ UriType label = gotLabels.get(0);
+ assertEquals("http://foo/Profile1", label.getValue());
+ label = gotLabels.get(1);
+ assertEquals("http://foo/Profile2", label.getValue());
+
+ List tagList = parsed.getMeta().getTag();
+ assertEquals(2, tagList.size());
+ assertEquals("scheme1", tagList.get(0).getSystem());
+ assertEquals("term1", tagList.get(0).getCode());
+ assertEquals("label1", tagList.get(0).getDisplay());
+ assertEquals("scheme2", tagList.get(1).getSystem());
+ assertEquals("term2", tagList.get(1).getCode());
+ assertEquals("label2", tagList.get(1).getDisplay());
+
+ tagList = parsed.getMeta().getSecurity();
+ assertEquals(2, tagList.size());
+ assertEquals("sec_scheme1", tagList.get(0).getSystem());
+ assertEquals("sec_term1", tagList.get(0).getCode());
+ assertEquals("sec_label1", tagList.get(0).getDisplay());
+ assertEquals("sec_scheme2", tagList.get(1).getSystem());
+ assertEquals("sec_term2", tagList.get(1).getCode());
+ assertEquals("sec_label2", tagList.get(1).getDisplay());
+ }
+
+ /**
+ * See #336
+ */
+ @Test
+ public void testEncodeAndParseNullPrimitiveWithExtensions() {
+
+ Patient p = new Patient();
+ p.setId("patid");
+ HumanName name = p.addName();
+ name.addGivenElement().setValue(null).setId("f0").addExtension(new Extension("http://foo", new StringType("FOOEXT0")));
+ name.addGivenElement().setValue("V1").setId("f1").addExtension((Extension) new Extension("http://foo", new StringType("FOOEXT1")).setId("ext1id"));
+ name.addGivenElement(); // this one shouldn't get encoded
+ name.addGivenElement().setValue(null).addExtension(new Extension("http://foo", new StringType("FOOEXT3")));
+ name.setId("nameid");
+
+ String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(output);
+
+ output = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(p);
+ String expected = "{\"resourceType\":\"Patient\",\"id\":\"patid\",\"name\":[{\"id\":\"nameid\",\"given\":[null,\"V1\",null],\"_given\":[{\"id\":\"f0\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT0\"}]},{\"id\":\"f1\",\"extension\":[{\"id\":\"ext1id\",\"url\":\"http://foo\",\"valueString\":\"FOOEXT1\"}]},{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT3\"}]}]}]}";
+ assertEquals(expected, output);
+
+ p = ourCtx.newJsonParser().parseResource(Patient.class, output);
+ assertEquals("patid", p.getIdElement().getIdPart());
+
+ name = p.getName().get(0);
+ assertEquals("nameid", name.getId());
+ assertEquals(3, name.getGiven().size());
+
+ assertEquals(null, name.getGiven().get(0).getValue());
+ assertEquals("V1", name.getGiven().get(1).getValue());
+ assertEquals(null, name.getGiven().get(2).getValue());
+
+ assertEquals("f0", name.getGiven().get(0).getId());
+ assertEquals("f1", name.getGiven().get(1).getId());
+ assertEquals(null, name.getGiven().get(2).getId());
+
+ assertEquals(1, name.getGiven().get(0).getExtension().size());
+ assertEquals("http://foo", name.getGiven().get(0).getExtension().get(0).getUrl());
+ assertEquals("FOOEXT0", ((StringType) name.getGiven().get(0).getExtension().get(0).getValue()).getValue());
+ assertEquals(null, name.getGiven().get(0).getExtension().get(0).getId());
+
+ assertEquals(1, name.getGiven().get(1).getExtension().size());
+ assertEquals("http://foo", name.getGiven().get(1).getExtension().get(0).getUrl());
+ assertEquals("FOOEXT1", ((StringType) name.getGiven().get(1).getExtension().get(0).getValue()).getValue());
+ assertEquals("ext1id", name.getGiven().get(1).getExtension().get(0).getId());
+
+ assertEquals(1, name.getGiven().get(2).getExtension().size());
+ assertEquals("http://foo", name.getGiven().get(2).getExtension().get(0).getUrl());
+ assertEquals("FOOEXT3", ((StringType) name.getGiven().get(2).getExtension().get(0).getValue()).getValue());
+ assertEquals(null, name.getGiven().get(2).getExtension().get(0).getId());
+
+ }
+
+ @Test
+ public void testEncodeAndParseSecurityLabels() {
+ Patient p = new Patient();
+ p.addName().setFamily("FAMILY");
+
+ List labels = new ArrayList();
+ labels.add(new Coding().setSystem("SYSTEM1").setCode("CODE1").setDisplay("DISPLAY1").setVersion("VERSION1"));
+ labels.add(new Coding().setSystem("SYSTEM2").setCode("CODE2").setDisplay("DISPLAY2").setVersion("VERSION2"));
+ p.getMeta().getSecurity().addAll(labels);
+
+ String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+
+ //@formatter:off
+ assertEquals("{\n" +
+ " \"resourceType\": \"Patient\",\n" +
+ " \"meta\": {\n" +
+ " \"security\": [\n" +
+ " {\n" +
+ " \"system\": \"SYSTEM1\",\n" +
+ " \"version\": \"VERSION1\",\n" +
+ " \"code\": \"CODE1\",\n" +
+ " \"display\": \"DISPLAY1\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"system\": \"SYSTEM2\",\n" +
+ " \"version\": \"VERSION2\",\n" +
+ " \"code\": \"CODE2\",\n" +
+ " \"display\": \"DISPLAY2\"\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"name\": [\n" +
+ " {\n" +
+ " \"family\": \"FAMILY\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}", enc.trim());
+ //@formatter:on
+
+ Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc);
+ List gotLabels = parsed.getMeta().getSecurity();
+
+ assertEquals(2, gotLabels.size());
+
+ Coding label = gotLabels.get(0);
+ assertEquals("SYSTEM1", label.getSystem());
+ assertEquals("CODE1", label.getCode());
+ assertEquals("DISPLAY1", label.getDisplay());
+ assertEquals("VERSION1", label.getVersion());
+
+ label = gotLabels.get(1);
+ assertEquals("SYSTEM2", label.getSystem());
+ assertEquals("CODE2", label.getCode());
+ assertEquals("DISPLAY2", label.getDisplay());
+ assertEquals("VERSION2", label.getVersion());
+ }
+
+ @Test
+ public void testEncodeBinaryWithSecurityContext() {
+ Binary bin = new Binary();
+ bin.setContentType("text/plain");
+ bin.setContent("Now is the time".getBytes());
+ Reference securityContext = new Reference();
+ securityContext.setReference("DiagnosticReport/1");
+ bin.setSecurityContext(securityContext);
+ String encoded = ourCtx.newJsonParser().encodeResourceToString(bin);
+ ourLog.info(encoded);
+ assertThat(encoded, containsString("Binary"));
+ assertThat(encoded, containsString("\"contentType\":\"text/plain\""));
+ assertThat(encoded, containsString("\"content\":\"Tm93IGlzIHRoZSB0aW1l\""));
+ assertThat(encoded, containsString("\"securityContext\":{\"reference\":\"DiagnosticReport/1\"}"));
+ }
+
+ @Test
+ public void testEncodeBundleNewBundleNoText() {
+
+ Bundle b = new Bundle();
+
+ Bundle.BundleEntryComponent e = b.addEntry();
+ e.setResource(new Patient());
+
+ String val = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(b);
+ ourLog.info(val);
+ assertThat(val, not(containsString("text")));
+
+ val = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(b);
+ ourLog.info(val);
+ assertThat(val, not(containsString("text")));
+
+ }
+
+ /**
+ * See #326
+ */
+ @Test
+ public void testEncodeContainedResource() {
+ Patient patient = new Patient();
+ patient.getBirthDateElement().setValueAsString("2016-04-05");
+ patient.addExtension().setUrl("test").setValue(new Reference(new Condition()));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ //@formatter:off
+ assertThat(encoded, stringContainsInOrder(
+ "{",
+ "\"resourceType\": \"Patient\",",
+ "\"contained\": [",
+ "{",
+ "\"resourceType\": \"Condition\",",
+ "\"id\": \"1\"",
+ "}",
+ "],",
+ "\"extension\": [",
+ "{",
+ "\"url\": \"test\",",
+ "\"valueReference\": {",
+ "\"reference\": \"#1\"",
+ "}",
+ "}",
+ "],",
+ "\"birthDate\": \"2016-04-05\"",
+ "}"
+ ));
+ //@formatter:on
+ }
+
+ @Test
+ public void testEncodeDoesntIncludeUuidId() {
+ Patient p = new Patient();
+ p.setId(new IdType("urn:uuid:42795ed8-041f-4ebf-b6f4-78ef6f64c2f2"));
+ p.addIdentifier().setSystem("ACME");
+
+ String actual = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
+ assertThat(actual, not(containsString("78ef6f64c2f2")));
+ }
+
+ @Test
+ public void testEncodeEmptyBinary() {
+ String output = ourCtx.newJsonParser().encodeResourceToString(new Binary());
+ assertEquals("{\"resourceType\":\"Binary\"}", output);
+ }
+
+ /**
+ * #158
+ */
+ @Test
+ public void testEncodeEmptyTag() {
+ ArrayList tagList = new ArrayList();
+ tagList.add(new Coding());
+ tagList.add(new Coding().setDisplay("Label"));
+
+ Patient p = new Patient();
+ p.getMeta().getTag().addAll(tagList);
+
+ String encoded = ourCtx.newJsonParser().encodeResourceToString(p);
+ assertThat(encoded, not(containsString("tag")));
+ }
+
+ /**
+ * #158
+ */
+ @Test
+ public void testEncodeEmptyTag2() {
+ ArrayList tagList = new ArrayList();
+ tagList.add(new Coding().setSystem("scheme").setCode("code"));
+ tagList.add(new Coding().setDisplay("Label"));
+
+ Patient p = new Patient();
+ p.getMeta().getTag().addAll(tagList);
+
+ String encoded = ourCtx.newJsonParser().encodeResourceToString(p);
+ assertThat(encoded, containsString("tag"));
+ assertThat(encoded, containsString("scheme"));
+ assertThat(encoded, not(containsString("Label")));
+ }
+
+ /**
+ * #480
+ */
+ @Test
+ public void testEncodeEmptyValue() {
+ QuestionnaireResponse qr = new QuestionnaireResponse();
+ qr.setId("123");
+ qr.getAuthoredElement().setValueAsString("");
+ qr.getItemFirstRep().setLinkIdElement(new StringType());
+ qr.getItemFirstRep().addItem().setLinkIdElement(new StringType(""));
+ qr.getItemFirstRep().addItem().setLinkIdElement(new StringType("LINKID"));
+
+ String encoded = ourCtx.newJsonParser().encodeResourceToString(qr);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder("123"));
+ assertThat(encoded, not(stringContainsInOrder("\"\"")));
+ assertThat(encoded, not(stringContainsInOrder("null")));
+ }
+
+ @Test
+ public void testEncodeExtensionInPrimitiveElement() {
+
+ CapabilityStatement c = new CapabilityStatement();
+ c.getAcceptUnknownElement().addExtension().setUrl("http://foo").setValue(new StringType("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\":\"CapabilityStatement\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}");
+
+ // Now with a value
+ ourLog.info("---------------");
+
+ c = new CapabilityStatement();
+ c.getAcceptUnknownElement().setValue(CapabilityStatement.UnknownContentCode.ELEMENTS);
+ c.getAcceptUnknownElement().addExtension().setUrl("http://foo").setValue(new StringType("AAA"));
+
+ encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c);
+ ourLog.info(encoded);
+
+ encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c);
+ ourLog.info(encoded);
+ assertEquals(encoded, "{\"resourceType\":\"CapabilityStatement\",\"acceptUnknown\":\"elements\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}");
+
+ }
+
+ @Test
+ public void testEncodeExtensionOnRoot() {
+ Patient p = new Patient();
+ p.setId("Patient/B");
+ p
+ .addExtension()
+ .setUrl("http://foo")
+ .setValue(new Reference("Practitioner/A"));
+
+ IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
+ parser.setDontEncodeElements(new HashSet(Arrays.asList("*.id", "*.meta")));
+
+ String encoded = parser.encodeResourceToString(p);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("http://foo"));
+ assertThat(encoded, containsString("Practitioner/A"));
+ }
+
+ @Test
+ public void testEncodeExtensionUndeclaredNonModifier() {
+ Observation obs = new Observation();
+ obs.setId("1");
+ obs.getMeta().addProfile("http://profile");
+ obs.setStatus(Observation.ObservationStatus.FINAL);
+ Extension ext = obs.addExtension();
+ ext.setUrl("http://exturl").setValue(new StringType("ext_url_value"));
+
+ obs.getCode().setText("CODE");
+
+ IParser parser = ourCtx.newJsonParser();
+
+ String output = parser.setPrettyPrint(true).encodeResourceToString(obs);
+ ourLog.info(output);
+
+ //@formatter:off
+ assertThat(output, stringContainsInOrder(
+ "\"id\": \"1\"",
+ "\"meta\"",
+ "\"extension\"",
+ "\"url\": \"http://exturl\"",
+ "\"valueString\": \"ext_url_value\"",
+ "\"code\":"
+ ));
+ assertThat(output, not(stringContainsInOrder(
+ "\"url\": \"http://exturl\"",
+ ",",
+ "\"url\": \"http://exturl\""
+ )));
+ //@formatter:on
+
+ obs = parser.parseResource(Observation.class, output);
+ assertEquals(1, obs.getExtension().size());
+ assertEquals("http://exturl", obs.getExtension().get(0).getUrl());
+ assertEquals("ext_url_value", ((StringType) obs.getExtension().get(0).getValue()).getValue());
+ assertEquals("final", obs.getStatusElement().getValueAsString());
+ assertEquals(Observation.ObservationStatus.FINAL, obs.getStatusElement().getValue());
+
+ }
+
+ @Test
+ public void testEncodeExtensionUndeclaredNonModifierWithChildExtension() {
+ Observation obs = new Observation();
+ obs.setId("1");
+ obs.getMeta().addProfile("http://profile");
+ Extension ext = obs.addExtension();
+ ext.setUrl("http://exturl");
+
+ Extension subExt = ext.addExtension();
+ subExt.setUrl("http://subext").setValue(new StringType("sub_ext_value"));
+
+ obs.getCode().setText("CODE");
+
+ IParser parser = ourCtx.newJsonParser();
+
+ String output = parser.setPrettyPrint(true).encodeResourceToString(obs);
+ ourLog.info(output);
+
+ //@formatter:off
+ assertThat(output, stringContainsInOrder(
+ "\"id\": \"1\"",
+ "\"meta\"",
+ "\"extension\"",
+ "\"url\": \"http://exturl\"",
+ "\"extension\"",
+ "\"url\": \"http://subext\"",
+ "\"valueString\": \"sub_ext_value\"",
+ "\"code\":"
+ ));
+ assertThat(output, not(stringContainsInOrder(
+ "\"url\": \"http://exturl\"",
+ ",",
+ "\"url\": \"http://exturl\""
+ )));
+ //@formatter:on
+
+ obs = parser.parseResource(Observation.class, output);
+ assertEquals(1, obs.getExtension().size());
+ assertEquals("http://exturl", obs.getExtension().get(0).getUrl());
+ assertEquals(1, obs.getExtension().get(0).getExtension().size());
+ assertEquals("http://subext", obs.getExtension().get(0).getExtension().get(0).getUrl());
+ assertEquals("sub_ext_value", ((StringType) obs.getExtension().get(0).getExtension().get(0).getValue()).getValue());
+ }
+
+
+ @Test
+ public void testEncodeHistoryEncodeVersionsAtPath1() {
+ ourCtx = FhirContext.forDstu3();
+
+ assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences());
+
+ Patient p = new Patient();
+ p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1"));
+
+ IParser parser = ourCtx.newJsonParser();
+
+ parser.setDontStripVersionsFromReferencesAtPaths("Patient.managingOrganization");
+ String enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
+ }
+
+ @Test
+ public void testEncodeHistoryEncodeVersionsAtPath2() {
+ ourCtx = FhirContext.forDstu3();
+
+ assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences());
+ assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences());
+
+ Patient p = new Patient();
+ p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1"));
+
+ IParser parser = ourCtx.newJsonParser();
+
+ parser.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference");
+ String enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
+ }
+
+ @Test
+ public void testEncodeHistoryEncodeVersionsAtPath3() {
+ ourCtx = FhirContext.forDstu3();
+
+ assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences());
+
+ AuditEvent auditEvent = new AuditEvent();
+ auditEvent.addEntity().setReference(new Reference("http://foo.com/Organization/2/_history/1"));
+
+ IParser parser = ourCtx.newJsonParser();
+
+ parser.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference");
+ String enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
+
+ parser.setDontStripVersionsFromReferencesAtPaths(new ArrayList());
+ enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
+
+ parser.setDontStripVersionsFromReferencesAtPaths((String[]) null);
+ enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
+
+ parser.setDontStripVersionsFromReferencesAtPaths((List) null);
+ enc = parser.setPrettyPrint(true).encodeResourceToString(auditEvent);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
+ }
+
+ @Test
+ public void testEncodeHistoryEncodeVersionsAtPathUsingOptions() {
+ ourCtx = FhirContext.forDstu3();
+
+ assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences());
+ assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences());
+ assertThat(ourCtx.getParserOptions().getDontStripVersionsFromReferencesAtPaths(), empty());
+
+ Patient p = new Patient();
+ p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1"));
+
+ IParser parser = ourCtx.newJsonParser();
+
+ ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths("Patient.managingOrganization");
+ String enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
+
+ ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(Arrays.asList("Patient.managingOrganization"));
+ enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
+
+ ourCtx.getParserOptions().setDontStripVersionsFromReferencesAtPaths(new HashSet(Arrays.asList("Patient.managingOrganization")));
+ enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
+ }
+
+ @Test
+ public void testEncodeHistoryStripVersionsFromReferences() {
+ ourCtx = FhirContext.forDstu3();
+
+ assertNull(ourCtx.newJsonParser().getStripVersionsFromReferences());
+
+ Patient p = new Patient();
+ p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1"));
+
+ IParser parser = ourCtx.newJsonParser();
+ String enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
+
+ parser.setStripVersionsFromReferences(false);
+ enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
+
+ ourCtx = FhirContext.forDstu3();
+ }
+
+ @Test
+ public void testEncodeHistoryStripVersionsFromReferencesFromContext() {
+ ourCtx = FhirContext.forDstu3();
+
+ assertTrue(ourCtx.getParserOptions().isStripVersionsFromReferences());
+
+ Patient p = new Patient();
+ p.setManagingOrganization(new Reference("http://foo.com/Organization/2/_history/1"));
+
+ IParser parser = ourCtx.newJsonParser();
+ String enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
+
+ ourCtx.getParserOptions().setStripVersionsFromReferences(false);
+ enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2/_history/1\""));
+
+ parser.setStripVersionsFromReferences(true);
+ enc = parser.setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+ assertThat(enc, containsString("\"reference\": \"http://foo.com/Organization/2\""));
+
+ ourCtx = FhirContext.forDstu3();
+ }
+
+ @Test
+ public void testEncodeNarrativeShouldIncludeNamespace() {
+
+ Patient p = new Patient();
+ p.getText().setDivAsString("VALUE");
+
+ String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(output);
+ assertThat(output, containsString("\"div\": \"VALUE\""));
+ }
+
+ @Test
+ public void testEncodeNarrativeShouldIncludeNamespaceWithProcessingInstruction() {
+
+ Patient p = new Patient();
+ p.getText().setDivAsString("VALUE");
+
+ String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(output);
+ assertThat(output, containsString("\"div\": \"VALUE\""));
+ }
+
+ @Test
+ public void testEncodeNarrativeSuppressed() throws Exception {
+ Patient patient = new Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("THE DIV");
+ patient.addName().setFamily("FAMILY");
+ patient.getMaritalStatus().addCoding().setCode("D");
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSuppressNarratives(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("Patient"));
+ assertThat(encoded, stringContainsInOrder(ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM, ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE));
+ assertThat(encoded, not(containsString("text")));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, containsString("maritalStatus"));
+ }
+
+ @Test
+ public void testEncodeParametersWithId() {
+ Parameters reqParms = new Parameters();
+ IdType patient = new IdType(1);
+ reqParms.addParameter().setName("patient").setValue(patient);
+
+ String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(reqParms);
+ ourLog.info(enc);
+
+ assertThat(enc, containsString("\"valueId\": \"1\""));
+ }
+
+ @Test
+ public void testEncodeSummary() {
+ Patient patient = new Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("THE DIV");
+ patient.addName().setFamily("FAMILY");
+ patient.addPhoto().setTitle("green");
+ patient.getMaritalStatus().addCoding().setCode("D");
+
+ ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("Patient"));
+ assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE + "\""));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeSummary2() {
+ Patient patient = new Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("THE DIV");
+ patient.addName().setFamily("FAMILY");
+ patient.getMaritalStatus().addCoding().setCode("D");
+
+ patient.getMeta().addTag().setSystem("foo").setCode("bar");
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).setSummaryMode(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("Patient"));
+ assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\": \"foo\",", "\"code\": \"bar\"", "\"system\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_SYSTEM + "\"",
+ "\"code\": \"" + ca.uhn.fhir.rest.api.Constants.TAG_SUBSETTED_CODE + "\""));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ /**
+ * See #205
+ */
+ @Test
+ public void testEncodeTags() {
+ Patient pt = new Patient();
+ pt.addIdentifier().setSystem("sys").setValue("val");
+
+ pt.getMeta().addTag().setSystem("scheme").setCode("term").setDisplay("display");
+
+ String enc = ourCtx.newJsonParser().encodeResourceToString(pt);
+ ourLog.info(enc);
+
+ assertEquals("{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}",
+ enc);
+
+ }
+
+ /**
+ * See #241
+ */
+ @Test
+ public void testEncodeThenParseShouldNotAddSpuriousId() throws Exception {
+ Condition condition = new Condition().setVerificationStatus(Condition.ConditionVerificationStatus.CONFIRMED);
+ Bundle bundle = new Bundle();
+ Bundle.BundleEntryComponent entry = new Bundle.BundleEntryComponent();
+ entry.setId("123");
+ entry.setResource(condition);
+ bundle.getEntry().add(entry);
+ IParser parser = ourCtx.newJsonParser();
+ String json = parser.encodeResourceToString(bundle);
+ ourLog.info(json);
+ bundle = (Bundle) parser.parseResource(json);
+
+ assertEquals("123", bundle.getEntry().get(0).getId());
+
+ condition = (Condition) bundle.getEntry().get(0).getResource();
+ assertEquals(null, condition.getId());
+ }
+
+ @Test
+ public void testEncodeWithDontEncodeElements() throws Exception {
+ Patient patient = new Patient();
+ patient.setId("123");
+
+ patient.getMeta().addProfile(("http://profile"));
+ patient.addName().setFamily("FAMILY").addGiven("GIVEN");
+ patient.addAddress().addLine("LINE1");
+
+ {
+ IParser p = ourCtx.newJsonParser();
+ p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newJsonParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.meta", "Patient.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newJsonParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.name.family"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("GIVEN"));
+ assertThat(out, not(containsString("FAMILY")));
+ }
+ {
+ IParser p = ourCtx.newJsonParser();
+ p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newJsonParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.meta"));
+ p.setEncodeElements(new HashSet(Arrays.asList("Patient.name")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("id"));
+ assertThat(out, not(containsString("address")));
+ assertThat(out, not(containsString("meta")));
+ }
+ }
+
+ @Test
+ public void testEncodingNullExtension() {
+ Patient p = new Patient();
+ Extension extension = new Extension("http://foo#bar");
+ p.addExtension(extension);
+ String str = ourCtx.newJsonParser().encodeResourceToString(p);
+
+ assertEquals("{\"resourceType\":\"Patient\"}", str);
+
+ extension.setValue(new StringType());
+
+ str = ourCtx.newJsonParser().encodeResourceToString(p);
+ assertEquals("{\"resourceType\":\"Patient\"}", str);
+
+ extension.setValue(new StringType(""));
+
+ str = ourCtx.newJsonParser().encodeResourceToString(p);
+ assertEquals("{\"resourceType\":\"Patient\"}", str);
+
+ }
+
+ /**
+ * See #341
+ */
+ @Test
+ public void testExplanationOfBenefit() {
+ //@formatter:off
+ String input = "{" +
+ " \"resourceType\": \"ExplanationOfBenefit\"," +
+ " \"insurance\": {\n" +
+ " \"coverage\": {\n" +
+ " \"reference\": \"Coverage/123\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"relationship\": {\n" +
+ " \"system\": \"http://hl7.org/fhir/relationship\",\n" +
+ " \"code\": \"1\",\n" +
+ " \"display\": \"self\"\n" +
+ " }\n" +
+ "}";
+ //@formatter:on
+
+ ExplanationOfBenefit eob = ourCtx.newJsonParser().parseResource(ExplanationOfBenefit.class, input);
+ assertEquals(Reference.class, eob.getInsurance().getCoverage().getClass());
+
+ Reference coverage = eob.getInsurance().getCoverage();
+ assertEquals("Coverage/123", coverage.getReference());
+ }
+
+ @Test
+ public void testExponentDoesntGetEncodedAsSuch() {
+ Observation obs = new Observation();
+ obs.setValue(new Quantity().setValue(new BigDecimal("0.000000000000000100")));
+
+ String str = ourCtx.newJsonParser().encodeResourceToString(obs);
+ ourLog.info(str);
+
+ assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}", str);
+ }
+
+ @Test
+ public void testExponentParseWorks() {
+ String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0000000000000001}}";
+ Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, input);
+
+ assertEquals("0.0000000000000001", ((Quantity) obs.getValue()).getValueElement().getValueAsString());
+
+ String str = ourCtx.newJsonParser().encodeResourceToString(obs);
+ ourLog.info(str);
+ assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0000000000000001}}", str);
+ }
+
+ /**
+ * #516
+ */
+ @Test(expected = DataFormatException.class)
+ public void testInvalidEnumValue() {
+ String res = "{ \"resourceType\": \"ValueSet\", \"url\": \"http://sample/ValueSet/education-levels\", \"version\": \"1\", \"name\": \"Education Levels\", \"status\": \"draft\", \"compose\": { \"include\": [ { \"filter\": [ { \"property\": \"n\", \"op\": \"n\", \"value\": \"365460000\" } ], \"system\": \"http://snomed.info/sct\" } ], \"exclude\": [ { \"concept\": [ { \"code\": \"224298008\" }, { \"code\": \"365460000\" }, { \"code\": \"473462005\" }, { \"code\": \"424587006\" } ], \"system\": \"http://snomed.info/sct\" } ] }, \"description\": \"A selection of Education Levels\", \"text\": { \"status\": \"generated\", \"div\": \"Education Levels
http://csiro.au/ValueSet/education-levelsA selection of Education Levels
\" }, \"experimental\": true, \"date\": \"2016-07-26\" }";
+ IParser parser = ourCtx.newJsonParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+ ValueSet parsed = parser.parseResource(ValueSet.class, res);
+ fail("DataFormat Invalid attribute exception should be thrown");
+ }
+
+ /**
+ * #65
+ */
+ @Test
+ public void testJsonPrimitiveWithExtensionEncoding() {
+
+ QuestionnaireResponse parsed = new QuestionnaireResponse();
+ parsed.addItem().setLinkId("value123");
+ parsed.getItem().get(0).getLinkIdElement().addExtension(new Extension("http://123", new StringType("HELLO")));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(parsed);
+ ourLog.info(encoded);
+ assertThat(encoded, containsString("{\"linkId\":\"value123\",\"_linkId\":{\"extension\":[{\"url\":\"http://123\",\"valueString\":\"HELLO\"}]}}"));
+
+ }
+
+ @Test
+ public void testLinkage() {
+ Linkage l = new Linkage();
+ l.addItem().getResource().setDisplay("FOO");
+ String out = ourCtx.newXmlParser().encodeResourceToString(l);
+ ourLog.info(out);
+ assertEquals(" ", out);
+ }
+
+
+ @Test
+ public void testOmitResourceId() {
+ Patient p = new Patient();
+ p.setId("123");
+ p.addName().setFamily("ABC");
+
+ assertThat(ourCtx.newJsonParser().encodeResourceToString(p), stringContainsInOrder("123", "ABC"));
+ assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), containsString("ABC"));
+ assertThat(ourCtx.newJsonParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123")));
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() {
+ try {
+ String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}";
+ ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false);
+ Bundle bundle = (Bundle) ourCtx.newJsonParser().parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ Patient o1 = (Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertFalse(o1Id.hasBaseUrl());
+ assertEquals("Patient", o1Id.getResourceType());
+ assertEquals("patxuzos", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ } finally {
+ // ensure we cleanup ourCtx so other tests continue to work
+ ourCtx = FhirContext.forDstu3();
+ }
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() {
+ try {
+ String tmp = "{\"resourceType\":\"Bundle\",\"entry\":[{\"fullUrl\":\"http://lalaland.org/patient/pat1\",\"resource\":{\"resourceType\":\"Patient\",\"id\":\"patxuzos\"}}]}";
+ Bundle bundle = (Bundle) ourCtx.newJsonParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ Patient o1 = (Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertFalse(o1Id.hasBaseUrl());
+ assertEquals("Patient", o1Id.getResourceType());
+ assertEquals("patxuzos", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ } finally {
+ // ensure we cleanup ourCtx so other tests continue to work
+ ourCtx = FhirContext.forDstu3();
+ }
+ }
+
+
+ @Test
+ public void testParseAndEncodeBundleWithUuidBase() {
+ //@formatter:off
+ String input =
+ "{\n" +
+ " \"resourceType\":\"Bundle\",\n" +
+ " \"type\":\"document\",\n" +
+ " \"entry\":[\n" +
+ " {\n" +
+ " \"fullUrl\":\"urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57\",\n" +
+ " \"resource\":{\n" +
+ " \"resourceType\":\"Composition\",\n" +
+ " \"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\",\n" +
+ " \"meta\":{\n" +
+ " \"lastUpdated\":\"2013-05-28T22:12:21Z\"\n" +
+ " },\n" +
+ " \"text\":{\n" +
+ " \"status\":\"generated\",\n" +
+ " \"div\":\"Generated Narrative with Details
id: 180f219f-97a8-486d-99d9-ed631fe4fc57
meta:
date: Feb 1, 2013 12:30:02 PM
type: Discharge Summary from Responsible Clinician (Details : {LOINC code '28655-9' = 'Physician attending Discharge summary)
status: final
confidentiality: N
author: Doctor Dave. Generated Summary: 23; Adam Careful
encounter: http://fhir.healthintersections.com.au/open/Encounter/doc-example
\"\n" +
+ " },\n" +
+ " \"date\":\"2013-02-01T12:30:02Z\",\n" +
+ " \"type\":{\n" +
+ " \"coding\":[\n" +
+ " {\n" +
+ " \"system\":\"http://loinc.org\",\n" +
+ " \"code\":\"28655-9\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"text\":\"Discharge Summary from Responsible Clinician\"\n" +
+ " },\n" +
+ " \"status\":\"final\",\n" +
+ " \"confidentiality\":\"N\",\n" +
+ " \"subject\":{\n" +
+ " \"reference\":\"http://fhir.healthintersections.com.au/open/Patient/d1\",\n" +
+ " \"display\":\"Eve Everywoman\"\n" +
+ " },\n" +
+ " \"author\":[\n" +
+ " {\n" +
+ " \"reference\":\"Practitioner/example\",\n" +
+ " \"display\":\"Doctor Dave\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"encounter\":{\n" +
+ " \"reference\":\"http://fhir.healthintersections.com.au/open/Encounter/doc-example\"\n" +
+ " },\n" +
+ " \"section\":[\n" +
+ " {\n" +
+ " \"title\":\"Reason for admission\",\n" +
+ " \"content\":{\n" +
+ " \"reference\":\"urn:uuid:d0dd51d3-3ab2-4c84-b697-a630c3e40e7a\"\n" +
+ " }\n" +
+ " },\n" +
+ " {\n" +
+ " \"title\":\"Medications on Discharge\",\n" +
+ " \"content\":{\n" +
+ " \"reference\":\"urn:uuid:673f8db5-0ffd-4395-9657-6da00420bbc1\"\n" +
+ " }\n" +
+ " },\n" +
+ " {\n" +
+ " \"title\":\"Known allergies\",\n" +
+ " \"content\":{\n" +
+ " \"reference\":\"urn:uuid:68f86194-e6e1-4f65-b64a-5314256f8d7b\"\n" +
+ " }\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ " }" +
+ " ]" +
+ "}";
+ //@formatter:on
+
+ Bundle parsed = ourCtx.newJsonParser().parseResource(Bundle.class, input);
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
+ ourLog.info(encoded);
+
+ assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+ assertEquals(null, parsed.getEntry().get(0).getResource().getIdElement().getBaseUrl());
+ assertEquals("urn:uuid:180f219f-97a8-486d-99d9-ed631fe4fc57", parsed.getEntry().get(0).getResource().getIdElement().getIdPart());
+ assertThat(encoded, not(containsString("\"id\":\"180f219f-97a8-486d-99d9-ed631fe4fc57\"")));
+ }
+
+ @Test
+ public void testParseAndEncodeComments() {
+ //@formatter:off
+ String input = "{\n" +
+ " \"resourceType\": \"Patient\",\n" +
+ " \"id\": \"pat1\",\n" +
+ " \"text\": {\n" +
+ " \"status\": \"generated\",\n" +
+ " \"div\": \"\\n \\n Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321
\\n \\n \"\n" +
+ " },\n" +
+ " \"identifier\": [\n" +
+ " {\n" +
+ " \"fhir_comments\":[\"identifier comment 1\",\"identifier comment 2\"],\n" +
+ " \"use\": \"usual\",\n" +
+ " \"_use\": {\n" +
+ " \"fhir_comments\":[\"use comment 1\",\"use comment 2\"]\n" +
+ " },\n" +
+ " \"type\": {\n" +
+ " \"coding\": [\n" +
+ " {\n" +
+ " \"system\": \"http://hl7.org/fhir/v2/0203\",\n" +
+ " \"code\": \"MR\"\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"system\": \"urn:oid:0.1.2.3.4.5.6.7\",\n" +
+ " \"value\": \"654321\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"active\": true" +
+ "}";
+ //@formatter:off
+
+ Patient res = ourCtx.newJsonParser().parseResource(Patient.class, input);
+ res.getFormatCommentsPre();
+ assertEquals("Patient/pat1", res.getId());
+ assertEquals("654321", res.getIdentifier().get(0).getValue());
+ assertEquals(true, res.getActive());
+
+ assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2"));
+ assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2"));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res);
+ ourLog.info(encoded);
+
+ //@formatter:off
+ assertThat(encoded, stringContainsInOrder(
+ "\"identifier\": [",
+ "{",
+ "\"fhir_comments\":",
+ "[",
+ "\"identifier comment 1\"",
+ ",",
+ "\"identifier comment 2\"",
+ "]",
+ "\"use\": \"usual\",",
+ "\"_use\": {",
+ "\"fhir_comments\":",
+ "[",
+ "\"use comment 1\"",
+ ",",
+ "\"use comment 2\"",
+ "]",
+ "},",
+ "\"type\""
+ ));
+ //@formatter:off
+ }
+
+ @Test
+ public void testParseBundleWithBinary() {
+ Binary patient = new Binary();
+ patient.setId(new IdType("http://base/Binary/11/_history/22"));
+ patient.setContentType("foo");
+ patient.setContent(new byte[]{1, 2, 3, 4});
+
+ String val = ourCtx.newJsonParser().encodeResourceToString(patient);
+
+ String expected = "{\"resourceType\":\"Binary\",\"id\":\"11\",\"meta\":{\"versionId\":\"22\"},\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}";
+ ourLog.info("Expected: {}", expected);
+ ourLog.info("Actual : {}", val);
+ assertEquals(expected, val);
+ }
+
+ /**
+ * #480
+ */
+ @Test
+ public void testParseEmptyValue() {
+ String input = "{\"resourceType\":\"QuestionnaireResponse\",\"id\":\"123\",\"authored\":\"\",\"group\":{\"linkId\":\"\"}}";
+ IParser parser = ourCtx.newJsonParser();
+
+ parser.setParserErrorHandler(new LenientErrorHandler().setErrorOnInvalidValue(false));
+ QuestionnaireResponse qr = parser.parseResource(QuestionnaireResponse.class, input);
+
+ assertEquals("QuestionnaireResponse/123", qr.getIdElement().getValue());
+ assertEquals(null, qr.getAuthored());
+ assertEquals(null, qr.getAuthoredElement().getValue());
+ assertEquals(null, qr.getAuthoredElement().getValueAsString());
+ assertEquals(null, qr.getItemFirstRep().getLinkId());
+ assertEquals(null, qr.getItemFirstRep().getLinkIdElement().getValue());
+ }
+
+ /**
+ * See #342
+ */
+ @Test()
+ public void testParseInvalid() {
+ try {
+ ourCtx.newJsonParser().parseResource("FOO");
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: 'F' (must be '{')", e.getMessage());
+ }
+ try {
+ ourCtx.newJsonParser().parseResource("[\"aaa\"]");
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: '[' (must be '{')", e.getMessage());
+ }
+
+ assertEquals(Bundle.class, ourCtx.newJsonParser().parseResource(" {\"resourceType\" : \"Bundle\"}").getClass());
+
+ }
+
+ /**
+ * See #414
+ */
+ @Test
+ public void testParseJsonExtensionWithoutUrl() {
+ //@formatter:off
+ String input =
+ "{\"resourceType\":\"Patient\"," +
+ "\"extension\":[ {\"valueDateTime\":\"2011-01-02T11:13:15\"} ]" +
+ "}";
+ //@formatter:on
+
+ IParser parser = ourCtx.newJsonParser();
+ parser.setParserErrorHandler(new LenientErrorHandler());
+ Patient parsed = (Patient) parser.parseResource(input);
+ assertEquals(1, parsed.getExtension().size());
+ assertEquals(null, parsed.getExtension().get(0).getUrl());
+ assertEquals("2011-01-02T11:13:15", parsed.getExtension().get(0).getValueAsPrimitive().getValueAsString());
+
+ try {
+ parser = ourCtx.newJsonParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+ parser.parseResource(input);
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Resource is missing required element 'url' in parent element 'extension'", e.getMessage());
+ }
+
+ }
+
+ /**
+ * See #414
+ */
+ @Test
+ public void testParseJsonModifierExtensionWithoutUrl() {
+ //@formatter:off
+ String input =
+ "{\"resourceType\":\"Patient\"," +
+ "\"modifierExtension\":[ {\"valueDateTime\":\"2011-01-02T11:13:15\"} ]" +
+ "}";
+ //@formatter:on
+
+ IParser parser = ourCtx.newJsonParser();
+ parser.setParserErrorHandler(new LenientErrorHandler());
+ Patient parsed = (Patient) parser.parseResource(input);
+ assertEquals(1, parsed.getModifierExtension().size());
+ assertEquals(null, parsed.getModifierExtension().get(0).getUrl());
+ assertEquals("2011-01-02T11:13:15", parsed.getModifierExtension().get(0).getValueAsPrimitive().getValueAsString());
+
+ try {
+ parser = ourCtx.newJsonParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+ parser.parseResource(input);
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Resource is missing required element 'url' in parent element 'modifierExtension'", e.getMessage());
+ }
+
+ }
+
+
+ /**
+ * See #484
+ */
+ @Test
+ public void testParseNarrativeWithEmptyDiv() {
+ String input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"\"}}";
+ Basic basic = ourCtx.newJsonParser().parseResource(Basic.class, input);
+ assertEquals(null, basic.getText().getDivAsString());
+
+ input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\"\"}}";
+ basic = ourCtx.newJsonParser().parseResource(Basic.class, input);
+ assertEquals(null, basic.getText().getDivAsString());
+
+ input = "{\"resourceType\":\"Basic\",\"id\":\"1\",\"text\":{\"status\":\"generated\",\"div\":\" \"}}";
+ basic = ourCtx.newJsonParser().parseResource(Basic.class, input);
+ assertEquals(" ", basic.getText().getDivAsString());
+
+ }
+
+ /**
+ * See #163
+ */
+ @Test
+ public void testParseResourceType() {
+ IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true);
+
+ // Patient
+ Patient patient = new Patient();
+ String patientId = UUID.randomUUID().toString();
+ patient.setId(new IdType("Patient", patientId));
+ patient.addName().addGiven("John").setFamily("Smith");
+ patient.setGender(Enumerations.AdministrativeGender.MALE);
+ patient.setBirthDateElement(new DateType("1987-04-16"));
+
+ // Bundle
+ Bundle bundle = new Bundle();
+ bundle.setType(Bundle.BundleType.COLLECTION);
+ bundle.addEntry().setResource(patient);
+
+ String bundleText = jsonParser.encodeResourceToString(bundle);
+ ourLog.info(bundleText);
+
+ Bundle reincarnatedBundle = jsonParser.parseResource(Bundle.class, bundleText);
+ Patient reincarnatedPatient = (Patient) reincarnatedBundle.getEntry().get(0).getResource();
+
+ assertEquals("Patient", patient.getIdElement().getResourceType());
+ assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType());
+ }
+
+ /**
+ * See #207
+ */
+ @Test
+ public void testParseResourceWithInvalidType() {
+ String input = "{" + "\"resourceType\":\"Patient\"," + "\"contained\":[" + " {" + " \"rezType\":\"Organization\"" + " }" + " ]" + "}";
+
+ IParser jsonParser = ourCtx.newJsonParser().setPrettyPrint(true);
+ try {
+ jsonParser.parseResource(input);
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Missing required element 'resourceType' from JSON resource object, unable to parse", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testParseWithPrecision() {
+ String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}";
+ Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, input);
+
+ DecimalType valueElement = ((Quantity) obs.getValue()).getValueElement();
+ assertEquals("0.000000000000000100", valueElement.getValueAsString());
+
+ String str = ourCtx.newJsonParser().encodeResourceToString(obs);
+ ourLog.info(str);
+ assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}", str);
+ }
+
+ @Test(expected = DataFormatException.class)
+ public void testParseWithTrailingContent() throws Exception {
+ //@formatter:off
+ String bundle = "{\n" +
+ " \"resourceType\" : \"Bundle\",\n" +
+ " \"total\" : 1\n" +
+ "}}";
+ //@formatter:on
+
+ Bundle b = ourCtx.newJsonParser().parseResource(Bundle.class, bundle);
+ }
+
+ /**
+ * See #344
+ */
+ @Test
+ public void testParserIsCaseSensitive() {
+ Observation obs = new Observation();
+ SampledData data = new SampledData();
+ data.setData("1 2 3");
+ data.setOrigin((SimpleQuantity) new SimpleQuantity().setValue(0L));
+ data.setPeriod(1000L);
+ obs.setValue(data);
+
+ IParser p = ourCtx.newJsonParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler());
+ String encoded = p.encodeResourceToString(obs);
+ ourLog.info(encoded);
+
+ p.parseResource(encoded);
+
+ try {
+ p.parseResource(encoded.replace("Observation", "observation"));
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'", e.getMessage());
+ }
+
+ try {
+ p.parseResource(encoded.replace("valueSampledData", "valueSampleddata"));
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Unknown element 'valueSampleddata' found during parse", e.getMessage());
+ }
+ }
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java
new file mode 100644
index 00000000000..4f1194afe09
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/Dstu3XmlParserTest.java
@@ -0,0 +1,3235 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.UUID;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.parser.LenientErrorHandler;
+import ca.uhn.fhir.parser.StrictErrorHandler;
+import com.google.common.collect.Sets;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.hamcrest.core.StringContains;
+import org.hamcrest.text.StringContainsInOrder;
+import org.hl7.fhir.dstu3.model.Address;
+import org.hl7.fhir.dstu3.model.AllergyIntolerance;
+import org.hl7.fhir.dstu3.model.Annotation;
+import org.hl7.fhir.dstu3.model.Appointment;
+import org.hl7.fhir.dstu3.model.AuditEvent;
+import org.hl7.fhir.dstu3.model.Binary;
+import org.hl7.fhir.dstu3.model.BooleanType;
+import org.hl7.fhir.dstu3.model.Bundle;
+import org.hl7.fhir.dstu3.model.CodeType;
+import org.hl7.fhir.dstu3.model.CodeableConcept;
+import org.hl7.fhir.dstu3.model.Coding;
+import org.hl7.fhir.dstu3.model.Composition;
+import org.hl7.fhir.dstu3.model.ConceptMap;
+import org.hl7.fhir.dstu3.model.Condition;
+import org.hl7.fhir.dstu3.model.ContactPoint;
+import org.hl7.fhir.dstu3.model.DataElement;
+import org.hl7.fhir.dstu3.model.DateTimeType;
+import org.hl7.fhir.dstu3.model.DateType;
+import org.hl7.fhir.dstu3.model.DiagnosticReport;
+import org.hl7.fhir.dstu3.model.DocumentManifest;
+import org.hl7.fhir.dstu3.model.Duration;
+import org.hl7.fhir.dstu3.model.ElementDefinition;
+import org.hl7.fhir.dstu3.model.Encounter;
+import org.hl7.fhir.dstu3.model.EnumFactory;
+import org.hl7.fhir.dstu3.model.Enumeration;
+import org.hl7.fhir.dstu3.model.Enumerations;
+import org.hl7.fhir.dstu3.model.Extension;
+import org.hl7.fhir.dstu3.model.GuidanceResponse;
+import org.hl7.fhir.dstu3.model.HumanName;
+import org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.dstu3.model.Identifier;
+import org.hl7.fhir.dstu3.model.InstantType;
+import org.hl7.fhir.dstu3.model.Location;
+import org.hl7.fhir.dstu3.model.Medication;
+import org.hl7.fhir.dstu3.model.MedicationRequest;
+import org.hl7.fhir.dstu3.model.MedicationStatement;
+import org.hl7.fhir.dstu3.model.Observation;
+import org.hl7.fhir.dstu3.model.Organization;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.dstu3.model.Practitioner;
+import org.hl7.fhir.dstu3.model.PrimitiveType;
+import org.hl7.fhir.dstu3.model.ProcedureRequest;
+import org.hl7.fhir.dstu3.model.Quantity;
+import org.hl7.fhir.dstu3.model.Reference;
+import org.hl7.fhir.dstu3.model.Resource;
+import org.hl7.fhir.dstu3.model.SampledData;
+import org.hl7.fhir.dstu3.model.SimpleQuantity;
+import org.hl7.fhir.dstu3.model.StringType;
+import org.hl7.fhir.dstu3.model.UriType;
+import org.hl7.fhir.dstu3.model.ValueSet;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.xmlunit.builder.DiffBuilder;
+import org.xmlunit.builder.Input;
+import org.xmlunit.diff.ComparisonControllers;
+import org.xmlunit.diff.DefaultNodeMatcher;
+import org.xmlunit.diff.Diff;
+import org.xmlunit.diff.ElementSelectors;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_DSTU3;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class Dstu3XmlParserTest {
+
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Dstu3XmlParserTest.class);
+ private FhirContext ourCtx = FhirContext.forDstu3();
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ WRAP.option(),
+ HAPI_FHIR_DSTU3.option(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ mavenBundle().groupId("org.xmlunit").artifactId("xmlunit-core").versionAsInProject(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+
+ @Test
+ public void testBaseUrlFooResourceCorrectlySerializedInExtensionValueReference() {
+ String refVal = "http://my.org/FooBar";
+
+ Patient fhirPat = new Patient();
+ fhirPat.addExtension().setUrl("x1").setValue(new Reference(refVal));
+
+ IParser parser = ourCtx.newXmlParser();
+
+ String output = parser.encodeResourceToString(fhirPat);
+ System.out.println("output: " + output);
+
+ // Deserialize then check that valueReference value is still correct
+ fhirPat = parser.parseResource(Patient.class, output);
+
+ List extlst = fhirPat.getExtensionsByUrl("x1");
+ Assert.assertEquals(1, extlst.size());
+ Assert.assertEquals(refVal, ((Reference) extlst.get(0).getValue()).getReference());
+ }
+
+ /**
+ * See #544
+ */
+ @Test
+ public void testBundleStitchReferencesByUuid() throws Exception {
+ Bundle bundle = new Bundle();
+
+ DocumentManifest dm = new DocumentManifest();
+ dm.getSubject().setReference("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3");
+ bundle.addEntry().setResource(dm);
+
+ Patient patient = new Patient();
+ patient.addName().setFamily("FAMILY");
+ bundle.addEntry().setResource(patient).setFullUrl("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3");
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(bundle);
+ ourLog.info(encoded);
+
+ bundle = ourCtx.newXmlParser().parseResource(Bundle.class, encoded);
+ dm = (DocumentManifest) bundle.getEntry().get(0).getResource();
+
+ assertEquals("urn:uuid:96e85cca-9797-45d6-834a-c4eb27f331d3", dm.getSubject().getReference());
+
+ Patient subject = (Patient) dm.getSubject().getResource();
+ assertNotNull(subject);
+ assertEquals("FAMILY", subject.getNameFirstRep().getFamily());
+ }
+
+ @Test
+ public void testBundleWithBinary() {
+
+ String bundle = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, bundle);
+ assertEquals(1, b.getEntry().size());
+
+ Binary bin = (Binary) b.getEntry().get(0).getResource();
+ assertArrayEquals(new byte[]{1, 2, 3, 4}, bin.getContent());
+
+ }
+
+
+ @Test
+ public void testContainedResourceInExtensionUndeclared() {
+ Patient p = new Patient();
+ p.addName().setFamily("PATIENT");
+
+ Organization o = new Organization();
+ o.setName("ORG");
+ p.addExtension(new Extension("urn:foo", new Reference(o)));
+
+ String str = ourCtx.newXmlParser().encodeResourceToString(p);
+ ourLog.info(str);
+
+ p = ourCtx.newXmlParser().parseResource(Patient.class, str);
+ assertEquals("PATIENT", p.getName().get(0).getFamily());
+
+ List exts = p.getExtensionsByUrl("urn:foo");
+ assertEquals(1, exts.size());
+ Reference rr = (Reference) exts.get(0).getValue();
+ o = (Organization) rr.getResource();
+ assertEquals("ORG", o.getName());
+ }
+
+ @Test(expected = DataFormatException.class)
+ public void testContainedResourceWithNoId() throws IOException {
+ String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_contained_with_no_id.xml"), StandardCharsets.UTF_8);
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+ parser.parseResource(Bundle.class, string);
+ }
+
+ @Test()
+ public void testContainedResourceWithNoIdLenient() throws IOException {
+ String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_contained_with_no_id.xml"), StandardCharsets.UTF_8);
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new LenientErrorHandler());
+ parser.parseResource(Bundle.class, string);
+ }
+
+ /**
+ * Test for the url generated based on the server config
+ */
+ @Test
+ public void testCustomUrlExtension() {
+ final String expected = " ";
+
+ final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
+ patient.setPetName(new StringType("myName"));
+
+ final IParser xmlParser = ourCtx.newXmlParser();
+ xmlParser.setServerBaseUrl("http://www.example.com");
+
+ final String parsedPatient = xmlParser.encodeResourceToString(patient);
+ System.out.println(parsedPatient);
+ assertEquals(expected, parsedPatient);
+
+ // Parse with string
+ MyPatientWithCustomUrlExtension newPatient = xmlParser.parseResource(MyPatientWithCustomUrlExtension.class, parsedPatient);
+ assertEquals("myName", newPatient.getPetName().getValue());
+
+ // Parse with stream
+ newPatient = xmlParser.parseResource(MyPatientWithCustomUrlExtension.class, new StringReader(parsedPatient));
+ assertEquals("myName", newPatient.getPetName().getValue());
+
+ // Check no NPE if base server not configure
+ newPatient = ourCtx.newXmlParser().parseResource(MyPatientWithCustomUrlExtension.class, new StringReader(parsedPatient));
+ assertNull("myName", newPatient.getPetName().getValue());
+ assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue());
+ }
+
+ @Test
+ public void testCustomUrlExtensioninBundle() {
+ final String expected = " ";
+
+ final MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
+ patient.setPetName(new StringType("myName"));
+
+ final Bundle bundle = new Bundle();
+ final Bundle.BundleEntryComponent entry = new Bundle.BundleEntryComponent();
+ entry.setResource(patient);
+ bundle.addEntry(entry);
+
+ final IParser xmlParser = ourCtx.newXmlParser();
+ xmlParser.setServerBaseUrl("http://www.example.com");
+
+ final String parsedBundle = xmlParser.encodeResourceToString(bundle);
+ System.out.println(parsedBundle);
+ assertEquals(expected, parsedBundle);
+
+ // Parse with string
+ Bundle newBundle = xmlParser.parseResource(Bundle.class, parsedBundle);
+ assertNotNull(newBundle);
+ assertEquals(1, newBundle.getEntry().size());
+ Patient newPatient = (Patient) newBundle.getEntry().get(0).getResource();
+ assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue());
+
+ // Parse with stream
+ newBundle = xmlParser.parseResource(Bundle.class, new StringReader(parsedBundle));
+ assertNotNull(newBundle);
+ assertEquals(1, newBundle.getEntry().size());
+ newPatient = (Patient) newBundle.getEntry().get(0).getResource();
+ assertEquals("myName", ((StringType) newPatient.getExtensionsByUrl("http://www.example.com/petname").get(0).getValue()).getValue());
+
+ }
+
+ @Test
+ public void testDuration() {
+ Encounter enc = new Encounter();
+ Duration duration = new Duration();
+ duration.setUnit("day").setValue(123L);
+ enc.setLength(duration);
+
+ String str = ourCtx.newXmlParser().encodeResourceToString(enc);
+ ourLog.info(str);
+
+ assertThat(str, not(containsString("meta")));
+ assertThat(str, containsString(" "));
+ }
+
+ @Test
+ public void testEncodeAndParseBundleWithResourceRefs() {
+
+ Patient pt = new Patient();
+ pt.setId("patid");
+ pt.addName().setFamily("PATIENT");
+
+ Organization org = new Organization();
+ org.setId("orgid");
+ org.setName("ORG");
+ pt.getManagingOrganization().setResource(org);
+
+ Bundle bundle = new Bundle();
+ bundle.addEntry().setResource(pt);
+ bundle.addEntry().setResource(org);
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(bundle);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder(
+ "",
+ "",
+ "",
+ " "));
+
+ bundle = ourCtx.newXmlParser().parseResource(Bundle.class, encoded);
+ pt = (Patient) bundle.getEntry().get(0).getResource();
+ org = (Organization) bundle.getEntry().get(1).getResource();
+
+ assertEquals("Organization/orgid", org.getIdElement().getValue());
+ assertEquals("Organization/orgid", pt.getManagingOrganization().getReferenceElement().getValue());
+ assertSame(org, pt.getManagingOrganization().getResource());
+ }
+
+ @Test
+ public void testEncodeAndParseCompositeExtension() {
+ PatientWithCustomCompositeExtension pat = new PatientWithCustomCompositeExtension();
+ pat.setId("123");
+ pat.setFooParentExtension(new PatientWithCustomCompositeExtension.FooParentExtension());
+ pat.getFooParentExtension().setChildA(new StringType("ValueA"));
+ pat.getFooParentExtension().setChildB(new StringType("ValueB"));
+
+ String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(pat);
+ ourLog.info(enc);
+
+ pat = ourCtx.newXmlParser().parseResource(PatientWithCustomCompositeExtension.class, enc);
+
+ assertEquals("ValueA", pat.getFooParentExtension().getChildA().getValue());
+ assertEquals("ValueB", pat.getFooParentExtension().getChildB().getValue());
+ }
+
+ @Test
+ public void testEncodeAndParseContained() {
+ IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
+
+ // Create an organization, note that the organization does not have an ID
+ Organization org = new Organization();
+ org.getNameElement().setValue("Contained Test Organization");
+
+ // Create a patient
+ Patient patient = new Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("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
+ Bundle b = new Bundle();
+ b.addEntry().setResource(patient);
+
+ // Encode the bundle
+ encoded = xmlParser.encodeResourceToString(b);
+ ourLog.info(encoded);
+ assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", " ")));
+ 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());
+
+ assertNotNull(patient.getManagingOrganization().getResource());
+ org = (Organization) patient.getManagingOrganization().getResource();
+ assertEquals("#1", org.getIdElement().getValue());
+ assertEquals("Contained Test Organization", org.getName());
+
+ // 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().clear();
+ patient.getManagingOrganization().setReference((String) 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().clear();
+ patient.getManagingOrganization().setReference((String) null);
+ patient.getManagingOrganization().getResource().setId(("#333"));
+ encoded = xmlParser.encodeResourceToString(patient);
+ ourLog.info(encoded);
+ assertThat(encoded, stringContainsInOrder(Arrays.asList("", "", " ", "")));
+ assertThat(encoded, not(stringContainsInOrder(Arrays.asList("", ""))));
+
+ }
+
+ @Test
+ public void testEncodeAndParseContainedCustomTypes() {
+ ourCtx = FhirContext.forDstu3();
+ ourCtx.setDefaultTypeForProfile(CustomObservation.PROFILE, CustomObservation.class);
+ ourCtx.setDefaultTypeForProfile(CustomDiagnosticReport.PROFILE, CustomDiagnosticReport.class);
+
+ CustomObservation obs = new CustomObservation();
+ obs.setStatus(Observation.ObservationStatus.FINAL);
+
+ CustomDiagnosticReport dr = new CustomDiagnosticReport();
+ dr.setStatus(DiagnosticReport.DiagnosticReportStatus.FINAL);
+ dr.addResult().setResource(obs);
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setPrettyPrint(true);
+
+ String output = parser.encodeResourceToString(dr);
+ ourLog.info(output);
+
+ assertThat(output, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " "));
+
+ /*
+ * Now PARSE!
+ */
+
+ dr = (CustomDiagnosticReport) parser.parseResource(output);
+ assertEquals(DiagnosticReport.DiagnosticReportStatus.FINAL, dr.getStatus());
+
+ assertEquals("#1", dr.getResult().get(0).getReference());
+ obs = (CustomObservation) dr.getResult().get(0).getResource();
+ assertEquals(Observation.ObservationStatus.FINAL, obs.getStatus());
+
+ ourCtx = null;
+ }
+
+ @Test
+ public void testEncodeAndParseContainedNonCustomTypes() {
+ ourCtx = FhirContext.forDstu3();
+
+ Observation obs = new Observation();
+ obs.setStatus(Observation.ObservationStatus.FINAL);
+
+ DiagnosticReport dr = new DiagnosticReport();
+ dr.setStatus(DiagnosticReport.DiagnosticReportStatus.FINAL);
+ dr.addResult().setResource(obs);
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setPrettyPrint(true);
+
+ String output = parser.encodeResourceToString(dr);
+ ourLog.info(output);
+
+ assertThat(output, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " "));
+
+ /*
+ * Now PARSE!
+ */
+
+ dr = (DiagnosticReport) parser.parseResource(output);
+ assertEquals(DiagnosticReport.DiagnosticReportStatus.FINAL, dr.getStatus());
+
+ assertEquals("#1", dr.getResult().get(0).getReference());
+ obs = (Observation) dr.getResult().get(0).getResource();
+ assertEquals(Observation.ObservationStatus.FINAL, obs.getStatus());
+
+ ourCtx = null;
+ }
+
+ @Test
+ public void testEncodeAndParseExtensionOnCode() {
+ Organization o = new Organization();
+ o.setName("ORG");
+ o.addExtension(new Extension("urn:foo", new CodeType("acode")));
+
+ String str = ourCtx.newXmlParser().encodeResourceToString(o);
+ ourLog.info(str);
+ assertThat(str, containsString(""));
+
+ o = ourCtx.newXmlParser().parseResource(Organization.class, str);
+
+ List exts = o.getExtensionsByUrl("urn:foo");
+ assertEquals(1, exts.size());
+ CodeType code = (CodeType) exts.get(0).getValue();
+ assertEquals("acode", code.getValue());
+
+ }
+
+ @Test
+ public void testEncodeAndParseExtensionOnReference() {
+ DataElement de = new DataElement();
+ ElementDefinition.ElementDefinitionBindingComponent b = de.addElement().getBinding();
+ b.setDescription("BINDING");
+
+ Organization o = new Organization();
+ o.setName("ORG");
+ b.addExtension(new Extension("urn:foo", new Reference(o)));
+
+ String str = ourCtx.newXmlParser().encodeResourceToString(de);
+ ourLog.info(str);
+
+ de = ourCtx.newXmlParser().parseResource(DataElement.class, str);
+ b = de.getElement().get(0).getBinding();
+ assertEquals("BINDING", b.getDescription());
+
+ List exts = b.getExtensionsByUrl("urn:foo");
+ assertEquals(1, exts.size());
+ Reference rr = (Reference) exts.get(0).getValue();
+ o = (Organization) rr.getResource();
+ assertEquals("ORG", o.getName());
+
+ }
+
+ @Test
+ public void testEncodeAndParseExtensions() throws Exception {
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
+
+ Extension ext = new Extension();
+ ext.setUrl("http://example.com/extensions#someext");
+ ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
+ patient.addExtension(ext);
+
+ Extension parent = new Extension().setUrl("http://example.com#parent");
+ patient.addExtension(parent);
+ Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.addExtension(child1);
+ Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value2"));
+ parent.addExtension(child2);
+
+ Extension modExt = new Extension();
+ modExt.setUrl("http://example.com/extensions#modext");
+ modExt.setValue(new DateType("1995-01-02"));
+ patient.addModifierExtension(modExt);
+
+ HumanName name = patient.addName();
+ name.setFamily("Blah");
+ StringType given = name.addGivenElement();
+ given.setValue("Joe");
+ Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given"));
+ given.addExtension(ext2);
+
+ StringType given2 = name.addGivenElement();
+ given2.setValue("Shmoe");
+ Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent");
+ given2.addExtension(given2ext);
+ given2ext.addExtension(new Extension().setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD")));
+
+ 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(
+ " "));
+ assertThat(enc, containsString(" "));
+ assertThat(enc, containsString(
+ " "));
+
+ /*
+ * Now parse this back
+ */
+
+ Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc);
+ ext = parsed.getExtension().get(0);
+ assertEquals("http://example.com/extensions#someext", ext.getUrl());
+ assertEquals("2011-01-02T11:13:15", ((DateTimeType) ext.getValue()).getValueAsString());
+
+ parent = patient.getExtension().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", ((StringType) child1.getValue()).getValueAsString());
+ child2 = parent.getExtension().get(1);
+ assertEquals("http://example.com#child", child2.getUrl());
+ assertEquals("value2", ((StringType) child2.getValue()).getValueAsString());
+
+ modExt = parsed.getModifierExtension().get(0);
+ assertEquals("http://example.com/extensions#modext", modExt.getUrl());
+ assertEquals("1995-01-02", ((DateType) modExt.getValue()).getValueAsString());
+
+ name = parsed.getName().get(0);
+
+ ext2 = name.getGiven().get(0).getExtension().get(0);
+ assertEquals("http://examples.com#givenext", ext2.getUrl());
+ assertEquals("given", ((StringType) ext2.getValue()).getValueAsString());
+
+ given2ext = name.getGiven().get(1).getExtension().get(0);
+ assertEquals("http://examples.com#givenext_parent", given2ext.getUrl());
+ assertNull(given2ext.getValue());
+ Extension given2ext2 = given2ext.getExtension().get(0);
+ assertEquals("http://examples.com#givenext_child", given2ext2.getUrl());
+ assertEquals("CHILD", ((StringType) given2ext2.getValue()).getValue());
+
+ }
+
+ /**
+ * See #216
+ */
+ @Test
+ public void testEncodeAndParseIdentifierDstu2() {
+ IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setSystem("SYS").setValue("VAL").setType(new CodeableConcept().addCoding(new Coding().setSystem("http://hl7.org/fhir/v2/0203").setCode("MR")));
+
+ String out = xmlParser.encodeResourceToString(patient);
+ ourLog.info(out);
+
+ assertThat(out, stringContainsInOrder("",
+ "",
+ "",
+ "",
+ "",
+ "
",
+ " ",
+ "",
+ "",
+ " "));
+
+ patient = ourCtx.newXmlParser().parseResource(Patient.class, out);
+ assertEquals("http://hl7.org/fhir/v2/0203", patient.getIdentifier().get(0).getType().getCoding().get(0).getSystem());
+ assertEquals("MR", patient.getIdentifier().get(0).getType().getCoding().get(0).getCode());
+ }
+
+ private Matcher super String> stringContainsInOrder(java.lang.String... substrings) {
+ return Matchers.stringContainsInOrder(Arrays.asList(substrings));
+ }
+
+ private Matcher super String> stringContainsInOrder(List substrings) {
+ return Matchers.stringContainsInOrder(substrings);
+ }
+
+ /**
+ * See #347
+ */
+ @Test
+ public void testEncodeAndParseMedicationRequest() {
+ MedicationRequest mo = new MedicationRequest();
+ mo.getAuthoredOnElement().setValueAsString("2015-10-05");
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(mo);
+ ourLog.info(encoded);
+
+ mo = ourCtx.newXmlParser().parseResource(MedicationRequest.class, encoded);
+ assertEquals("2015-10-05", mo.getAuthoredOnElement().getValueAsString());
+ }
+
+ @Test
+ public void testEncodeAndParseMetaProfileAndTags() {
+ Patient p = new Patient();
+ p.addName().setFamily("FAMILY");
+
+ p.getMeta().addProfile("http://foo/Profile1");
+ p.getMeta().addProfile("http://foo/Profile2");
+
+ p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1");
+ p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2");
+
+ p.getMeta().addSecurity().setSystem("sec_scheme1").setCode("sec_term1").setDisplay("sec_label1");
+ p.getMeta().addSecurity().setSystem("sec_scheme2").setCode("sec_term2").setDisplay("sec_label2");
+
+ String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+
+ assertThat(enc, stringContainsInOrder("",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "
",
+ "",
+ "",
+ "",
+ "",
+ "
",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " "));
+
+ Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc);
+ List gotLabels = parsed.getMeta().getProfile();
+ assertEquals(2, gotLabels.size());
+ UriType label = gotLabels.get(0);
+ assertEquals("http://foo/Profile1", label.getValue());
+ label = gotLabels.get(1);
+ assertEquals("http://foo/Profile2", label.getValue());
+
+ List tagList = parsed.getMeta().getTag();
+ assertEquals(2, tagList.size());
+ assertEquals("scheme1", tagList.get(0).getSystem());
+ assertEquals("term1", tagList.get(0).getCode());
+ assertEquals("label1", tagList.get(0).getDisplay());
+ assertEquals("scheme2", tagList.get(1).getSystem());
+ assertEquals("term2", tagList.get(1).getCode());
+ assertEquals("label2", tagList.get(1).getDisplay());
+
+ tagList = parsed.getMeta().getSecurity();
+ assertEquals(2, tagList.size());
+ assertEquals("sec_scheme1", tagList.get(0).getSystem());
+ assertEquals("sec_term1", tagList.get(0).getCode());
+ assertEquals("sec_label1", tagList.get(0).getDisplay());
+ assertEquals("sec_scheme2", tagList.get(1).getSystem());
+ assertEquals("sec_term2", tagList.get(1).getCode());
+ assertEquals("sec_label2", tagList.get(1).getDisplay());
+ }
+
+ @Test
+ public void testEncodeAndParseMetaProfiles() {
+ Patient p = new Patient();
+ p.addName().setFamily("FAMILY");
+
+ p.getMeta().addTag().setSystem("scheme1").setCode("term1").setDisplay("label1");
+ p.getMeta().addTag().setSystem("scheme2").setCode("term2").setDisplay("label2");
+
+ String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+
+ assertThat(enc, stringContainsInOrder("",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "
",
+ "",
+ "",
+ "",
+ "",
+ "
",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " "));
+
+ Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc);
+ assertThat(parsed.getMeta().getProfile(), empty());
+
+ List tagList = parsed.getMeta().getTag();
+ assertEquals(2, tagList.size());
+ assertEquals("scheme1", tagList.get(0).getSystem());
+ assertEquals("term1", tagList.get(0).getCode());
+ assertEquals("label1", tagList.get(0).getDisplay());
+ assertEquals("scheme2", tagList.get(1).getSystem());
+ assertEquals("term2", tagList.get(1).getCode());
+ assertEquals("label2", tagList.get(1).getDisplay());
+ }
+
+ /**
+ * See #336
+ */
+ @Test
+ public void testEncodeAndParseNullPrimitiveWithExtensions() {
+
+ Patient p = new Patient();
+ p.setId("patid");
+ HumanName name = p.addName();
+ name.addGivenElement().setValue(null).setId("f0").addExtension(new Extension("http://foo", new StringType("FOOEXT0")));
+ name.addGivenElement().setValue("V1").setId("f1").addExtension((Extension) new Extension("http://foo", new StringType("FOOEXT1")).setId("ext1id"));
+ name.addGivenElement(); // this one shouldn't get encoded
+ name.addGivenElement().setValue(null).addExtension(new Extension("http://foo", new StringType("FOOEXT3")));
+ name.setId("nameid");
+
+ String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(output);
+
+ output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(p);
+ String expected = " ";
+
+ ourLog.info("Expected: {}", expected);
+ ourLog.info("Actual : {}", output);
+
+ assertEquals(expected, output);
+
+ p = ourCtx.newXmlParser().parseResource(Patient.class, output);
+ assertEquals("patid", p.getIdElement().getIdPart());
+
+ name = p.getName().get(0);
+ assertEquals("nameid", name.getId());
+ assertEquals(3, name.getGiven().size());
+
+ assertEquals(null, name.getGiven().get(0).getValue());
+ assertEquals("V1", name.getGiven().get(1).getValue());
+ assertEquals(null, name.getGiven().get(2).getValue());
+
+ assertEquals("f0", name.getGiven().get(0).getId());
+ assertEquals("f1", name.getGiven().get(1).getId());
+ assertEquals(null, name.getGiven().get(2).getId());
+
+ assertEquals(1, name.getGiven().get(0).getExtension().size());
+ assertEquals("http://foo", name.getGiven().get(0).getExtension().get(0).getUrl());
+ assertEquals("FOOEXT0", ((StringType) name.getGiven().get(0).getExtension().get(0).getValue()).getValue());
+ assertEquals(null, name.getGiven().get(0).getExtension().get(0).getId());
+
+ assertEquals(1, name.getGiven().get(1).getExtension().size());
+ assertEquals("http://foo", name.getGiven().get(1).getExtension().get(0).getUrl());
+ assertEquals("FOOEXT1", ((StringType) name.getGiven().get(1).getExtension().get(0).getValue()).getValue());
+ assertEquals("ext1id", name.getGiven().get(1).getExtension().get(0).getId());
+
+ assertEquals(1, name.getGiven().get(2).getExtension().size());
+ assertEquals("http://foo", name.getGiven().get(2).getExtension().get(0).getUrl());
+ assertEquals("FOOEXT3", ((StringType) name.getGiven().get(2).getExtension().get(0).getValue()).getValue());
+ assertEquals(null, name.getGiven().get(2).getExtension().get(0).getId());
+
+ }
+
+ @Test
+ public void testEncodeAndParseProfiledDatatype() {
+ MedicationRequest mo = new MedicationRequest();
+ mo.addDosageInstruction().getTiming().getRepeat().setBounds(new Duration().setCode("code"));
+ String out = ourCtx.newXmlParser().encodeResourceToString(mo);
+ ourLog.info(out);
+ assertThat(out, containsString(""));
+
+ mo = ourCtx.newXmlParser().parseResource(MedicationRequest.class, out);
+ Duration duration = (Duration) mo.getDosageInstruction().get(0).getTiming().getRepeat().getBounds();
+ assertEquals("code", duration.getCode());
+ }
+
+ /**
+ * See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
+ */
+ @Test
+ public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
+ IParser xmlParser = ourCtx.newXmlParser();
+
+ MedicationStatement ms = new MedicationStatement();
+ ms.addDosage().setDose(new SimpleQuantity().setValue(123));
+
+ String output = xmlParser.encodeResourceToString(ms);
+ assertThat(output, containsString(" "));
+ }
+
+ @Test
+ public void testEncodeAndParseSecurityLabels() {
+ Patient p = new Patient();
+ p.addName().setFamily("FAMILY");
+
+ List labels = new ArrayList();
+ labels.add(new Coding().setSystem("SYSTEM1").setCode("CODE1").setDisplay("DISPLAY1").setVersion("VERSION1"));
+ labels.add(new Coding().setSystem("SYSTEM2").setCode("CODE2").setDisplay("DISPLAY2").setVersion("VERSION2"));
+ p.getMeta().getSecurity().addAll(labels);
+
+ String enc = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(enc);
+
+ assertThat(enc, stringContainsInOrder("",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "
",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "
",
+ "",
+ "",
+ "",
+ " ",
+ " "));
+
+ Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, enc);
+ List gotLabels = parsed.getMeta().getSecurity();
+
+ assertEquals(2, gotLabels.size());
+
+ Coding label = gotLabels.get(0);
+ assertEquals("SYSTEM1", label.getSystem());
+ assertEquals("CODE1", label.getCode());
+ assertEquals("DISPLAY1", label.getDisplay());
+ assertEquals("VERSION1", label.getVersion());
+
+ label = gotLabels.get(1);
+ assertEquals("SYSTEM2", label.getSystem());
+ assertEquals("CODE2", label.getCode());
+ assertEquals("DISPLAY2", label.getDisplay());
+ assertEquals("VERSION2", label.getVersion());
+ }
+
+ /**
+ * See #103
+ */
+ @Test
+ public void testEncodeAndReEncodeContainedJson() {
+ Composition comp = new Composition();
+ comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section0_Allergy0")));
+ comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section1_Allergy0")));
+ comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section2_Allergy0")));
+
+ IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
+
+ String string = parser.encodeResourceToString(comp);
+ ourLog.info(string);
+
+ Composition parsed = parser.parseResource(Composition.class, string);
+ parsed.getSection().remove(0);
+
+ string = parser.encodeResourceToString(parsed);
+ ourLog.info(string);
+
+ parsed = parser.parseResource(Composition.class, string);
+ assertEquals(2, parsed.getContained().size());
+ }
+
+ /**
+ * See #103
+ */
+ @Test
+ public void testEncodeAndReEncodeContainedXml() {
+ Composition comp = new Composition();
+ comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section0_Allergy0")));
+ comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section1_Allergy0")));
+ comp.addSection().addEntry().setResource(new AllergyIntolerance().addNote(new Annotation().setText("Section2_Allergy0")));
+
+ IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
+
+ String string = parser.encodeResourceToString(comp);
+ ourLog.info(string);
+
+ Composition parsed = parser.parseResource(Composition.class, string);
+ parsed.getSection().remove(0);
+
+ string = parser.encodeResourceToString(parsed);
+ ourLog.info(string);
+
+ parsed = parser.parseResource(Composition.class, string);
+ assertEquals(2, parsed.getContained().size());
+ }
+
+ @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(" ", output);
+ }
+
+ @Test
+ public void testEncodeBinaryWithSecurityContext() {
+ Binary bin = new Binary();
+ bin.setContentType("text/plain");
+ bin.setContent("Now is the time".getBytes());
+ Reference securityContext = new Reference();
+ securityContext.setReference("DiagnosticReport/1");
+ bin.setSecurityContext(securityContext);
+ String encoded = ourCtx.newXmlParser().encodeResourceToString(bin);
+ ourLog.info(encoded);
+ assertThat(encoded, containsString("Binary"));
+ assertThat(encoded, containsString(""));
+ assertThat(encoded, containsString(" "));
+ assertThat(encoded, containsString(""));
+ }
+
+ @Test
+ public void testEncodeBundleWithContained() {
+ DiagnosticReport rpt = new DiagnosticReport();
+ rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Sharp1")).setId("#1"));
+ rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Uuid1")).setId("urn:uuid:UUID1"));
+
+ Bundle b = new Bundle();
+ b.addEntry().setResource(rpt);
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder("",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ " "));
+
+ }
+
+ /**
+ * See #113
+ */
+ @Test
+ public void testEncodeContainedResources() {
+
+ MedicationRequest medicationPrescript = new MedicationRequest();
+
+ String medId = "123";
+ CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding().setSystem("urn:sys").setCode("code1"));
+
+ // Adding medication to Contained.
+ Medication medResource = new Medication();
+ medResource.setCode(codeDt);
+ medResource.setId("#" + String.valueOf(medId));
+ medicationPrescript.getContained().add(medResource);
+
+ // Medication reference. This should point to the contained resource.
+ Reference medRefDt = new Reference("#" + medId);
+ medRefDt.setDisplay("MedRef");
+ medicationPrescript.setMedication(medRefDt);
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
+ String encoded = p.encodeResourceToString(medicationPrescript);
+ ourLog.info(encoded);
+
+ // @formatter:on
+ assertThat(encoded,
+ stringContainsInOrder("", "", "", "", "", "",
+ "", "", "
", "
", " ", " ", "", "",
+ "", " ", " "));
+
+ }
+
+ /**
+ * See #113
+ */
+ @Test
+ public void testEncodeContainedResourcesAutomatic() {
+
+ MedicationRequest medicationPrescript = new MedicationRequest();
+ String nameDisp = "MedRef";
+ CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding("urn:sys", "code1", null));
+
+ // Adding medication to Contained.
+ Medication medResource = new Medication();
+ // No ID set
+ medResource.setCode(codeDt);
+
+ // Medication reference. This should point to the contained resource.
+ Reference medRefDt = new Reference();
+ medRefDt.setDisplay(nameDisp);
+ // Resource reference set, but no ID
+ medRefDt.setResource(medResource);
+ medicationPrescript.setMedication(medRefDt);
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
+ String encoded = p.encodeResourceToString(medicationPrescript);
+ ourLog.info(encoded);
+
+ assertThat(encoded,
+ stringContainsInOrder("", "", "", "", "", "",
+ "", "", "
", "
", " ", " ", "", "",
+ "", " ", " "));
+
+ }
+
+ /**
+ * See #113
+ */
+ @Test
+ public void testEncodeContainedResourcesManualContainUsingNonLocalId() {
+
+ MedicationRequest medicationPrescript = new MedicationRequest();
+
+ String medId = "123";
+ CodeableConcept codeDt = new CodeableConcept().addCoding(new Coding("urn:sys", "code1", null));
+
+ // Adding medication to Contained.
+ Medication medResource = new Medication();
+ medResource.setCode(codeDt);
+ medResource.setId(String.valueOf(medId)); // ID does not start with '#'
+ medicationPrescript.getContained().add(medResource);
+
+ // Medication reference. This should point to the contained resource.
+ Reference medRefDt = new Reference("#" + medId);
+ medRefDt.setDisplay("MedRef");
+ medicationPrescript.setMedication(medRefDt);
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
+ String encoded = p.encodeResourceToString(medicationPrescript);
+ ourLog.info(encoded);
+
+ assertThat(encoded,
+ stringContainsInOrder("", "", "", "", "", "",
+ "", "", "
", "
", " ", " ", "", "",
+ "", " ", " "));
+
+ }
+
+ @Test
+ public void testEncodeContainedWithNarrativeIsSuppresed() throws Exception {
+ IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
+
+ // Create an organization, note that the organization does not have an ID
+ Organization org = new Organization();
+ org.getNameElement().setValue("Contained Test Organization");
+ org.getText().setDivAsString("FOOBAR");
+
+ // Create a patient
+ Patient patient = new Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
+ patient.getText().setDivAsString("BARFOO");
+ patient.getManagingOrganization().setResource(org);
+
+ String encoded = parser.encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder("", "BARFOO", "", "", "", ""));
+ assertThat(encode, stringContainsInOrder("\n\nA P TAG
line1\nline2\nline3 BOLD
", + "
line1\nline2\nline3 BOLD")); + + } + + @Test + public void testEncodeDivWithPrePrettyPrint() { + + Patient p = new Patient(); + p.getText().setDivAsString("
A P TAG
line1\nline2\nline3 BOLD
", ""));
+ assertThat(encoded, not(containsString("text")));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, containsString("maritalStatus"));
+ }
+
+ @Test
+ public void testEncodeNonContained() {
+ // Create an organization
+ Organization org = new Organization();
+ org.setId("Organization/65546");
+ org.getNameElement().setValue("Contained Test Organization");
+
+ // Create a patient
+ Patient patient = new Patient();
+ patient.setId("Patient/1333");
+ patient.addIdentifier().setSystem("urn:mrns").setValue("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
", ""));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeSummary2() {
+ Patient patient = new Patient();
+ patient.setId("Patient/1/_history/1");
+ patient.getText().setDivAsString("", ""));
+ assertThat(encoded, stringContainsInOrder("", " ",
+ "
", " "));
+ assertThat(encoded, not(containsString("THE DIV")));
+ assertThat(encoded, containsString("family"));
+ assertThat(encoded, not(containsString("maritalStatus")));
+ }
+
+ @Test
+ public void testEncodeUndeclaredBlock() throws Exception {
+ FooMessageHeader.FooMessageSourceComponent source = new FooMessageHeader.FooMessageSourceComponent();
+ source.getMessageHeaderApplicationId().setValue("APPID");
+ source.setName("NAME");
+
+ FooMessageHeader header = new FooMessageHeader();
+ header.setSource(source);
+
+ header.addDestination().setName("DEST");
+
+ Bundle bundle = new Bundle();
+ bundle.addEntry().setResource(header);
+
+ IParser p = ourCtx.newXmlParser();
+ p.setPrettyPrint(true);
+
+ String encode = p.encodeResourceToString(bundle);
+ ourLog.info(encode);
+
+ assertThat(encode, containsString(""));
+ assertThat(encode, stringContainsInOrder(" fact = new Address.AddressUseEnumFactory();
+ PrimitiveType enumeration = new Enumeration(fact).setValue(Address.AddressUse.HOME);
+ patient.addExtension().setUrl("urn:foo").setValue(enumeration);
+
+ String val = parser.encodeResourceToString(patient);
+ ourLog.info(val);
+ assertThat(val, StringContains.containsString(" "));
+
+ MyPatientWithOneDeclaredEnumerationExtensionDstu3 actual = parser.parseResource(MyPatientWithOneDeclaredEnumerationExtensionDstu3.class, val);
+ assertEquals(Address.AddressUse.HOME, patient.getAddress().get(0).getUse());
+ Enumeration ref = actual.getFoo();
+ assertEquals("home", ref.getValue().toCode());
+
+ }
+
+ @Test
+ public void testEncodeWithContained() {
+ List contained = new ArrayList();
+
+ // Will be added by reference
+ Patient p = new Patient();
+ p.setId("#" + "1000");
+ contained.add(p);
+
+ // Will be added by direct resource object
+ Location l = new Location();
+ l.setId("#" + "1001");
+ contained.add(l);
+
+ // Will not be referred to (and therefore shouldn't appear in output)
+ Location l2 = new Location();
+ l2.setId("#1002");
+ contained.add(l2);
+
+ Appointment appointment = new Appointment();
+ appointment.setId("1234");
+ appointment.getContained().addAll(contained);
+
+ appointment.addParticipant().getActor().setReference("#1000");
+ appointment.addParticipant().getActor().setResource(l);
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(appointment);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ " "));
+
+ assertThat(encoded, not(containsString("#1002")));
+ }
+
+ @Test
+ public void testEncodeWithDontEncodeElements() throws Exception {
+ Patient patient = new Patient();
+ patient.setId("123");
+ patient.getMeta().addProfile("http://profile");
+ patient.addName().setFamily("FAMILY").addGiven("GIVEN");
+ patient.addAddress().addLine("LINE1");
+
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.meta", "Patient.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.name.family"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("GIVEN"));
+ assertThat(out, not(containsString("FAMILY")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("*.meta", "*.id"));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("address"));
+ assertThat(out, not(containsString("id")));
+ assertThat(out, not(containsString("meta")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setDontEncodeElements(Sets.newHashSet("Patient.meta"));
+ p.setEncodeElements(new HashSet(Arrays.asList("Patient.name")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(patient);
+ ourLog.info(out);
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, containsString("id"));
+ assertThat(out, not(containsString("address")));
+ assertThat(out, not(containsString("meta")));
+ }
+ }
+
+ @Test
+ public void testEncodeWithEncodeElements() throws Exception {
+ Patient patient = new Patient();
+ patient.getMeta().addProfile("http://profile");
+ patient.addName().setFamily("FAMILY");
+ patient.addAddress().addLine("LINE1");
+
+ Bundle bundle = new Bundle();
+ bundle.setTotal(100);
+ bundle.addEntry().setResource(patient);
+
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setEncodeElements(new HashSet<>(Arrays.asList("Patient.name", "Bundle.entry")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(bundle);
+ ourLog.info(out);
+ assertThat(out, not(containsString("total")));
+ assertThat(out, (containsString("Patient")));
+ assertThat(out, (containsString("name")));
+ assertThat(out, not(containsString("address")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setEncodeElements(new HashSet(Arrays.asList("Patient.name")));
+ p.setEncodeElementsAppliesToResourceTypes(new HashSet(Arrays.asList("Patient")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(bundle);
+ ourLog.info(out);
+ assertThat(out, (containsString("total")));
+ assertThat(out, (containsString("Patient")));
+ assertThat(out, (containsString("name")));
+ assertThat(out, not(containsString("address")));
+ }
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setEncodeElements(new HashSet(Arrays.asList("Patient")));
+ p.setEncodeElementsAppliesToResourceTypes(new HashSet(Arrays.asList("Patient")));
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(bundle);
+ ourLog.info(out);
+ assertThat(out, (containsString("total")));
+ assertThat(out, (containsString("Patient")));
+ assertThat(out, (containsString("name")));
+ assertThat(out, (containsString("address")));
+ }
+
+ }
+
+ @Test
+ public void testEncodeWithEncodeElementsAppliesToChildResourcesOnly() throws Exception {
+ Patient patient = new Patient();
+ patient.getMeta().addProfile("http://profile");
+ patient.addName().setFamily("FAMILY");
+ patient.addAddress().addLine("LINE1");
+
+ Bundle bundle = new Bundle();
+ bundle.setTotal(100);
+ bundle.addEntry().setResource(patient);
+
+ {
+ IParser p = ourCtx.newXmlParser();
+ p.setEncodeElements(new HashSet<>(Arrays.asList("Patient.name")));
+ p.setEncodeElementsAppliesToChildResourcesOnly(true);
+ p.setPrettyPrint(true);
+ String out = p.encodeResourceToString(bundle);
+ ourLog.info(out);
+ assertThat(out, containsString("total"));
+ assertThat(out, containsString("Patient"));
+ assertThat(out, containsString("name"));
+ assertThat(out, not(containsString("address")));
+ }
+ }
+
+ /**
+ * Test for the url generated based on the server config
+ */
+ @Test
+ public void testGeneratedUrls() {
+ final IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
+ xmlParser.setServerBaseUrl("http://myserver.com");
+
+ final CustomPatientDstu3 patient = new CustomPatientDstu3();
+ patient.setHomeless(new BooleanType(true));
+
+ final String parsedPatient = xmlParser.encodeResourceToString(patient);
+
+ assertTrue(parsedPatient.contains(""));
+ assertTrue(parsedPatient.contains(""));
+ }
+
+ @Test
+ public void testMoreExtensions() throws Exception {
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setUse(Identifier.IdentifierUse.OFFICIAL).setSystem("urn:example").setValue("7000135");
+
+ Extension ext = new Extension();
+ ext.setUrl("http://example.com/extensions#someext");
+ ext.setValue(new DateTimeType("2011-01-02T11:13:15"));
+
+ // Add the extension to the resource
+ patient.addExtension(ext);
+ // END SNIPPET: resourceExtension
+
+ // START SNIPPET: resourceStringExtension
+ HumanName name = patient.addName();
+ name.setFamily("Shmoe");
+ StringType given = name.addGivenElement();
+ given.setValue("Joe");
+ Extension ext2 = new Extension().setUrl("http://examples.com#givenext").setValue(new StringType("given"));
+ given.addExtension(ext2);
+
+ StringType given2 = name.addGivenElement();
+ given2.setValue("Shmoe");
+ Extension given2ext = new Extension().setUrl("http://examples.com#givenext_parent");
+ given2.addExtension(given2ext);
+ Extension givenExtChild = new Extension();
+ givenExtChild.setUrl("http://examples.com#givenext_child").setValue(new StringType("CHILD"));
+ given2ext.addExtension(givenExtChild);
+ // END SNIPPET: resourceStringExtension
+
+ // START SNIPPET: subExtension
+ Extension parent = new Extension().setUrl("http://example.com#parent");
+ patient.addExtension(parent);
+
+ Extension child1 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.addExtension(child1);
+
+ Extension child2 = new Extension().setUrl("http://example.com#child").setValue(new StringType("value1"));
+ parent.addExtension(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(" "));
+ assertThat(enc, containsString(
+ " "));
+ }
+
+ @Test
+ public void testOmitResourceId() {
+ Patient p = new Patient();
+ p.setId("123");
+ p.addName().setFamily("ABC");
+
+ assertThat(ourCtx.newXmlParser().encodeResourceToString(p), stringContainsInOrder("123", "ABC"));
+ assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), containsString("ABC"));
+ assertThat(ourCtx.newXmlParser().setOmitResourceId(true).encodeResourceToString(p), not(containsString("123")));
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnFhirContext() {
+ try {
+ String tmp = " ";
+ ourCtx.getParserOptions().setOverrideResourceIdWithBundleEntryFullUrl(false);
+ Bundle bundle = (Bundle) ourCtx.newXmlParser().parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ Patient o1 = (Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertFalse(o1Id.hasBaseUrl());
+ assertEquals("Patient", o1Id.getResourceType());
+ assertEquals("patxuzos", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ } finally {
+ // ensure we cleanup ourCtx so other tests continue to work
+ ourCtx = null;
+ }
+ }
+
+ @Test
+ public void testOverrideResourceIdWithBundleEntryFullUrlDisabled_ConfiguredOnParser() {
+ try {
+ String tmp = " ";
+ Bundle bundle = (Bundle) ourCtx.newXmlParser().setOverrideResourceIdWithBundleEntryFullUrl(false).parseResource(tmp);
+ assertEquals(1, bundle.getEntry().size());
+ {
+ Patient o1 = (Patient) bundle.getEntry().get(0).getResource();
+ IIdType o1Id = o1.getIdElement();
+ assertFalse(o1Id.hasBaseUrl());
+ assertEquals("Patient", o1Id.getResourceType());
+ assertEquals("patxuzos", o1Id.getIdPart());
+ assertFalse(o1Id.hasVersionIdPart());
+ }
+ } finally {
+ // ensure we cleanup ourCtx so other tests continue to work
+ ourCtx = null;
+ }
+ }
+
+ @Test
+ public void testParseAndEncodeComments() {
+ String input = "\n" +
+ " " +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "\n" +
+ " Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321
\n" +
+ "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " " +
+ " " +
+ " ";
+
+ Patient res = ourCtx.newXmlParser().parseResource(Patient.class, input);
+ res.getFormatCommentsPre();
+ assertEquals("Patient/pat1", res.getId());
+ assertEquals("654321", res.getIdentifier().get(0).getValue());
+ assertEquals(true, res.getActive());
+
+ assertThat(res.getIdElement().getFormatCommentsPre(), contains("pre resource comment"));
+ assertThat(res.getIdentifier().get(0).getFormatCommentsPre(), contains("identifier comment 1", "identifier comment 2"));
+ assertThat(res.getIdentifier().get(0).getUseElement().getFormatCommentsPre(), contains("use comment 1", "use comment 2"));
+ assertThat(res.getActiveElement().getFormatCommentsPost(), contains("post resource comment"));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder(
+ "\"identifier\": [",
+ "{",
+ "\"fhir_comments\":",
+ "[",
+ "\"identifier comment 1\"",
+ ",",
+ "\"identifier comment 2\"",
+ "]",
+ "\"use\": \"usual\",",
+ "\"_use\": {",
+ "\"fhir_comments\":",
+ "[",
+ "\"use comment 1\"",
+ ",",
+ "\"use comment 2\"",
+ "]",
+ "},",
+ "\"type\""));
+
+ encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ " ",
+ "Patient Donald DUCK @ Acme Healthcare, Inc. MR = 654321
",
+ "",
+ " ",
+ " \n",
+ " ",
+ "",
+ "",
+ "",
+ " ",
+ "",
+ " "));
+
+ }
+
+ @Test
+ public void testParseAndEncodeCommentsOnExtensions() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Patient pat = ourCtx.newXmlParser().parseResource(Patient.class, input);
+ String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(pat);
+ ourLog.info(output);
+
+ assertThat(output, stringContainsInOrder(
+ "",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " "));
+
+ output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(pat);
+ ourLog.info(output);
+
+ assertThat(output, stringContainsInOrder(
+ "{",
+ " \"resourceType\": \"Patient\",",
+ " \"id\": \"someid\",",
+ " \"_id\": {",
+ " \"fhir_comments\": [",
+ " \" comment 1 \"",
+ " ]",
+ " },",
+ " \"extension\": [",
+ " {",
+ " \"fhir_comments\": [",
+ " \" comment 2 \",",
+ " \" comment 7 \"",
+ " ],",
+ " \"url\": \"urn:patientext:att\",",
+ " \"valueAttachment\": {",
+ " \"fhir_comments\": [",
+ " \" comment 3 \",",
+ " \" comment 6 \"",
+ " ],",
+ " \"contentType\": \"aaaa\",",
+ " \"_contentType\": {",
+ " \"fhir_comments\": [",
+ " \" comment 4 \"",
+ " ]",
+ " },",
+ " \"data\": \"AAAA\",",
+ " \"_data\": {",
+ " \"fhir_comments\": [",
+ " \" comment 5 \"",
+ " ]",
+ " }",
+ " }",
+ " }",
+ " ]",
+ "}"));
+
+ }
+
+ @Test
+ public void testParseAndEncodeExtensionOnReference() {
+
+ String input = "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ " " +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "" +
+ " " +
+ "
" +
+ " " +
+ " " +
+ " " +
+ " " +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "" +
+ "
" +
+ " " +
+ " " +
+ " " +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ " " +
+ "" +
+ "" +
+ " " +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "
" +
+ "
" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "
" +
+ "
" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "
" +
+ "
" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "
" +
+ "
" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ "" +
+ " " +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ "" +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ "" +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ " " +
+ " " +
+ " " +
+ "" +
+ "" +
+ "" +
+ " " +
+ "" +
+ "" +
+ " " +
+ "" +
+ " " +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ "" +
+ "" +
+ " " +
+ " " +
+ "" +
+ " " +
+ " " +
+ " " +
+ " ";
+
+ DataElement de = ourCtx.newXmlParser().parseResource(DataElement.class, input);
+ String output = ourCtx.newXmlParser().encodeResourceToString(de).replace(" xmlns=\"http://hl7.org/fhir\"", "");
+
+ ElementDefinition elem = de.getElement().get(0);
+ ElementDefinition.ElementDefinitionBindingComponent b = elem.getBinding();
+ // assertEquals("All codes representing the gender of a person.", b.getDescription());
+
+ Reference ref = (Reference) b.getValueSet();
+ assertEquals("#2179414", ref.getReference());
+
+ assertEquals(2, ref.getExtension().size());
+ Extension ext = ref.getExtension().get(0);
+ assertEquals("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset", ext.getUrl());
+ assertEquals(Reference.class, ext.getValue().getClass());
+ assertEquals("#2179414-permitted", ((Reference) ext.getValue()).getReference());
+ assertEquals(ValueSet.class, ((Reference) ext.getValue()).getResource().getClass());
+
+ ext = ref.getExtension().get(1);
+ assertEquals("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-conceptmap", ext.getUrl());
+ assertEquals(Reference.class, ext.getValue().getClass());
+ assertEquals("#2179414-cm", ((Reference) ext.getValue()).getReference());
+ assertEquals(ConceptMap.class, ((Reference) ext.getValue()).getResource().getClass());
+
+ ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(de));
+
+ assertThat(output, containsString("http://hl7.org/fhir/StructureDefinition/11179-permitted-value-valueset"));
+
+ }
+
+ @Test
+ public void testParseAndEncodeNestedExtensions() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Patient p = ourCtx.newXmlParser().parseResource(Patient.class, input);
+ DateType bd = p.getBirthDateElement();
+ assertEquals("2005-03-04", bd.getValueAsString());
+
+ List exts = bd.getExtensionsByUrl("http://my.fancy.extension.url");
+ assertEquals(1, exts.size());
+ Extension ext = exts.get(0);
+ assertEquals(null, ext.getValue());
+
+ exts = ext.getExtensionsByUrl("http://my.fancy.extension.url");
+ assertEquals(1, exts.size());
+ ext = exts.get(0);
+ assertEquals("myNestedValue", ((StringType) ext.getValue()).getValue());
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(encoded);
+
+ assertThat(encoded, stringContainsInOrder(
+ "",
+ "",
+ "",
+ "",
+ "",
+ " ",
+ " ",
+ " ",
+ " "));
+
+ }
+
+ @Test
+ public void testParseBundleNewWithPlaceholderIds() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+
+ Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+
+ }
+
+ @Test
+ public void testParseBundleNewWithPlaceholderIdsInBase1() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+
+ Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+ }
+
+ @Test
+ public void testParseBundleNewWithPlaceholderIdsInBase2() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+
+ Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("urn:uuid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+
+ input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+
+ parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("urn:uuid:0.1.2.3", parsed.getEntry().get(0).getResource().getIdElement().getValue());
+
+ }
+
+ @Test
+ public void testParseBundleOldStyleWithUnknownLinks() throws Exception {
+
+ String bundle = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Bundle b = (Bundle) ourCtx.newXmlParser().parseResource(bundle);
+ assertEquals(1, b.getEntry().size());
+
+ }
+
+ @Test
+ public void testParseBundleOldWithPlaceholderIds() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n";
+
+ Bundle parsed = (Bundle) ourCtx.newXmlParser().parseResource(input);
+ assertEquals("urn:oid:0.1.2.3", parsed.getEntry().get(0).getResource().getId());
+
+ }
+
+ @Test
+ public void testParseBundleWithBinary() {
+ // TODO: implement this test, make sure we handle ID and meta correctly in Binary
+ }
+
+ /**
+ * See #191
+ */
+ @Test
+ public void testParseBundleWithLinksOfUnknownRelation() throws Exception {
+ String input = IOUtils.toString(Dstu3XmlParserTest.class.getResourceAsStream("/bundle_orion.xml"), StandardCharsets.UTF_8);
+ Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+
+ Bundle.BundleLinkComponent link = parsed.getLink().get(0);
+ assertEquals("just trying add link", link.getRelation());
+ assertEquals("blarion", link.getUrl());
+
+ Bundle.BundleEntryComponent entry = parsed.getEntry().get(0);
+ link = entry.getLink().get(0);
+ assertEquals("orionhealth.edit", link.getRelation());
+ assertEquals("Observation", link.getUrl());
+ }
+
+ @Test
+ public void testParseBundleWithResourceId() {
+
+ String input = ""
+ + " "
+ + " "
+ + " "
+ + " \n";
+
+ Bundle bundle = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+ assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/3", bundle.getEntry().get(0).getResource().getIdElement().getValue());
+ assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/2", bundle.getEntry().get(1).getResource().getIdElement().getValue());
+ assertEquals("http://localhost:58402/fhir/context/Patient/1/_history/1", bundle.getEntry().get(2).getResource().getIdElement().getValue());
+ }
+
+
+ /**
+ * Thanks to Alexander Kley!
+ */
+ @Test
+ public void testParseContainedBinaryResource() {
+ byte[] bin = new byte[]{0, 1, 2, 3, 4};
+ final Binary binary = new Binary();
+ binary.setContentType("PatientConsent").setContent(bin);
+
+ DocumentManifest manifest = new DocumentManifest();
+ CodeableConcept cc = new CodeableConcept();
+ cc.addCoding().setSystem("mySystem").setCode("PatientDocument");
+ manifest.setType(cc);
+ manifest.setMasterIdentifier(new Identifier().setSystem("mySystem").setValue(UUID.randomUUID().toString()));
+ manifest.addContent().setP(new Reference(binary));
+ manifest.setStatus(Enumerations.DocumentReferenceStatus.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().size());
+ assertEquals(1, actual.getContent().size());
+
+ /*
+ * If this fails, it's possibe the DocumentManifest structure is wrong: It should be
+ *
+ * @Child(name = "p", type = {Attachment.class, ValueSet.class}, order=1, min=1, max=1, modifier=false, summary=true)
+ */
+ assertNotNull(((Reference) actual.getContent().get(0).getP()).getResource());
+ }
+
+ /**
+ * See #426
+ */
+ @Test
+ public void testParseExtensionWithIdType() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
+
+ List extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare");
+ extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id");
+ Extension ext = extList.get(0);
+ IdType value = (IdType) ext.getValue();
+ assertEquals("mc1", value.getValueAsString());
+ }
+
+ /**
+ * See #426
+ *
+ * Value type of FOO isn't a valid datatype
+ */
+ @Test
+ public void testParseExtensionWithInvalidType() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
+
+ List extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare");
+ extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id");
+ Extension ext = extList.get(0);
+ IdType value = (IdType) ext.getValue();
+ assertEquals(null, value);
+ }
+
+ /**
+ * See #342
+ */
+ @Test(expected = DataFormatException.class)
+ public void testParseInvalid() {
+ ourCtx.newXmlParser().parseResource("FOO");
+ }
+
+ /**
+ * See #366
+ */
+ @Test()
+ public void testParseInvalidBoolean() {
+
+ String resource = "\n" +
+ " \n" +
+ " ";
+
+ IParser p = ourCtx.newXmlParser();
+
+ try {
+ p.parseResource(resource);
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Invalid attribute value \"1\": Invalid boolean string: '1'", e.getMessage());
+ }
+
+ LenientErrorHandler errorHandler = new LenientErrorHandler();
+ assertEquals(true, errorHandler.isErrorOnInvalidValue());
+ errorHandler.setErrorOnInvalidValue(false);
+ p.setParserErrorHandler(errorHandler);
+ }
+
+ @Test
+ public void testParseInvalidTextualNumber() {
+ Observation obs = new Observation();
+ obs.setValue(new Quantity().setValue(1234));
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs);
+ encoded = encoded.replace("1234", "\"1234\"");
+ ourLog.info(encoded);
+ ourCtx.newJsonParser().parseResource(encoded);
+ }
+
+ @Test
+ public void testParseMetaUpdatedDate() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, input);
+
+ InstantType updated = b.getMeta().getLastUpdatedElement();
+ assertEquals("2015-06-22T15:48:57.554-04:00", updated.getValueAsString());
+
+ }
+
+ @Test
+ public void testParseMetadata() throws Exception {
+
+ String content = "\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" +
+ " ";
+
+ Bundle b = ourCtx.newXmlParser().parseResource(Bundle.class, content);
+ assertEquals(1, b.getEntry().size());
+
+ Bundle.BundleEntryComponent entry = b.getEntry().get(0);
+ Patient pt = (Patient) entry.getResource();
+ assertEquals("http://foo/fhirBase2/Patient/1/_history/2", pt.getIdElement().getValue());
+ assertEquals("2012-01-02", pt.getBirthDateElement().getValueAsString());
+ assertEquals("0.123", entry.getSearch().getScore().toString());
+ assertEquals("match", entry.getSearch().getMode().toCode());
+ assertEquals("POST", entry.getRequest().getMethod().toCode());
+ assertEquals("http://foo/Patient?identifier=value", entry.getRequest().getUrl());
+ assertEquals("2001-02-22T09:22:33-07:00", pt.getMeta().getLastUpdatedElement().getValueAsString());
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
+ String reEncoded = p.encodeResourceToString(b);
+ ourLog.info(reEncoded);
+
+ compareXml(content, reEncoded);
+
+ }
+
+ @Test
+ public void testParseNestedExtensionsInvalid() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ try {
+ ourCtx.newXmlParser().parseResource(Patient.class, input);
+ fail();
+ } catch (DataFormatException e) {
+ assertThat(e.getMessage(), containsString("Extension (URL='http://my.fancy.extension.url') must not have both a value and other contained extensions"));
+ }
+ }
+
+ /**
+ * See #163
+ */
+ @Test
+ public void testParseResourceType() {
+ IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
+
+ // Patient
+ Patient patient = new Patient();
+ String patientId = UUID.randomUUID().toString();
+ patient.setId(new IdType("Patient", patientId));
+ patient.addName().addGiven("John").setFamily("Smith");
+ patient.setGender(Enumerations.AdministrativeGender.MALE);
+ patient.setBirthDateElement(new DateType("1987-04-16"));
+
+ // Bundle
+ Bundle bundle = new Bundle();
+ bundle.setType(Bundle.BundleType.COLLECTION);
+ bundle.addEntry().setResource(patient);
+
+ String bundleText = xmlParser.encodeResourceToString(bundle);
+ ourLog.info(bundleText);
+
+ Bundle reincarnatedBundle = xmlParser.parseResource(Bundle.class, bundleText);
+ Patient reincarnatedPatient = (Patient) reincarnatedBundle.getEntry().get(0).getResource();
+
+ assertEquals("Patient", patient.getIdElement().getResourceType());
+ assertEquals("Patient", reincarnatedPatient.getIdElement().getResourceType());
+ }
+
+ @Test(expected = DataFormatException.class)
+ public void testParseWithInvalidLocalRef() throws IOException {
+ String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_invalid_contained_ref.xml"), StandardCharsets.UTF_8);
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+ parser.parseResource(Bundle.class, string);
+ }
+
+ @Test()
+ public void testParseWithInvalidLocalRefLenient() throws IOException {
+ String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_invalid_contained_ref.xml"), StandardCharsets.UTF_8);
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new LenientErrorHandler());
+ parser.parseResource(Bundle.class, string);
+ }
+
+ /**
+ * If a contained resource refers to a contained resource that comes after it, it should still be successfully
+ * woven together.
+ */
+ @Test
+ public void testParseWovenContainedResources() throws IOException {
+ String string = IOUtils.toString(getClass().getResourceAsStream("/bundle_with_woven_obs.xml"), StandardCharsets.UTF_8);
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+ org.hl7.fhir.dstu3.model.Bundle bundle = parser.parseResource(Bundle.class, string);
+
+ DiagnosticReport resource = (DiagnosticReport) bundle.getEntry().get(0).getResource();
+ Observation obs = (Observation) resource.getResult().get(1).getResource();
+ assertEquals("#2", obs.getId());
+ Reference performerFirstRep = obs.getPerformerFirstRep();
+ Practitioner performer = (Practitioner) performerFirstRep.getResource();
+ assertEquals("#3", performer.getId());
+ }
+
+ /**
+ * See #414
+ */
+ @Test
+ public void testParseXmlExtensionWithoutUrl() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new LenientErrorHandler());
+ Patient parsed = (Patient) parser.parseResource(input);
+ assertEquals(1, parsed.getExtension().size());
+ assertEquals(null, parsed.getExtension().get(0).getUrl());
+ assertEquals("2011-01-02T11:13:15", parsed.getExtension().get(0).getValueAsPrimitive().getValueAsString());
+
+ try {
+ parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+ parser.parseResource(input);
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Resource is missing required element 'url' in parent element 'extension'", e.getCause().getMessage());
+ }
+
+ }
+
+ /**
+ * See #414
+ */
+ @Test
+ public void testParseXmlModifierExtensionWithoutUrl() {
+
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ IParser parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new LenientErrorHandler());
+ Patient parsed = (Patient) parser.parseResource(input);
+ assertEquals(1, parsed.getModifierExtension().size());
+ assertEquals(null, parsed.getModifierExtension().get(0).getUrl());
+ assertEquals("2011-01-02T11:13:15", parsed.getModifierExtension().get(0).getValueAsPrimitive().getValueAsString());
+
+ try {
+ parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+ parser.parseResource(input);
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("Resource is missing required element 'url' in parent element 'modifierExtension'", e.getCause().getMessage());
+ }
+
+ }
+
+ /**
+ * See #344
+ */
+ @Test
+ public void testParserIsCaseSensitive() {
+ Observation obs = new Observation();
+ SampledData data = new SampledData();
+ data.setData("1 2 3");
+ data.setOrigin((SimpleQuantity) new SimpleQuantity().setValue(0L));
+ data.setPeriod(1000L);
+ obs.setValue(data);
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true).setParserErrorHandler(new StrictErrorHandler());
+ String encoded = p.encodeResourceToString(obs);
+ ourLog.info(encoded);
+
+ p.parseResource(encoded);
+
+ try {
+ p.parseResource(encoded.replace("Observation", "observation"));
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("DataFormatException at [[row,col {unknown-source}]: [1,1]]: Unknown resource type 'observation': Resource names are case sensitive, found similar name: 'Observation'",
+ e.getMessage());
+ }
+
+ try {
+ p.parseResource(encoded.replace("valueSampledData", "valueSampleddata"));
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Unknown element 'valueSampleddata' found during parse", e.getMessage());
+ }
+ }
+
+ /**
+ * See #551
+ */
+ @Test
+ public void testXmlLargeAttribute() {
+ String largeString = StringUtils.leftPad("", (int) FileUtils.ONE_MB, 'A');
+
+ Patient p = new Patient();
+ p.addName().setFamily(largeString);
+
+ String encoded = ourCtx.newXmlParser().encodeResourceToString(p);
+
+ p = ourCtx.newXmlParser().parseResource(Patient.class, encoded);
+
+ assertEquals(largeString, p.getNameFirstRep().getFamily());
+ }
+
+ /**
+ * See #339
+ *
+ * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing
+ */
+ @Test
+ public void testXxe() {
+
+ String input = "" +
+ "" +
+ "]>" +
+ "" +
+ "" +
+ "TEXT &xxe; TEXT" +
+ " " +
+ "" +
+ "" +
+ " " +
+ " ";
+
+ ourLog.info(input);
+
+ try {
+ ourCtx.newXmlParser().parseResource(Patient.class, input);
+ fail();
+ } catch (DataFormatException e) {
+ assertThat(e.toString(), containsString("Undeclared general entity"));
+ }
+
+ }
+
+ public static void compareXml(String content, String reEncoded) {
+ Diff d = DiffBuilder.compare(Input.fromString(content))
+ .withTest(Input.fromString(reEncoded))
+ .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))
+ .checkForSimilar()
+ .ignoreWhitespace() // this is working with newest Saxon 9.8.0-2 (not worked with 9.7.0-15
+ .ignoreComments() // this is not working even with newest Saxon 9.8.0-2
+ .withComparisonController(ComparisonControllers.Default)
+ .build();
+
+ assertTrue(d.toString(), !d.hasDifferences());
+ }
+
+ @ResourceDef(name = "Patient")
+ public static class TestPatientFor327 extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(name = "testCondition")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false)
+ private List testConditions = null;
+
+ public List getConditions() {
+ return this.testConditions;
+ }
+
+ public void setCondition(List ref) {
+ this.testConditions = ref;
+ }
+ }
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java
new file mode 100644
index 00000000000..84b8ceaf4ae
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeader.java
@@ -0,0 +1,46 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+import ca.uhn.fhir.model.api.annotation.Block;
+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 org.hl7.fhir.dstu3.model.Identifier;
+import org.hl7.fhir.dstu3.model.MessageHeader;
+import org.hl7.fhir.exceptions.FHIRException;
+
+@ResourceDef(name = "MessageHeader")
+public class FooMessageHeader extends MessageHeader {
+
+ private static final long serialVersionUID = 1L;
+
+ @Block()
+ public static class FooMessageSourceComponent extends MessageSourceComponent {
+
+ private static final long serialVersionUID = 1L;
+ @Child(name = "ext-messageheader-application-id", type = Identifier.class, modifier = true)
+ @Description(shortDefinition = "Message Header Application ID")
+ @Extension(url = "http://foo", definedLocally = false, isModifier = false)
+ private Identifier messageHeaderApplicationId;
+
+ /*
+ * Get messageHeaderApplicationId
+ */
+ public Identifier getMessageHeaderApplicationId() throws FHIRException {
+
+ if (messageHeaderApplicationId == null) {
+ messageHeaderApplicationId = new Identifier();
+ }
+ return messageHeaderApplicationId;
+ }
+
+ /*
+ * Set messageHeaderApplicationId
+ */
+ public void setmessageHeaderApplicationId(Identifier messageHeaderApplicationId) {
+ this.messageHeaderApplicationId = messageHeaderApplicationId;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java
new file mode 100644
index 00000000000..97714273f47
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/FooMessageHeaderWithExplicitField.java
@@ -0,0 +1,57 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+import ca.uhn.fhir.model.api.annotation.Block;
+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 org.hl7.fhir.dstu3.model.Identifier;
+import org.hl7.fhir.dstu3.model.MessageHeader;
+import org.hl7.fhir.exceptions.FHIRException;
+
+@ResourceDef(name = "FooMessageHeader")
+public class FooMessageHeaderWithExplicitField extends MessageHeader {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The source application from which this message originated.
+ */
+ @Child(name = "source", type = {}, order = Child.REPLACE_PARENT, min = 1, max = 1, modifier = false, summary = true)
+ @Description(shortDefinition = "Message Source Application", formalDefinition = "The source application from which this message originated.")
+ protected FooMessageSourceComponent source;
+
+ public void setSourceNew(FooMessageSourceComponent theSource) {
+ source = theSource;
+ }
+
+ @Block()
+ public static class FooMessageSourceComponent extends MessageSourceComponent {
+
+ private static final long serialVersionUID = 1L;
+ @Child(name = "ext-messageheader-application-id", type = Identifier.class, modifier = true)
+ @Description(shortDefinition = "Message Header Application ID")
+ @Extension(url = "http://foo", definedLocally = false, isModifier = false)
+ private Identifier messageHeaderApplicationId;
+
+ /*
+ * Get messageHeaderApplicationId
+ */
+ public Identifier getMessageHeaderApplicationId() throws FHIRException {
+
+ if (messageHeaderApplicationId == null) {
+ messageHeaderApplicationId = new Identifier();
+ }
+ return messageHeaderApplicationId;
+ }
+
+ /*
+ * Set messageHeaderApplicationId
+ */
+ public void setmessageHeaderApplicationId(Identifier messageHeaderApplicationId) {
+ this.messageHeaderApplicationId = messageHeaderApplicationId;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java
new file mode 100644
index 00000000000..c4949c0e6aa
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithCustomUrlExtension.java
@@ -0,0 +1,52 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+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 org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.dstu3.model.StringType;
+
+@ResourceDef()
+public class MyPatientWithCustomUrlExtension extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(name = "petName")
+ @Extension(url = "/petname", definedLocally = false, isModifier = false)
+ @Description(shortDefinition = "The name of the patient's favourite pet")
+ private StringType myPetName;
+
+ @Child(name = "customid")
+ @Extension(url = "/customid", definedLocally = false, isModifier = false)
+ @Description(shortDefinition = "The customid of the patient's ")
+ private IdType myCustomId;
+
+ public StringType getPetName() {
+ if (myPetName == null) {
+ myPetName = new StringType();
+ }
+ return myPetName;
+ }
+
+ public void setPetName(final StringType thePetName) {
+ myPetName = thePetName;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty() && getCustomId().isEmpty() && getPetName().isEmpty();
+ }
+
+ public IdType getCustomId() {
+ if (myCustomId == null) {
+ myCustomId = new IdType();
+ }
+ return myCustomId;
+ }
+
+ public void setCustomId(final IdType myCustomId) {
+ this.myCustomId = myCustomId;
+ }
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java
new file mode 100644
index 00000000000..2be26671ce4
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/MyPatientWithOneDeclaredEnumerationExtensionDstu3.java
@@ -0,0 +1,66 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+import java.util.List;
+import ca.uhn.fhir.model.api.annotation.Block;
+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 org.hl7.fhir.dstu3.model.Address.AddressUse;
+import org.hl7.fhir.dstu3.model.Enumeration;
+import org.hl7.fhir.dstu3.model.Identifier;
+import org.hl7.fhir.dstu3.model.Patient;
+
+@ResourceDef(name = "Patient")
+public class MyPatientWithOneDeclaredEnumerationExtensionDstu3 extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(order = 0, name = "foo")
+ @Extension(url = "urn:foo", definedLocally = true, isModifier = false)
+ private Enumeration myFoo;
+
+ /**
+ * A contact party (e.g. guardian, partner, friend) for the patient.
+ */
+ @Child(name = "contact", type = {}, order=Child.REPLACE_PARENT, min=0, max=Child.MAX_UNLIMITED, modifier=false, summary=false)
+ @Description(shortDefinition="A contact party (e.g. guardian, partner, friend) for the patient", formalDefinition="A contact party (e.g. guardian, partner, friend) for the patient." )
+ protected List contact;
+
+ public Enumeration getFoo() {
+ return myFoo;
+ }
+
+ public void setFoo(Enumeration theFoo) {
+ myFoo = theFoo;
+ }
+
+ @Block()
+ public static class MessageSourceComponent extends ContactComponent {
+
+ private static final long serialVersionUID = 1L;
+ @Child(name = "contact-eyecolour", type = { Identifier.class }, modifier = true)
+ @Description(shortDefinition = "Application ID")
+ @Extension(url = "http://foo.com/contact-eyecolour", definedLocally = false, isModifier = false)
+ private Identifier myEyeColour;
+
+ /*
+ * Get messageHeaderApplicationId
+ */
+ public Identifier getEyeColour() {
+ if (myEyeColour == null) {
+ myEyeColour = new Identifier();
+ }
+ return myEyeColour;
+ }
+
+ /*
+ * Set messageHeaderApplicationId
+ */
+ public void setEyeColour(Identifier messageHeaderApplicationId) {
+ this.myEyeColour = messageHeaderApplicationId;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java
new file mode 100644
index 00000000000..f05e39f37c6
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientProfileDstu3.java
@@ -0,0 +1,72 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+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.util.ElementUtil;
+import org.hl7.fhir.dstu3.model.CodeableConcept;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.dstu3.model.Reference;
+
+@ResourceDef(name="Patient", profile = "http://hl7.org/fhir/StructureDefinition/Patient")
+public class PatientProfileDstu3 extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(name="owner", min=0, max=1)
+ @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#owningOrganization", definedLocally=false, isModifier=false)
+ @Description(shortDefinition="The organization that owns this animal")
+ private Reference owningOrganization;
+
+ public Reference getOwningOrganization() {
+ if (owningOrganization == null) {
+ owningOrganization = new Reference();
+ }
+ return owningOrganization;
+ }
+
+ public PatientProfileDstu3 setOwningOrganization(Reference owningOrganization) {
+ this.owningOrganization = owningOrganization;
+ return this;
+ }
+
+ @Child(name="colorPrimary", min=0, max=1)
+ @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorPrimary", definedLocally=false, isModifier=false)
+ @Description(shortDefinition="The animals primary color")
+ private CodeableConcept colorPrimary;
+
+ @Child(name="colorSecondary", min=0, max=1)
+ @Extension(url="http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary", definedLocally=false, isModifier=false)
+ @Description(shortDefinition="The animals secondary color")
+ private CodeableConcept colorSecondary;
+
+ public CodeableConcept getColorPrimary() {
+ if (this.colorPrimary == null) {
+ return new CodeableConcept();
+ }
+ return colorPrimary;
+ }
+
+ public void setColorPrimary(CodeableConcept colorPrimary) {
+ this.colorPrimary = colorPrimary;
+ }
+
+ public CodeableConcept getColorSecondary() {
+ if (this.colorSecondary == null) {
+ return new CodeableConcept();
+ }
+ return colorSecondary;
+ }
+
+ public void setColorSecondary(CodeableConcept colorSecondary) {
+ this.colorSecondary = colorSecondary;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty() && ElementUtil.isEmpty(owningOrganization) && ElementUtil.isEmpty(colorPrimary)
+ && ElementUtil.isEmpty(colorSecondary) ;
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java
new file mode 100644
index 00000000000..9521c2f96ff
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/PatientWithCustomCompositeExtension.java
@@ -0,0 +1,81 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+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.util.ElementUtil;
+import org.hl7.fhir.dstu3.model.BackboneElement;
+import org.hl7.fhir.dstu3.model.Patient;
+import org.hl7.fhir.dstu3.model.StringType;
+
+@ResourceDef(name = "Patient")
+public class PatientWithCustomCompositeExtension extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * A custom extension
+ */
+ @Child(name = "foo")
+ @Extension(url="http://acme.org/fooParent", definedLocally = false, isModifier = false)
+ protected FooParentExtension fooParentExtension;
+
+ public FooParentExtension getFooParentExtension() {
+ return fooParentExtension;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty() && ElementUtil.isEmpty(fooParentExtension);
+ }
+
+ public void setFooParentExtension(FooParentExtension theFooParentExtension) {
+ fooParentExtension = theFooParentExtension;
+ }
+
+ @Block
+ public static class FooParentExtension extends BackboneElement {
+
+ private static final long serialVersionUID = 4522090347756045145L;
+
+ @Child(name = "childA")
+ @Extension(url = "http://acme.org/fooChildA", definedLocally = false, isModifier = false)
+ private StringType myChildA;
+
+ @Child(name = "childB")
+ @Extension(url = "http://acme.org/fooChildB", definedLocally = false, isModifier = false)
+ private StringType myChildB;
+
+ @Override
+ public FooParentExtension copy() {
+ FooParentExtension copy = new FooParentExtension();
+ copy.myChildA = myChildA;
+ copy.myChildB = myChildB;
+ return copy;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty() && ElementUtil.isEmpty(myChildA, myChildB);
+ }
+
+ public StringType getChildA() {
+ return myChildA;
+ }
+
+ public StringType getChildB() {
+ return myChildB;
+ }
+
+ public void setChildA(StringType theChildA) {
+ myChildA = theChildA;
+ }
+
+ public void setChildB(StringType theChildB) {
+ myChildB = theChildB;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java
new file mode 100644
index 00000000000..d0918aa628f
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/dstu3/ResourceValidatorDstu3FeatureTest.java
@@ -0,0 +1,410 @@
+package ca.uhn.fhir.tests.integration.karaf.dstu3;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.model.api.annotation.Child;
+import ca.uhn.fhir.model.api.annotation.ResourceDef;
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.parser.StrictErrorHandler;
+import ca.uhn.fhir.validation.*;
+import ca.uhn.fhir.validation.schematron.SchematronBaseValidator;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.Validate;
+import org.hamcrest.core.StringContains;
+import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
+import org.hl7.fhir.dstu3.context.IWorkerContext;
+import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
+import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
+import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
+import org.hl7.fhir.dstu3.model.*;
+import org.hl7.fhir.exceptions.FHIRException;
+import org.hl7.fhir.utilities.validation.ValidationMessage;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_DSTU3;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class ResourceValidatorDstu3FeatureTest {
+
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceValidatorDstu3FeatureTest.class);
+ private FhirContext ourCtx = FhirContext.forDstu3();
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ HAPI_FHIR_VALIDATION_DSTU3.option(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ WRAP.option(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+
+
+ private List logResultsAndReturnNonInformationalOnes(ValidationResult theOutput) {
+ List retVal = new ArrayList<>();
+
+ int index = 0;
+ for (SingleValidationMessage next : theOutput.getMessages()) {
+ ourLog.info("Result {}: {} - {} - {}",
+ new Object[]{index, next.getSeverity(), next.getLocationString(), next.getMessage()});
+ index++;
+
+ if (next.getSeverity() != ResultSeverityEnum.INFORMATION) {
+ retVal.add(next);
+ }
+ }
+
+ return retVal;
+ }
+
+ /**
+ * See issue #50
+ */
+ @Test
+ public void testOutOfBoundsDate() {
+ Patient p = new Patient();
+ p.setBirthDateElement(new DateType("2000-12-31"));
+
+ // Put in an invalid date
+ IParser parser = ourCtx.newXmlParser();
+ parser.setParserErrorHandler(new StrictErrorHandler());
+
+ String encoded = parser.setPrettyPrint(true).encodeResourceToString(p).replace("2000-12-31", "2000-15-31");
+ ourLog.info(encoded);
+
+ assertThat(encoded, StringContains.containsString("2000-15-31"));
+
+ ValidationResult result = ourCtx.newValidator().validateWithResult(encoded);
+ String resultString = parser.setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome());
+ ourLog.info(resultString);
+
+ assertEquals(2, ((OperationOutcome) result.toOperationOutcome()).getIssue().size());
+ assertThat(resultString, StringContains.containsString("cvc-pattern-valid"));
+
+ try {
+ parser.parseResource(encoded);
+ fail();
+ } catch (DataFormatException e) {
+ assertEquals("DataFormatException at [[row,col {unknown-source}]: [2,4]]: Invalid attribute value \"2000-15-31\": Invalid date/time format: \"2000-15-31\"", e.getMessage());
+ }
+ }
+ @Test
+ public void testValidateCareTeamXsd() {
+ CareTeam careTeam = new CareTeam();
+ careTeam
+ .addParticipant()
+ .setMember(new Reference("http://example.com/Practitioner/1647bbb2-3b12-43cc-923c-a475f817e881"))
+ .setOnBehalfOf(new Reference("Organization/5859a28f-01e7-42d8-a8ba-48b31679a828"));
+
+ IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
+ String encoded = parser.encodeResourceToString(careTeam);
+
+ ourLog.info(encoded);
+
+ FhirValidator val = ourCtx.newValidator();
+
+ ValidationResult result = val.validateWithResult(encoded);
+ String resultString = parser.setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome());
+ ourLog.info(resultString);
+
+ assertThat(resultString, containsString("No issues detected during validation"));
+
+ }
+
+ @Test
+ public void testValidateCodeableConceptContainingOnlyBadCode() {
+ Patient p = new Patient();
+ p.getMaritalStatus().addCoding().setSystem("http://hl7.org/fhir/v3/MaritalStatus").setCode("FOO");
+
+ FhirValidator val = ourCtx.newValidator();
+ val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
+ val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
+ val.registerValidatorModule(new FhirInstanceValidator());
+
+ ValidationResult output = val.validateWithResult(p);
+ List all = logResultsAndReturnNonInformationalOnes(output);
+
+ assertEquals("None of the codes provided are in the value set http://hl7.org/fhir/ValueSet/marital-status (http://hl7.org/fhir/ValueSet/marital-status, and a code should come from this value set unless it has no suitable code) (codes = http://hl7.org/fhir/v3/MaritalStatus#FOO)", output.getMessages().get(0).getMessage());
+ assertEquals(ResultSeverityEnum.WARNING, output.getMessages().get(0).getSeverity());
+ }
+
+ @Test
+ public void testValidateCodeableConceptContainingOnlyGoodCode() {
+ Patient p = new Patient();
+ p.getMaritalStatus().addCoding().setSystem("http://hl7.org/fhir/v3/MaritalStatus").setCode("M");
+
+ FhirValidator val = ourCtx.newValidator();
+ val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
+ val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
+ val.registerValidatorModule(new FhirInstanceValidator());
+
+ ValidationResult output = val.validateWithResult(p);
+ List all = logResultsAndReturnNonInformationalOnes(output);
+ assertEquals(0, all.size());
+ assertEquals(0, output.getMessages().size());
+ }
+
+ @Test
+ public void testValidateJsonNumericId() {
+ String input = "{\"resourceType\": \"Patient\",\n" +
+ " \"id\": 123,\n" +
+ " \"meta\": {\n" +
+ " \"versionId\": \"29\",\n" +
+ " \"lastUpdated\": \"2015-12-22T19:53:11.000Z\"\n" +
+ " },\n" +
+ " \"communication\": {\n" +
+ " \"language\": {\n" +
+ " \"coding\": [\n" +
+ " {\n" +
+ " \"system\": \"urn:ietf:bcp:47\",\n" +
+ " \"code\": \"hi\",\n" +
+ " \"display\": \"Hindi\",\n" +
+ " \"userSelected\": false\n" +
+ " }],\n" +
+ " \"text\": \"Hindi\"\n" +
+ " },\n" +
+ " \"preferred\": true\n" +
+ " }\n" +
+ "}";
+
+ FhirValidator val = ourCtx.newValidator();
+ val.registerValidatorModule(new FhirInstanceValidator());
+ ValidationResult output = val.validateWithResult(input);
+
+ OperationOutcome operationOutcome = (OperationOutcome) output.toOperationOutcome();
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
+// ourLog.info(encoded);
+
+ assertThat(encoded, containsString("Error parsing JSON: the primitive value must be a string"));
+
+ }
+
+ @Test
+ public void testValidateQuestionnaireWithCanonicalUrl() {
+ String input = "{\n" +
+ " \"resourceType\": \"Questionnaire\",\n" +
+ " \"url\": \"http://some.example.url\",\n" +
+ " \"status\": \"active\",\n" +
+ " \"subjectType\": [\n" +
+ " \"Patient\"\n" +
+ " ],\n" +
+ " \"item\": [\n" +
+ " {\n" +
+ " \"linkId\": \"example-question\",\n" +
+ " \"text\": \"Is the sky blue?\",\n" +
+ " \"type\": \"choice\",\n" +
+ " \"options\": {\n" +
+ " \"reference\": \"http://loinc.org/vs/LL3044-6\"\n" +
+ " }\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+
+ Questionnaire q = new Questionnaire();
+ q = ourCtx.newJsonParser().parseResource(Questionnaire.class, input);
+
+ FhirValidator val = ourCtx.newValidator();
+ val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
+ val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
+ val.registerValidatorModule(new FhirInstanceValidator());
+
+ ValidationResult result = val.validateWithResult(q);
+
+ OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
+ ourLog.info(encoded);
+
+ }
+
+ /**
+ * Make sure that the elements that appear in all resources (meta, language, extension, etc) all appear in the correct order
+ */
+ @Test
+ public void testValidateResourceWithResourceElements() {
+ TestPatientFor327 patient = new TestPatientFor327();
+ patient.setBirthDate(new Date());
+ patient.setId("123");
+ patient.getText().setDivAsString("FOO");
+ patient.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
+ patient.getLanguageElement().setValue("en");
+ patient.addExtension().setUrl("http://foo").setValue(new StringType("MOD"));
+ patient.getMeta().setLastUpdated(new Date());
+
+ List conditions = new ArrayList();
+ Condition condition = new Condition();
+ condition.getSubject().setReference("Patient/123");
+ condition.addBodySite().setText("BODY SITE");
+ condition.getCode().setText("CODE");
+ condition.setClinicalStatus(Condition.ConditionClinicalStatus.ACTIVE);
+ condition.setVerificationStatus(Condition.ConditionVerificationStatus.CONFIRMED);
+ conditions.add(new Reference(condition));
+ patient.setCondition(conditions);
+ patient.addIdentifier().setSystem("http://foo").setValue("123");
+
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
+ ourLog.info(encoded);
+
+ FhirValidator val = ourCtx.newValidator();
+ val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
+ val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
+ val.registerValidatorModule(new FhirInstanceValidator());
+
+ ValidationResult result = val.validateWithResult(encoded);
+
+ OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
+ String ooencoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
+ ourLog.info(ooencoded);
+
+ assertTrue(result.isSuccessful());
+
+ assertThat(ooencoded, containsString("Unknown extension http://foo"));
+ }
+
+ /**
+ * See https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= email&utm_source=footer
+ */
+ @Test
+ public void testValidateWithExtensionsJson() {
+ PatientProfileDstu3 myPatient = new PatientProfileDstu3();
+ myPatient.setId("1");
+ myPatient.setColorPrimary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-grey")));
+ myPatient.setColorSecondary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-white")));
+ myPatient.setOwningOrganization(new Reference("Organization/2.25.79433498044103547197447759549862032393"));
+ myPatient.addName().setFamily("FamilyName");
+ myPatient.addExtension().setUrl("http://foo.com/example").setValue(new StringType("String Extension"));
+
+ IParser p = ourCtx.newJsonParser().setPrettyPrint(true);
+ String messageString = p.encodeResourceToString(myPatient);
+// ourLog.info(messageString);
+
+ String[] strings = {"meta",
+ "String Extension",
+ "Organization/2.25.79433498044103547197447759549862032393",
+ "furry-grey",
+ "furry-white",
+ "FamilyName"};
+ assertThat(messageString, stringContainsInOrder(
+ Arrays.asList(strings)
+ ));
+ String[] strings1 = {"extension",
+ "meta"};
+ assertThat(messageString, not(stringContainsInOrder(
+ Arrays.asList(strings1)
+ )));
+
+ FhirValidator val = ourCtx.newValidator();
+ val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
+ val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
+ val.registerValidatorModule(new FhirInstanceValidator());
+
+ ValidationResult result = val.validateWithResult(messageString);
+
+ OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
+ ourLog.info(encoded);
+
+ assertTrue(result.isSuccessful());
+
+ assertThat(messageString, containsString("valueReference"));
+ assertThat(messageString, not(containsString("valueResource")));
+ }
+
+ /**
+ * See https://groups.google.com/d/msgid/hapi-fhir/a266083f-6454-4cf0-a431-c6500f052bea%40googlegroups.com?utm_medium= email&utm_source=footer
+ */
+ @Test
+ public void testValidateWithExtensionsXml() {
+ PatientProfileDstu3 myPatient = new PatientProfileDstu3();
+ myPatient.setId("1");
+ myPatient.setColorPrimary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-grey")));
+ myPatient.setColorSecondary(new CodeableConcept().addCoding(new Coding().setSystem("http://example.com#animalColor").setCode("furry-white")));
+ myPatient.setOwningOrganization(new Reference("Organization/2.25.79433498044103547197447759549862032393"));
+ myPatient.addName().setFamily("FamilyName");
+ myPatient.addExtension().setUrl("http://foo.com/example").setValue(new StringType("String Extension"));
+
+ IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
+ String messageString = p.encodeResourceToString(myPatient);
+ ourLog.info(messageString);
+
+ //@formatter:off
+ String[] strings = {"meta",
+ "Organization/2.25.79433498044103547197447759549862032393",
+ "furry-grey",
+ "furry-white",
+ "String Extension",
+ "FamilyName"};
+ assertThat(messageString, stringContainsInOrder(
+ Arrays.asList(strings)
+ ));
+ String[] strings1 = {"extension",
+ "meta"};
+ assertThat(messageString, not(stringContainsInOrder(
+ Arrays.asList(strings1)
+ )));
+ assertThat(messageString, containsString("url=\"http://ahr.copa.inso.tuwien.ac.at/StructureDefinition/Patient#animal-colorSecondary\""));
+ assertThat(messageString, containsString("url=\"http://foo.com/example\""));
+ //@formatter:on
+
+ FhirValidator val = ourCtx.newValidator();
+ val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
+ val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
+ val.registerValidatorModule(new FhirInstanceValidator());
+
+ ValidationResult result = val.validateWithResult(messageString);
+
+ OperationOutcome operationOutcome = (OperationOutcome) result.toOperationOutcome();
+ String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(operationOutcome);
+ ourLog.info(encoded);
+
+ assertTrue(result.isSuccessful());
+
+ assertThat(messageString, containsString("valueReference"));
+ assertThat(messageString, not(containsString("valueResource")));
+ }
+
+ @ResourceDef(name = "Patient")
+ public static class TestPatientFor327 extends Patient {
+
+ private static final long serialVersionUID = 1L;
+
+ @Child(name = "testCondition")
+ @ca.uhn.fhir.model.api.annotation.Extension(url = "testCondition", definedLocally = true, isModifier = false)
+ private List testConditions = null;
+
+ public List getConditions() {
+ return this.testConditions;
+ }
+
+ public void setCondition(List ref) {
+ this.testConditions = ref;
+ }
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java
new file mode 100644
index 00000000000..1ae2468018f
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/FhirInstanceValidatorR4Test.java
@@ -0,0 +1,114 @@
+package ca.uhn.fhir.tests.integration.karaf.r4;
+
+import java.io.IOException;
+import java.util.List;
+import ca.uhn.fhir.context.FhirContext;
+import org.hl7.fhir.exceptions.FHIRException;
+import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
+import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
+import org.hl7.fhir.r4.model.Base;
+import org.hl7.fhir.r4.model.BooleanType;
+import org.hl7.fhir.r4.model.Observation;
+import org.hl7.fhir.r4.model.Patient;
+import org.hl7.fhir.r4.model.StringType;
+import org.hl7.fhir.r4.model.StructureDefinition;
+import org.hl7.fhir.r4.utils.FHIRPathEngine;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_R4;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class FhirInstanceValidatorR4Test {
+
+ private FhirContext ourCtx = FhirContext.forR4();
+ private FHIRPathEngine ourEngine = new FHIRPathEngine(new HapiWorkerContext(ourCtx, new DefaultProfileValidationSupport()));
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirInstanceValidatorR4Test.class);
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ HAPI_FHIR_VALIDATION_R4.option(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ WRAP.option(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+
+ @Test
+ public void testAs() throws Exception {
+ Observation obs = new Observation();
+ obs.setValue(new StringType("FOO"));
+
+ List value = ourEngine.evaluate(obs, "Observation.value.as(String)");
+ assertEquals(1, value.size());
+ assertEquals("FOO", ((StringType)value.get(0)).getValue());
+ }
+
+ @Test
+ public void testExistsWithNoValue() throws FHIRException {
+ Patient patient = new Patient();
+ patient.setDeceased(new BooleanType());
+ List eval = ourEngine.evaluate(patient, "Patient.deceased.exists()");
+ ourLog.info(eval.toString());
+ assertFalse(((BooleanType)eval.get(0)).getValue());
+ }
+
+ @Test
+ public void testExistsWithValue() throws FHIRException {
+ Patient patient = new Patient();
+ patient.setDeceased(new BooleanType(false));
+ List eval = ourEngine.evaluate(patient, "Patient.deceased.exists()");
+ ourLog.info(eval.toString());
+ assertTrue(((BooleanType)eval.get(0)).getValue());
+ }
+
+ @Test
+ public void testConcatenation() throws FHIRException {
+ String exp = "Patient.name.family & '.'";
+
+ Patient p = new Patient();
+ p.addName().setFamily("TEST");
+ String result = ourEngine.evaluateToString(p, exp);
+ assertEquals("TEST.", result);
+ }
+
+ @Test
+ public void testConcatenationFunction() throws FHIRException {
+ String exp = "element.first().path.startsWith(%resource.type) and element.tail().all(path.startsWith(%resource.type&'.'))";
+
+ StructureDefinition sd = new StructureDefinition();
+ StructureDefinition.StructureDefinitionDifferentialComponent diff = sd.getDifferential();
+
+ diff.addElement().setPath("Patient.name");
+
+
+ Patient p = new Patient();
+ p.addName().setFamily("TEST");
+ List result = ourEngine.evaluate(null, p, diff, exp);
+ ourLog.info(result.toString());
+// assertEquals("TEST.", result);
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java
new file mode 100644
index 00000000000..e5c617d5de2
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4JsonParserTest.java
@@ -0,0 +1,275 @@
+package ca.uhn.fhir.tests.integration.karaf.r4;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.parser.IParser;
+import com.google.common.collect.Sets;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Extension;
+import org.hl7.fhir.r4.model.Medication;
+import org.hl7.fhir.r4.model.MedicationDispense;
+import org.hl7.fhir.r4.model.MedicationRequest;
+import org.hl7.fhir.r4.model.Patient;
+import org.hl7.fhir.r4.model.Reference;
+import org.hl7.fhir.r4.model.StringType;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_R4;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class R4JsonParserTest {
+
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(R4JsonParserTest.class);
+ private FhirContext ourCtx = FhirContext.forR4();
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ WRAP.option(),
+ HAPI_FHIR_R4.option(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+
+ private Bundle createBundleWithPatient() {
+ Bundle b = new Bundle();
+ b.setId("BUNDLEID");
+ b.getMeta().addProfile("http://FOO");
+
+ Patient p = new Patient();
+ p.setId("PATIENTID");
+ p.getMeta().addProfile("http://BAR");
+ p.addName().addGiven("GIVEN");
+ b.addEntry().setResource(p);
+ return b;
+ }
+
+ /**
+ * See #814
+ */
+ @Test
+ public void testDuplicateContainedResourcesNotOutputtedTwice() {
+ MedicationDispense md = new MedicationDispense();
+
+ MedicationRequest mr = new MedicationRequest();
+ md.addAuthorizingPrescription().setResource(mr);
+
+ Medication med = new Medication();
+ md.setMedication(new Reference(med));
+ mr.setMedication(new Reference(med));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(md);
+ ourLog.info(encoded);
+
+ int idx = encoded.indexOf("\"Medication\"");
+ assertNotEquals(-1, idx);
+
+ idx = encoded.indexOf("\"Medication\"", idx + 1);
+ assertEquals(-1, idx);
+
+ }
+
+ /**
+ * See #814
+ */
+ @Test
+ public void testDuplicateContainedResourcesNotOutputtedTwiceWithManualIds() {
+ MedicationDispense md = new MedicationDispense();
+
+ MedicationRequest mr = new MedicationRequest();
+ mr.setId("#MR");
+ md.addAuthorizingPrescription().setResource(mr);
+
+ Medication med = new Medication();
+ med.setId("#MED");
+ md.setMedication(new Reference(med));
+ mr.setMedication(new Reference(med));
+
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(md);
+ ourLog.info(encoded);
+
+ int idx = encoded.indexOf("\"Medication\"");
+ assertNotEquals(-1, idx);
+
+ idx = encoded.indexOf("\"Medication\"", idx + 1);
+ assertEquals(-1, idx);
+
+ }
+
+ @Test
+ public void testExcludeNothing() {
+ IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
+ Set excludes = new HashSet<>();
+// excludes.add("*.id");
+ parser.setDontEncodeElements(excludes);
+
+ Bundle b = createBundleWithPatient();
+
+ String encoded = parser.encodeResourceToString(b);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("BUNDLEID"));
+ assertThat(encoded, containsString("http://FOO"));
+ assertThat(encoded, containsString("PATIENTID"));
+ assertThat(encoded, containsString("http://BAR"));
+ assertThat(encoded, containsString("GIVEN"));
+
+ b = parser.parseResource(Bundle.class, encoded);
+
+ assertEquals("BUNDLEID", b.getIdElement().getIdPart());
+ assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
+ assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
+ }
+
+ @Test
+ public void testExcludeRootStuff() {
+ IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
+ Set excludes = new HashSet<>();
+ excludes.add("id");
+ excludes.add("meta");
+ parser.setDontEncodeElements(excludes);
+
+ Bundle b = createBundleWithPatient();
+
+ String encoded = parser.encodeResourceToString(b);
+ ourLog.info(encoded);
+
+ assertThat(encoded, not(containsString("BUNDLEID")));
+ assertThat(encoded, not(containsString("http://FOO")));
+ assertThat(encoded, (containsString("PATIENTID")));
+ assertThat(encoded, (containsString("http://BAR")));
+ assertThat(encoded, containsString("GIVEN"));
+
+ b = parser.parseResource(Bundle.class, encoded);
+
+ assertNotEquals("BUNDLEID", b.getIdElement().getIdPart());
+ assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
+ assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
+ }
+
+ @Test
+ public void testExcludeStarDotStuff() {
+ IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
+ Set excludes = new HashSet<>();
+ excludes.add("*.id");
+ excludes.add("*.meta");
+ parser.setDontEncodeElements(excludes);
+
+ Bundle b = createBundleWithPatient();
+
+ String encoded = parser.encodeResourceToString(b);
+ ourLog.info(encoded);
+
+ assertThat(encoded, not(containsString("BUNDLEID")));
+ assertThat(encoded, not(containsString("http://FOO")));
+ assertThat(encoded, not(containsString("PATIENTID")));
+ assertThat(encoded, not(containsString("http://BAR")));
+ assertThat(encoded, containsString("GIVEN"));
+
+ b = parser.parseResource(Bundle.class, encoded);
+
+ assertNotEquals("BUNDLEID", b.getIdElement().getIdPart());
+ assertNotEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
+ assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
+ }
+
+ /**
+ * Test that long JSON strings don't get broken up
+ */
+ @Test
+ public void testNoBreakInLongString() {
+ String longString = StringUtils.leftPad("", 100000, 'A');
+
+ Patient p = new Patient();
+ p.addName().setFamily(longString);
+ String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
+
+ assertThat(encoded, containsString(longString));
+ }
+
+ @Test
+ public void testParseAndEncodeExtensionWithValueWithExtension() {
+ String input = "{\n" +
+ " \"resourceType\": \"Patient\",\n" +
+ " \"extension\": [\n" +
+ " {\n" +
+ " \"url\": \"https://purl.org/elab/fhir/network/StructureDefinition/1/BirthWeight\",\n" +
+ " \"_valueDecimal\": {\n" +
+ " \"extension\": [\n" +
+ " {\n" +
+ " \"url\": \"http://www.hl7.org/fhir/extension-data-absent-reason.html\",\n" +
+ " \"valueCoding\": {\n" +
+ " \"system\": \"http://hl7.org/fhir/ValueSet/birthweight\",\n" +
+ " \"code\": \"Underweight\",\n" +
+ " \"userSelected\": false\n" +
+ " }\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ " }\n" +
+ " ],\n" +
+ " \"identifier\": [\n" +
+ " {\n" +
+ " \"system\": \"https://purl.org/elab/fhir/network/StructureDefinition/1/EuroPrevallStudySubjects\",\n" +
+ " \"value\": \"1\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"gender\": \"female\"\n" +
+ "}";
+
+ IParser jsonParser = ourCtx.newJsonParser();
+ IParser xmlParser = ourCtx.newXmlParser();
+ jsonParser.setDontEncodeElements(Sets.newHashSet("id", "meta"));
+ xmlParser.setDontEncodeElements(Sets.newHashSet("id", "meta"));
+
+ Patient parsed = jsonParser.parseResource(Patient.class, input);
+
+ ourLog.info(jsonParser.setPrettyPrint(true).encodeResourceToString(parsed));
+ assertThat(xmlParser.encodeResourceToString(parsed), containsString("Underweight"));
+ assertThat(jsonParser.encodeResourceToString(parsed), containsString("Underweight"));
+
+ }
+
+ @Test
+ public void testParseExtensionOnPrimitive() throws IOException {
+ String input = IOUtils.toString(R4JsonParserTest.class.getResourceAsStream("/extension-on-line.txt"));
+ IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);
+ Patient pt = parser.parseResource(Patient.class, input);
+
+ StringType line0 = pt.getAddressFirstRep().getLine().get(0);
+ assertEquals("535 Sheppard Avenue West, Unit 1907", line0.getValue());
+ Extension houseNumberExt = line0.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-houseNumber");
+ assertEquals("535", ((StringType) houseNumberExt.getValue()).getValue());
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java
new file mode 100644
index 00000000000..67b75f1148f
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/java/ca/uhn/fhir/tests/integration/karaf/r4/R4XmlParserTest.java
@@ -0,0 +1,195 @@
+package ca.uhn.fhir.tests.integration.karaf.r4;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.parser.IParser;
+import com.google.common.collect.Sets;
+import org.hamcrest.core.IsNot;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Patient;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_R4;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
+import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
+
+
+/**
+ * Useful docs about this test: https://ops4j1.jira.com/wiki/display/paxexam/FAQ
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class R4XmlParserTest {
+
+ private final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(R4XmlParserTest.class);
+ private FhirContext ourCtx = FhirContext.forR4();
+
+ @Configuration
+ public Option[] config() throws IOException {
+ return options(
+ KARAF.option(),
+ WRAP.option(),
+ HAPI_FHIR_R4.option(),
+ mavenBundle().groupId("org.apache.servicemix.bundles").artifactId("org.apache.servicemix.bundles.hamcrest").versionAsInProject(),
+ when(false)
+ .useOptions(
+ debugConfiguration("5005", true))
+ );
+ }
+ private Bundle createBundleWithPatient() {
+ Bundle b = new Bundle();
+ b.setId("BUNDLEID");
+ b.getMeta().addProfile("http://FOO");
+
+ Patient p = new Patient();
+ p.setId("PATIENTID");
+ p.getMeta().addProfile("http://BAR");
+ p.addName().addGiven("GIVEN");
+ b.addEntry().setResource(p);
+ return b;
+ }
+
+ @Test
+ public void testParseAndEncodeXmlNumericEntity() {
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ Patient p = ourCtx.newXmlParser().parseResource(Patient.class, input);
+ assertEquals("A \n B", p.getNameFirstRep().getFamily());
+
+ String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
+ ourLog.info(output);
+
+ }
+
+ @Test
+ public void testExcludeNothing() {
+ IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
+ Set excludes = new HashSet<>();
+// excludes.add("*.id");
+ parser.setDontEncodeElements(excludes);
+
+ Bundle b = createBundleWithPatient();
+
+ String encoded = parser.encodeResourceToString(b);
+ ourLog.info(encoded);
+
+ assertThat(encoded, containsString("BUNDLEID"));
+ assertThat(encoded, containsString("http://FOO"));
+ assertThat(encoded, containsString("PATIENTID"));
+ assertThat(encoded, containsString("http://BAR"));
+ assertThat(encoded, containsString("GIVEN"));
+
+ b = parser.parseResource(Bundle.class, encoded);
+
+ assertEquals("BUNDLEID", b.getIdElement().getIdPart());
+ assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
+ assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
+ }
+
+ @Test
+ public void testExcludeRootStuff() {
+ IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
+ Set excludes = new HashSet<>();
+ excludes.add("id");
+ excludes.add("meta");
+ parser.setDontEncodeElements(excludes);
+
+ Bundle b = createBundleWithPatient();
+
+ String encoded = parser.encodeResourceToString(b);
+ ourLog.info(encoded);
+
+ assertThat(encoded, IsNot.not(containsString("BUNDLEID")));
+ assertThat(encoded, IsNot.not(containsString("http://FOO")));
+ assertThat(encoded, (containsString("PATIENTID")));
+ assertThat(encoded, (containsString("http://BAR")));
+ assertThat(encoded, containsString("GIVEN"));
+
+ b = parser.parseResource(Bundle.class, encoded);
+
+ assertNotEquals("BUNDLEID", b.getIdElement().getIdPart());
+ assertEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
+ assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
+ }
+
+ @Test
+ public void testExcludeStarDotStuff() {
+ IParser parser = ourCtx.newXmlParser().setPrettyPrint(true);
+ Set excludes = new HashSet<>();
+ excludes.add("*.id");
+ excludes.add("*.meta");
+ parser.setDontEncodeElements(excludes);
+
+ Bundle b = createBundleWithPatient();
+
+ String encoded = parser.encodeResourceToString(b);
+ ourLog.info(encoded);
+
+ assertThat(encoded, IsNot.not(containsString("BUNDLEID")));
+ assertThat(encoded, IsNot.not(containsString("http://FOO")));
+ assertThat(encoded, IsNot.not(containsString("PATIENTID")));
+ assertThat(encoded, IsNot.not(containsString("http://BAR")));
+ assertThat(encoded, containsString("GIVEN"));
+
+ b = parser.parseResource(Bundle.class, encoded);
+
+ assertNotEquals("BUNDLEID", b.getIdElement().getIdPart());
+ assertNotEquals("Patient/PATIENTID", ((Patient) b.getEntry().get(0).getResource()).getId());
+ assertEquals("GIVEN", ((Patient) b.getEntry().get(0).getResource()).getNameFirstRep().getGivenAsSingleString());
+ }
+
+ @Test
+ public void testParseAndEncodeExtensionWithValueWithExtension() {
+ String input = "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "
\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " ";
+
+ IParser xmlParser = ourCtx.newXmlParser();
+ IParser jsonParser = ourCtx.newJsonParser();
+ jsonParser.setDontEncodeElements(Sets.newHashSet("id", "meta"));
+ xmlParser.setDontEncodeElements(Sets.newHashSet("id", "meta"));
+
+ Patient parsed = xmlParser.parseResource(Patient.class, input);
+
+ ourLog.info(jsonParser.setPrettyPrint(true).encodeResourceToString(parsed));
+ assertThat(xmlParser.encodeResourceToString(parsed), containsString("Underweight"));
+ assertThat(jsonParser.encodeResourceToString(parsed), containsString("Underweight"));
+
+ }
+
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json
new file mode 100644
index 00000000000..24557e54b65
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle-example.json
@@ -0,0 +1,53 @@
+{
+ "resourceType": "Bundle",
+ "id": "example",
+ "meta": {
+ "versionId": "1",
+ "lastUpdated": "2014-08-18T01:43:30Z"
+ },
+ "type": "searchset",
+ "total": 3,
+ "link": [
+ {
+ "relation": "next",
+ "url": "https://example.com/base/MedicationOrder?patient=347&searchId=ff15fd40-ff71-4b48-b366-09c706bed9d0&page=2"
+ },
+ {
+ "relation": "self",
+ "url": "https://example.com/base/MedicationOrder?patient=347&_include=MedicationOrder.medication"
+ }
+ ],
+ "entry": [
+ {
+ "fullUrl": "http://example.com/base/MedicationOrder/3123/_history/1",
+ "resource": {
+ "resourceType": "MedicationOrder",
+ "id": "3123",
+ "meta" : {
+ "versionId" : "1",
+ "lastUpdated" : "2014-08-16T05:31:17Z"
+ },
+ "patient": {
+ "reference": "Patient/347"
+ },
+ "medicationReference": {
+ "reference": "Medication/example"
+ }
+ },
+ "search": {
+ "mode": "match",
+ "score": 1
+ }
+ },
+ {
+ "fullUrl": "http://example.com/base/Medication/example",
+ "resource": {
+ "resourceType": "Medication",
+ "id": "example"
+ },
+ "search": {
+ "mode": "include"
+ }
+ }
+ ]
+}
diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml
new file mode 100644
index 00000000000..37a83687b99
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_orion.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml
new file mode 100644
index 00000000000..8fe8320c489
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_ref_by_uuid_544.xml
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml
new file mode 100644
index 00000000000..cd189a0838e
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_contained_with_no_id.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml
new file mode 100644
index 00000000000..d10ece0f0b4
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_invalid_contained_ref.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml
new file mode 100644
index 00000000000..a7d0cca0016
--- /dev/null
+++ b/hapi-fhir-karaf-integration-tests/src/test/resources/bundle_with_woven_obs.xml
@@ -0,0 +1,317 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz b/hapi-fhir-karaf-integration-tests/src/test/resources/conformance.json.gz
new file mode 100644
index 0000000000000000000000000000000000000000..9f5ca59e23715949f366c9b61fe80fce5daba832
GIT binary patch
literal 40983
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