diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index d2b2b83ed1f..fcfdad2b0c8 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -1221,15 +1221,8 @@ public class JsonParser extends BaseParser implements IParser { assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType"); String resourceType = ((JsonString) resourceTypeObj).getString(); - RuntimeResourceDefinition def; - if (theResourceType != null) { - def = myContext.getResourceDefinition(theResourceType); - } else { - def = myContext.getResourceDefinition(resourceType); - } - - ParserState state = ParserState.getPreResourceInstance(def.getImplementingClass(), myContext, true, getErrorHandler()); - state.enteringNewElement(null, def.getName()); + ParserState state = ParserState.getPreResourceInstance(theResourceType, myContext, true, getErrorHandler()); + state.enteringNewElement(null, resourceType); parseChildren(object, state); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java index 57d19cbea43..e06264ede47 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java @@ -488,7 +488,7 @@ class ParserState { } else if ("author".equals(theLocalPart)) { push(new AtomAuthorState(myEntry)); } else if ("content".equals(theLocalPart)) { - push(new PreResourceStateHapi(myEntry, myResourceType)); + push(new PreResourceStateHapi(myEntry, myResourceType).setRequireResourceType(false)); } else if ("summary".equals(theLocalPart)) { push(new XhtmlState(getPreResourceState(), myEntry.getSummary(), false)); } else if ("category".equals(theLocalPart)) { @@ -794,7 +794,6 @@ class ParserState { myPreResourceState = thePreResourceState; } - @SuppressWarnings("unused") public void attributeValue(String theName, String theValue) throws DataFormatException { myErrorHandler.unknownAttribute(null, theName); } @@ -803,7 +802,6 @@ class ParserState { // ignore by default } - @SuppressWarnings("unused") public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException { myErrorHandler.unknownElement(null, theLocalPart); } @@ -1053,7 +1051,7 @@ class ParserState { } else if ("score".equals(theLocalPart)) { push(new PrimitiveState(getPreResourceState(), myEntry.getScore())); } else if ("resource".equals(theLocalPart)) { - push(new PreResourceStateHapi(myEntry, myResourceType)); + push(new PreResourceStateHapi(myEntry, myResourceType).setRequireResourceType(false)); } else if ("deleted".equals(theLocalPart)) { push(new BundleEntryDeletedState(getPreResourceState(), myEntry)); } else { @@ -1987,6 +1985,12 @@ class ParserState { private IBaseResource myInstance; private FhirVersionEnum myParentVersion; private Class myResourceType; + private boolean myRequireResourceType = true; + + public ParserState.PreResourceState setRequireResourceType(boolean theRequireResourceType) { + myRequireResourceType = theRequireResourceType; + return this; + } public PreResourceState(Class theResourceType) { super(null); @@ -2020,6 +2024,9 @@ class ParserState { } else { definition = myContext.getResourceDefinition(myResourceType); if (!StringUtils.equals(theLocalPart, definition.getName())) { + if (myRequireResourceType) { + throw new DataFormatException(myContext.getLocalizer().getMessage(ParserState.class, "wrongResourceTypeFound", definition.getName(), theLocalPart)); + } definition = myContext.getResourceDefinition(theLocalPart); if (!(definition instanceof RuntimeResourceDefinition)) { throw new DataFormatException("Element '" + theLocalPart + "' is not a resource, expected a resource at this position"); @@ -2573,13 +2580,19 @@ class ParserState { return myDt; } + @Override + public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException { + // IGNORE - don't handle this as an error, we process these as XML events + } + @Override public void attributeValue(String theName, String theValue) throws DataFormatException { if (myJsonMode) { myDt.setValueAsString(theValue); return; + } else { + // IGNORE - don't handle this as an error, we process these as XML events } - super.attributeValue(theName, theValue); } protected void doPop() { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java index fa2ccb73232..51a975674cb 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java @@ -1144,7 +1144,7 @@ public class GenericClient extends BaseClient implements IGenericClient { BaseHttpClientInvocation invocation = OperationMethodBinding.createOperationInvocation(myContext, resourceName, id, myOperationName, myParameters, myUseHttpGet); IClientResponseHandler handler; - handler = new ResourceResponseHandler(myParameters.getClass(), null); + handler = new ResourceResponseHandler(null, null); Object retVal = invoke(null, handler, invocation); if (myContext.getResourceDefinition((IBaseResource) retVal).getName().equals("Parameters")) { diff --git a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties index f707b95c4ca..0b7677b150c 100644 --- a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties +++ b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties @@ -25,6 +25,8 @@ ca.uhn.fhir.rest.method.SearchMethodBinding.invalidSpecialParamName=Method [{0}] ca.uhn.fhir.rest.method.SearchMethodBinding.idWithoutCompartment=Method [{0}] in provider [{1}] has an @IdParam parameter. This is only allowable for compartment search (e.g. @Search(compartment="foo") ) ca.uhn.fhir.rest.method.SearchMethodBinding.idNullForCompartmentSearch=ID parameter can not be null or empty for compartment search +ca.uhn.fhir.parser.ParserState.wrongResourceTypeFound=Incorrect resource type found, expected "{0}" but found "{1}" + ca.uhn.fhir.rest.server.RestfulServer.getPagesNonHttpGet=Requests for _getpages must use HTTP GET ca.uhn.fhir.validation.FhirValidator.noPhlocWarningOnStartup=Phloc-schematron library not found on classpath, will not attempt to perform schematron validation diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java index f51b9d05e3e..8f68a2f1628 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java @@ -76,6 +76,7 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.client.IGenericClient; +import ca.uhn.fhir.rest.client.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.gclient.StringClientParam; import ca.uhn.fhir.rest.gclient.TokenClientParam; @@ -388,6 +389,7 @@ public class ResourceProviderDstu2Test { assertEquals(Patient.class, found.getEntries().get(0).getResource().getClass()); assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getSearchMode().getValueAsEnum()); assertEquals(BundleEntrySearchModeEnum.MATCH, found.getEntries().get(0).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE)); + assertThat(found.getEntries().get(0).getResource().getText().getDiv().getValueAsString(), containsString("hello"); + private void parseAndEncode(String name) throws IOException { + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream(name)); +// ourLog.info(msg); - Bundle b = new Bundle(); - b.getTotalResults().setValue(123); - b.addEntry().setResource(p); + IParser p = ourCtx.newJsonParser(); + Profile res = p.parseResource(Profile.class, msg); - String out = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); - ourLog.info(out); - assertThat(out, containsString("
hello
")); + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); +// ourLog.info(encoded); - p.getText().setDiv("hello"); - out = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); - ourLog.info(out); - // Backslashes need to be escaped because they are in a JSON value - assertThat(out, containsString("hello")); + JSON expected = JSONSerializer.toJSON(msg.trim()); + JSON actual = JSONSerializer.toJSON(encoded.trim()); + String exp = expected.toString().replace("\\r\\n", "\\n"); // .replace("§", "§"); + String act = actual.toString().replace("\\r\\n", "\\n"); + + ourLog.info("Expected: {}", exp); + ourLog.info("Actual : {}", act); + + assertEquals(exp, act); } - @Test - public void testEncodeOmitsVersionAndBase() { - Patient p = new Patient(); - p.getManagingOrganization().setReference("http://example.com/base/Patient/1/_history/2"); - - String enc; - - enc = ourCtx.newJsonParser().encodeResourceToString(p); - ourLog.info(enc); - assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); - - enc = ourCtx.newJsonParser().setServerBaseUrl("http://example.com/base").encodeResourceToString(p); - ourLog.info(enc); - assertThat(enc, containsString("\"Patient/1\"")); - - enc = ourCtx.newJsonParser().setServerBaseUrl("http://example.com/base2").encodeResourceToString(p); - ourLog.info(enc); - assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); - } - @Test public void testDecimalPrecisionPreserved() { String number = "52.3779939997090374535378485873776474764643249869328698436986235758587"; @@ -134,8 +113,6 @@ public class JsonParserTest { assertEquals(number, parsed.getPosition().getLatitude().getValueAsString()); } - - @Test public void testEncodeAndParseExtensions() throws Exception { @@ -248,163 +225,8 @@ public class JsonParserTest { assertEquals("CHILD", ((StringDt) given2ext2.getValue()).getValue()); } - - - - /** - * #65 - */ - @Test - public void testJsonPrimitiveWithExtensionEncoding() { - String res = "{\"resourceType\":\"Questionnaire\",\"status\":\"draft\",\"authored\":\"2014-10-30T14:15:00\",\"subject\":{\"reference\":\"http://www.hl7.org/fhir/Patient/1\"},\"author\":{\"reference\":\"http://www.hl7.org/fhir/Practitioner/1\"},\"name\":{\"text\":\"WDHB Friends and Family Test\"},\"group\":{\"header\":\"Note: This is an anonymous survey, which means you cannot be identified.\",\"_header\":[{\"extension\":[{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#language\",\"valueCode\":\"en\"},{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#string-translation\",\"valueString\":\"è«\\u008b注æ\\u0084\\u008fï¼\\u009aè¿\\u0099æ\\u0098¯ä¸\\u0080个å\\u008c¿å\\u0090\\u008dè°\\u0083æ\\u009f¥ï¼\\u008c被è°\\u0083æ\\u009f¥äººå°\\u0086ä¸\\u008dä¼\\u009a被è¯\\u0086å\\u0088«å\\u0087ºæ\\u009d¥ã\\u0080\\u0082\"},{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#string-translation\",\"valueString\":\"ì\\u009dµëª\\u0085ì\\u009c¼ë¡\\u009c í\\u0095\\u0098ë\\u008a\\u0094 ì\\u0084¤ë¬¸ì¡°ì\\u0082¬ì\\u009d´ë¯\\u0080ë¡\\u009c ì\\u009e\\u0091ì\\u0084±ì\\u009e\\u0090ê°\\u0080 ë\\u0088\\u0084구ì\\u009d¸ì§\\u0080 ë°\\u009dí\\u0098\\u0080ì§\\u0080ì§\\u0080 ì\\u0095\\u008aì\\u008aµë\\u008b\\u0088ë\\u008b¤.\"}]}],\"question\":[{\"extension\":[{\"url\":\"http://hl7.org/fhir/questionnaire-extensions#answerFormat\",\"valueCode\":\"single-choice\"}],\"text\":\"Are you a patient?\",\"options\":{\"reference\":\"#question1\"}}]}}"; - Questionnaire parsed = ourCtx.newJsonParser().parseResource(Questionnaire.class, res); - assertEquals("Note: This is an anonymous survey, which means you cannot be identified.", parsed.getGroup().getHeader().getValue()); - assertEquals(1, parsed.getGroup().getHeader().getUndeclaredExtensionsByUrl("http://hl7.org/fhir/Profile/iso-21090#language").size()); - - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed); - ourLog.info(encoded); - assertThat(encoded, containsString("\"_header\":{")); - - } - - - @Test - public void testEncodeNonContained() { - Organization org = new Organization(); - org.setId("Organization/65546"); - org.getName().setValue("Contained Test Organization"); - - Patient patient = new Patient(); - patient.setId("Patient/1333"); - patient.addIdentifier("urn:mrns", "253345"); - patient.getManagingOrganization().setResource(org); - - Bundle b = Bundle.withResources(Collections.singletonList((IResource)patient), ourCtx, "http://foo"); - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); - ourLog.info(encoded); - assertThat(encoded, not(containsString("contained"))); - assertThat(encoded, containsString("\"reference\":\"Organization/65546\"")); - - encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); - ourLog.info(encoded); - assertThat(encoded, not(containsString("contained"))); - assertThat(encoded, containsString("\"reference\":\"Organization/65546\"")); - } - @Test - public void testEncodeIds() { - Patient pt =new Patient(); - pt.addIdentifier("sys", "val"); - - ListResource list = new ListResource(); - list.setId("listId"); - list.addEntry().setItem(new ResourceReferenceDt(pt)); - - String enc = ourCtx.newJsonParser().encodeResourceToString(list); - ourLog.info(enc); - - assertThat(enc, containsString("\"id\":\"1\"")); - - ListResource parsed = ourCtx.newJsonParser().parseResource(ListResource.class,enc); - assertEquals(Patient.class, parsed.getEntryFirstRep().getItem().getResource().getClass()); - - enc = enc.replace("\"id\"", "\"_id\""); - parsed = ourCtx.newJsonParser().parseResource(ListResource.class,enc); - assertEquals(Patient.class, parsed.getEntryFirstRep().getItem().getResource().getClass()); -} - - @Test - public void testEncodingNullExtension() { - Patient p = new Patient(); - ExtensionDt extension = new ExtensionDt(false, "http://foo#bar"); - p.addUndeclaredExtension(extension); - String str = ourCtx.newJsonParser().encodeResourceToString(p); - - assertEquals("{\"resourceType\":\"Patient\"}", str); - - extension.setValue(new StringDt()); - - str = ourCtx.newJsonParser().encodeResourceToString(p); - assertEquals("{\"resourceType\":\"Patient\"}", str); - - extension.setValue(new StringDt("")); - - str = ourCtx.newJsonParser().encodeResourceToString(p); - assertEquals("{\"resourceType\":\"Patient\"}", str); - - } - - @Test - public void testParseSingleQuotes() { - try { - ourCtx.newJsonParser().parseBundle("{ 'resourceType': 'Bundle' }"); - fail(); - } catch (DataFormatException e) { - // Should be an error message about how single quotes aren't valid JSON - assertThat(e.getMessage(), containsString("double quote")); - } - } - - @Test - public void testEncodeExtensionInCompositeElement() { - - Conformance c = new Conformance(); - c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); - - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); - ourLog.info(encoded); - - encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); - ourLog.info(encoded); - assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"rest\":[{\"security\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}]}"); - - } - - @Test - public void testEncodeExtensionInPrimitiveElement() { - - Conformance c = new Conformance(); - c.getAcceptUnknown().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); - - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); - ourLog.info(encoded); - - encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); - ourLog.info(encoded); - assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); - - // Now with a value - ourLog.info("---------------"); - - c = new Conformance(); - c.getAcceptUnknown().setValue(true); - c.getAcceptUnknown().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); - - encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); - ourLog.info(encoded); - - encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); - ourLog.info(encoded); - assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"acceptUnknown\":true,\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); - - } - - @Test - public void testEncodeExtensionInResourceElement() { - - Conformance c = new Conformance(); - // c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); - c.addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); - - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); - ourLog.info(encoded); - - encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); - ourLog.info(encoded); - assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"); - - } @Test public void testEncodeBinaryResource() { @@ -418,185 +240,51 @@ public class JsonParserTest { } + + @Test - public void testParseEmptyNarrative() throws ConfigurationException, DataFormatException, IOException { - //@formatter:off - String text = "{\n" + - " \"resourceType\" : \"Patient\",\n" + - " \"extension\" : [\n" + - " {\n" + - " \"url\" : \"http://clairol.org/colour\",\n" + - " \"valueCode\" : \"B\"\n" + - " }\n" + - " ],\n" + - " \"text\" : {\n" + - " \"div\" : \"\"\n" + - " }" + - "}"; - //@formatter:on + public void testEncodeBundle() throws InterruptedException { + Bundle b = new Bundle(); - Patient res = (Patient) ourCtx.newJsonParser().parseResource(text); - XhtmlDt div = res.getText().getDiv(); - String value = div.getValueAsString(); + InstantDt pub = InstantDt.withCurrentTime(); + Thread.sleep(2); - assertEquals("", value); - assertEquals(null, div.getValue()); - } + Patient p1 = new Patient(); + p1.addName().addFamily("Family1"); + BundleEntry entry = b.addEntry(); + entry.getId().setValue("1"); + entry.setResource(p1); + entry.getSummary().setValueAsString("this is the summary"); - @Test - public void testNestedContainedResources() { + Patient p2 = new Patient(); + p2.addName().addFamily("Family2"); + entry = b.addEntry(); + entry.getId().setValue("2"); + entry.setLinkAlternate(new StringDt("http://foo/bar")); + entry.setResource(p2); - Observation A = new Observation(); - A.getName().setText("A"); + BundleEntry deletedEntry = b.addEntry(); + deletedEntry.setId(new IdDt("Patient/3")); + InstantDt nowDt = InstantDt.withCurrentTime(); + deletedEntry.setDeleted(nowDt); - Observation B = new Observation(); - B.getName().setText("B"); - A.addRelated().setTarget(new ResourceReferenceDt(B)); + String bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(bundleString); - Observation C = new Observation(); - C.getName().setText("C"); - B.addRelated().setTarget(new ResourceReferenceDt(C)); + List strings = new ArrayList(); + strings.addAll(Arrays.asList("\"id\":\"1\"")); + strings.addAll(Arrays.asList("this is the summary")); + strings.addAll(Arrays.asList("\"id\":\"2\"", "\"rel\":\"alternate\"", "\"href\":\"http://foo/bar\"")); + strings.addAll(Arrays.asList("\"deleted\":\"" + nowDt.getValueAsString() + "\"", "\"id\":\"Patient/3\"")); + assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings)); - String str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(A); - ourLog.info(str); - - assertThat(str, stringContainsInOrder(Arrays.asList("\"text\":\"B\"", "\"text\":\"C\"", "\"text\":\"A\""))); - - // Only one (outer) contained block - int idx0 = str.indexOf("\"contained\""); - int idx1 = str.indexOf("\"contained\"", idx0 + 1); - - assertNotEquals(-1, idx0); - assertEquals(-1, idx1); - - Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, str); - assertEquals("A", obs.getName().getText().getValue()); - - Observation obsB = (Observation) obs.getRelatedFirstRep().getTarget().getResource(); - assertEquals("B", obsB.getName().getText().getValue()); - - Observation obsC = (Observation) obsB.getRelatedFirstRep().getTarget().getResource(); - assertEquals("C", obsC.getName().getText().getValue()); - - } - - @Test - public void testParseQuery() { - String msg = "{\n" + " \"resourceType\": \"Query\",\n" + " \"text\": {\n" + " \"status\": \"generated\",\n" + " \"div\": \"
[Put rendering here]
\"\n" + " },\n" - + " \"identifier\": \"urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376\",\n" + " \"parameter\": [\n" + " {\n" + " \"url\": \"http://hl7.org/fhir/query#_query\",\n" - + " \"valueString\": \"example\"\n" + " }\n" + " ]\n" + "}"; - Query query = ourCtx.newJsonParser().parseResource(Query.class, msg); - - assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString()); - assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString()); - assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString()); - - } - - @Test - public void testEncodeQuery() { - Query q = new Query(); - ExtensionDt parameter = q.addParameter(); - parameter.setUrl("http://hl7.org/fhir/query#_query").setValue(new StringDt("example")); - - String val = new FhirContext().newJsonParser().encodeResourceToString(q); - ourLog.info(val); - - //@formatter:off - String expected = - "{" + - "\"resourceType\":\"Query\"," + - "\"parameter\":[" + - "{" + - "\"url\":\"http://hl7.org/fhir/query#_query\"," + - "\"valueString\":\"example\"" + - "}" + - "]" + - "}"; - //@formatter:on - - ourLog.info("Expect: {}", expected); - ourLog.info("Got : {}", val); - assertEquals(expected, val); - - } - - @Test - public void testParseBinaryResource() { - - Binary val = ourCtx.newJsonParser().parseResource(Binary.class, "{\"resourceType\":\"Binary\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}"); - assertEquals("foo", val.getContentType()); - assertArrayEquals(new byte[] { 1, 2, 3, 4 }, val.getContent()); - - } - - @Test - public void testTagList() { - - //@formatter:off - String tagListStr = "{\n" + - " \"resourceType\" : \"TagList\", " + - " \"category\" : [" + - " { " + - " \"term\" : \"term0\", " + - " \"label\" : \"label0\", " + - " \"scheme\" : \"scheme0\" " + - " }," + - " { " + - " \"term\" : \"term1\", " + - " \"label\" : \"label1\", " + - " \"scheme\" : null " + - " }," + - " { " + - " \"term\" : \"term2\", " + - " \"label\" : \"label2\" " + - " }" + - " ] " + - "}"; - //@formatter:on - - TagList tagList = new FhirContext().newJsonParser().parseTagList(tagListStr); - assertEquals(3, tagList.size()); - assertEquals("term0", tagList.get(0).getTerm()); - assertEquals("label0", tagList.get(0).getLabel()); - assertEquals("scheme0", tagList.get(0).getScheme()); - assertEquals("term1", tagList.get(1).getTerm()); - assertEquals("label1", tagList.get(1).getLabel()); - assertEquals(null, tagList.get(1).getScheme()); - assertEquals("term2", tagList.get(2).getTerm()); - assertEquals("label2", tagList.get(2).getLabel()); - assertEquals(null, tagList.get(2).getScheme()); - - /* - * Encode - */ - - //@formatter:off - String expected = "{" + - "\"resourceType\":\"TagList\"," + - "\"category\":[" + - "{" + - "\"term\":\"term0\"," + - "\"label\":\"label0\"," + - "\"scheme\":\"scheme0\"" + - "}," + - "{" + - "\"term\":\"term1\"," + - "\"label\":\"label1\"" + - "}," + - "{" + - "\"term\":\"term2\"," + - "\"label\":\"label2\"" + - "}" + - "]" + - "}"; - //@formatter:on - - String encoded = new FhirContext().newJsonParser().encodeTagListToString(tagList); - assertEquals(expected, encoded); + b.getEntries().remove(2); + bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + assertThat(bundleString, not(containsString("deleted"))); } + @Test public void testEncodeBundleCategory() { @@ -621,7 +309,7 @@ public class JsonParserTest { assertNull(b.getEntries().get(0).getResource()); } - + @Test public void testEncodeBundleEntryCategory() { @@ -645,58 +333,6 @@ public class JsonParserTest { assertNull(b.getEntries().get(0).getResource()); } - - @Test - public void testEncodeContained__() { - // Create an organization - Organization org = new Organization(); - org.getName().setValue("Contained Test Organization"); - - // Create a patient - Patient patient = new Patient(); - patient.setId("Patient/1333"); - patient.addIdentifier("urn:mrns", "253345"); - patient.getManagingOrganization().setResource(org); - - // Create a bundle with just the patient resource - List resources = new ArrayList(); - resources.add(patient); - Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base"); - - // Encode the buntdle - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); - ourLog.info(encoded); - assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\":\"Organization", "id\":\"1\""))); - assertThat(encoded, containsString("reference\":\"#1\"")); - - encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); - ourLog.info(encoded); - assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\":\"Organization", "id\":\"1\""))); - assertThat(encoded, containsString("reference\":\"#1\"")); - } - - @Test - public void testEncodeContainedWithNarrativeIsSuppresed() { - IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); - - // Create an organization, note that the organization does not have an ID - Organization org = new Organization(); - org.getName().setValue("Contained Test Organization"); - org.getText().setDiv("
FOOBAR
"); - - // Create a patient - Patient patient = new Patient(); - patient.setId("Patient/1333"); - patient.addIdentifier("urn:mrns", "253345"); - patient.getText().setDiv("
BARFOO
"); - patient.getManagingOrganization().setResource(org); - - String encoded = parser.encodeResourceToString(patient); - ourLog.info(encoded); - assertThat(encoded, not(containsString("FOOBAR"))); - assertThat(encoded, (containsString("BARFOO"))); - - } @Test public void testEncodeContained() { @@ -761,10 +397,36 @@ public class JsonParserTest { assertThat(encoded, not(stringContainsInOrder(Arrays.asList("\"contained\":", "[", "\"contained\":")))); } - - - + @Test + public void testEncodeContained__() { + // Create an organization + Organization org = new Organization(); + org.getName().setValue("Contained Test Organization"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + patient.getManagingOrganization().setResource(org); + + // Create a bundle with just the patient resource + List resources = new ArrayList(); + resources.add(patient); + Bundle b = Bundle.withResources(resources, ourCtx, "http://example.com/base"); + + // Encode the buntdle + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\":\"Organization", "id\":\"1\""))); + assertThat(encoded, containsString("reference\":\"#1\"")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, stringContainsInOrder(Arrays.asList("\"contained\"", "resourceType\":\"Organization", "id\":\"1\""))); + assertThat(encoded, containsString("reference\":\"#1\"")); + } + @Test public void testEncodeContainedResources() throws IOException { @@ -777,34 +439,7 @@ public class JsonParserTest { } - @Test - public void testParseJsonProfile() throws IOException { - parseAndEncode("/patient.profile.json"); - parseAndEncode("/alert.profile.json"); - } - - private void parseAndEncode(String name) throws IOException { - String msg = IOUtils.toString(XmlParser.class.getResourceAsStream(name)); -// ourLog.info(msg); - - IParser p = ourCtx.newJsonParser(); - Profile res = p.parseResource(Profile.class, msg); - - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(res); -// ourLog.info(encoded); - - JSON expected = JSONSerializer.toJSON(msg.trim()); - JSON actual = JSONSerializer.toJSON(encoded.trim()); - - String exp = expected.toString().replace("\\r\\n", "\\n"); // .replace("§", "§"); - String act = actual.toString().replace("\\r\\n", "\\n"); - - ourLog.info("Expected: {}", exp); - ourLog.info("Actual : {}", act); - - assertEquals(exp, act); - } - + @Test public void testEncodeContainedResourcesMore() { @@ -829,6 +464,29 @@ public class JsonParserTest { } + @Test + public void testEncodeContainedWithNarrativeIsSuppresed() { + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + + // Create an organization, note that the organization does not have an ID + Organization org = new Organization(); + org.getName().setValue("Contained Test Organization"); + org.getText().setDiv("
FOOBAR
"); + + // Create a patient + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + patient.getText().setDiv("
BARFOO
"); + patient.getManagingOrganization().setResource(org); + + String encoded = parser.encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString("FOOBAR"))); + assertThat(encoded, (containsString("BARFOO"))); + + } + @Test public void testEncodeDeclaredExtensionWithAddressContent() { IParser parser = new FhirContext().newJsonParser(); @@ -867,17 +525,6 @@ public class JsonParserTest { } - @Test - public void testEncodeExtensionOnEmptyElement() throws Exception { - - ValueSet valueSet = new ValueSet(); - valueSet.addTelecom().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); - - String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet); - assertThat(encoded, containsString("\"telecom\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}")); - - } - @Test public void testEncodeExt() throws Exception { @@ -900,6 +547,77 @@ public class JsonParserTest { } + @Test + public void testEncodeExtensionInCompositeElement() { + + Conformance c = new Conformance(); + c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"rest\":[{\"security\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}]}"); + + } + + @Test + public void testEncodeExtensionInPrimitiveElement() { + + Conformance c = new Conformance(); + c.getAcceptUnknown().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); + + // Now with a value + ourLog.info("---------------"); + + c = new Conformance(); + c.getAcceptUnknown().setValue(true); + c.getAcceptUnknown().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"acceptUnknown\":true,\"_acceptUnknown\":{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}}"); + + } + + @Test + public void testEncodeExtensionInResourceElement() { + + Conformance c = new Conformance(); + // c.addRest().getSecurity().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + c.addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(c); + ourLog.info(encoded); + + encoded = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(c); + ourLog.info(encoded); + assertEquals(encoded, "{\"resourceType\":\"Conformance\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}"); + + } + + @Test + public void testEncodeExtensionOnEmptyElement() throws Exception { + + ValueSet valueSet = new ValueSet(); + valueSet.addTelecom().addUndeclaredExtension(false, "http://foo", new StringDt("AAA")); + + String encoded = ourCtx.newJsonParser().encodeResourceToString(valueSet); + assertThat(encoded, containsString("\"telecom\":[{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"AAA\"}]}")); + + } + @Test public void testEncodeExtensionWithResourceContent() { IParser parser = new FhirContext().newJsonParser(); @@ -921,6 +639,29 @@ public class JsonParserTest { } + @Test + public void testEncodeIds() { + Patient pt =new Patient(); + pt.addIdentifier("sys", "val"); + + ListResource list = new ListResource(); + list.setId("listId"); + list.addEntry().setItem(new ResourceReferenceDt(pt)); + + String enc = ourCtx.newJsonParser().encodeResourceToString(list); + ourLog.info(enc); + + assertThat(enc, containsString("\"id\":\"1\"")); + + ListResource parsed = ourCtx.newJsonParser().parseResource(ListResource.class,enc); + assertEquals(Patient.class, parsed.getEntryFirstRep().getItem().getResource().getClass()); + + enc = enc.replace("\"id\"", "\"_id\""); + parsed = ourCtx.newJsonParser().parseResource(ListResource.class,enc); + assertEquals(Patient.class, parsed.getEntryFirstRep().getItem().getResource().getClass()); +} + + @Test public void testEncodeInvalidChildGoodException() { Observation obs = new Observation(); @@ -935,6 +676,103 @@ public class JsonParserTest { } } + @Test + public void testEncodeNarrativeBlockInBundle() { + Patient p = new Patient(); + p.addIdentifier("foo", "bar"); + p.getText().setStatus(NarrativeStatusEnum.GENERATED); + p.getText().setDiv("
hello
"); + + Bundle b = new Bundle(); + b.getTotalResults().setValue(123); + b.addEntry().setResource(p); + + String out = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(out); + assertThat(out, containsString("
hello
")); + + p.getText().setDiv("hello"); + out = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(out); + // Backslashes need to be escaped because they are in a JSON value + assertThat(out, containsString("hello")); + + } + + @Test + public void testEncodeNonContained() { + Organization org = new Organization(); + org.setId("Organization/65546"); + org.getName().setValue("Contained Test Organization"); + + Patient patient = new Patient(); + patient.setId("Patient/1333"); + patient.addIdentifier("urn:mrns", "253345"); + patient.getManagingOrganization().setResource(org); + + Bundle b = Bundle.withResources(Collections.singletonList((IResource)patient), ourCtx, "http://foo"); + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); + ourLog.info(encoded); + assertThat(encoded, not(containsString("contained"))); + assertThat(encoded, containsString("\"reference\":\"Organization/65546\"")); + + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(patient); + ourLog.info(encoded); + assertThat(encoded, not(containsString("contained"))); + assertThat(encoded, containsString("\"reference\":\"Organization/65546\"")); + } + + @Test + public void testEncodeOmitsVersionAndBase() { + Patient p = new Patient(); + p.getManagingOrganization().setReference("http://example.com/base/Patient/1/_history/2"); + + String enc; + + enc = ourCtx.newJsonParser().encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); + + enc = ourCtx.newJsonParser().setServerBaseUrl("http://example.com/base").encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"Patient/1\"")); + + enc = ourCtx.newJsonParser().setServerBaseUrl("http://example.com/base2").encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); + } + + + + + @Test + public void testEncodeQuery() { + Query q = new Query(); + ExtensionDt parameter = q.addParameter(); + parameter.setUrl("http://hl7.org/fhir/query#_query").setValue(new StringDt("example")); + + String val = new FhirContext().newJsonParser().encodeResourceToString(q); + ourLog.info(val); + + //@formatter:off + String expected = + "{" + + "\"resourceType\":\"Query\"," + + "\"parameter\":[" + + "{" + + "\"url\":\"http://hl7.org/fhir/query#_query\"," + + "\"valueString\":\"example\"" + + "}" + + "]" + + "}"; + //@formatter:on + + ourLog.info("Expect: {}", expected); + ourLog.info("Got : {}", val); + assertEquals(expected, val); + + } + @Test public void testEncodeResourceRef() throws DataFormatException { @@ -976,6 +814,27 @@ public class JsonParserTest { } + @Test + public void testEncodingNullExtension() { + Patient p = new Patient(); + ExtensionDt extension = new ExtensionDt(false, "http://foo#bar"); + p.addUndeclaredExtension(extension); + String str = ourCtx.newJsonParser().encodeResourceToString(p); + + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new StringDt()); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + extension.setValue(new StringDt("")); + + str = ourCtx.newJsonParser().encodeResourceToString(p); + assertEquals("{\"resourceType\":\"Patient\"}", str); + + } + @Test public void testExtensionOnComposite() throws Exception { @@ -1045,6 +904,22 @@ public class JsonParserTest { } + /** + * #65 + */ + @Test + public void testJsonPrimitiveWithExtensionEncoding() { + String res = "{\"resourceType\":\"Questionnaire\",\"status\":\"draft\",\"authored\":\"2014-10-30T14:15:00\",\"subject\":{\"reference\":\"http://www.hl7.org/fhir/Patient/1\"},\"author\":{\"reference\":\"http://www.hl7.org/fhir/Practitioner/1\"},\"name\":{\"text\":\"WDHB Friends and Family Test\"},\"group\":{\"header\":\"Note: This is an anonymous survey, which means you cannot be identified.\",\"_header\":[{\"extension\":[{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#language\",\"valueCode\":\"en\"},{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#string-translation\",\"valueString\":\"è«\\u008b注æ\\u0084\\u008fï¼\\u009aè¿\\u0099æ\\u0098¯ä¸\\u0080个å\\u008c¿å\\u0090\\u008dè°\\u0083æ\\u009f¥ï¼\\u008c被è°\\u0083æ\\u009f¥äººå°\\u0086ä¸\\u008dä¼\\u009a被è¯\\u0086å\\u0088«å\\u0087ºæ\\u009d¥ã\\u0080\\u0082\"},{\"url\":\"http://hl7.org/fhir/Profile/iso-21090#string-translation\",\"valueString\":\"ì\\u009dµëª\\u0085ì\\u009c¼ë¡\\u009c í\\u0095\\u0098ë\\u008a\\u0094 ì\\u0084¤ë¬¸ì¡°ì\\u0082¬ì\\u009d´ë¯\\u0080ë¡\\u009c ì\\u009e\\u0091ì\\u0084±ì\\u009e\\u0090ê°\\u0080 ë\\u0088\\u0084구ì\\u009d¸ì§\\u0080 ë°\\u009dí\\u0098\\u0080ì§\\u0080ì§\\u0080 ì\\u0095\\u008aì\\u008aµë\\u008b\\u0088ë\\u008b¤.\"}]}],\"question\":[{\"extension\":[{\"url\":\"http://hl7.org/fhir/questionnaire-extensions#answerFormat\",\"valueCode\":\"single-choice\"}],\"text\":\"Are you a patient?\",\"options\":{\"reference\":\"#question1\"}}]}}"; + Questionnaire parsed = ourCtx.newJsonParser().parseResource(Questionnaire.class, res); + assertEquals("Note: This is an anonymous survey, which means you cannot be identified.", parsed.getGroup().getHeader().getValue()); + assertEquals(1, parsed.getGroup().getHeader().getUndeclaredExtensionsByUrl("http://hl7.org/fhir/Profile/iso-21090#language").size()); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed); + ourLog.info(encoded); + assertThat(encoded, containsString("\"_header\":{")); + + } + @Test public void testNarrativeGeneration() throws DataFormatException, IOException { @@ -1056,14 +931,14 @@ public class JsonParserTest { INarrativeGenerator gen = new INarrativeGenerator() { @Override - public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt theNarrative) throws DataFormatException { - theNarrative.getDiv().setValueAsString("
help
"); - theNarrative.getStatus().setValueAsString("generated"); + public void generateNarrative(IBaseResource theResource, BaseNarrativeDt theNarrative) { + throw new UnsupportedOperationException(); } @Override - public void generateNarrative(IBaseResource theResource, BaseNarrativeDt theNarrative) { - throw new UnsupportedOperationException(); + public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt theNarrative) throws DataFormatException { + theNarrative.getDiv().setValueAsString("
help
"); + theNarrative.getStatus().setValueAsString("generated"); } @Override @@ -1092,6 +967,52 @@ public class JsonParserTest { assertThat(str, StringContains.containsString(",\"text\":{\"status\":\"generated\",\"div\":\"
help
\"},")); } + @Test + public void testNestedContainedResources() { + + Observation A = new Observation(); + A.getName().setText("A"); + + Observation B = new Observation(); + B.getName().setText("B"); + A.addRelated().setTarget(new ResourceReferenceDt(B)); + + Observation C = new Observation(); + C.getName().setText("C"); + B.addRelated().setTarget(new ResourceReferenceDt(C)); + + String str = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(A); + ourLog.info(str); + + assertThat(str, stringContainsInOrder(Arrays.asList("\"text\":\"B\"", "\"text\":\"C\"", "\"text\":\"A\""))); + + // Only one (outer) contained block + int idx0 = str.indexOf("\"contained\""); + int idx1 = str.indexOf("\"contained\"", idx0 + 1); + + assertNotEquals(-1, idx0); + assertEquals(-1, idx1); + + Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, str); + assertEquals("A", obs.getName().getText().getValue()); + + Observation obsB = (Observation) obs.getRelatedFirstRep().getTarget().getResource(); + assertEquals("B", obsB.getName().getText().getValue()); + + Observation obsC = (Observation) obsB.getRelatedFirstRep().getTarget().getResource(); + assertEquals("C", obsC.getName().getText().getValue()); + + } + + @Test + public void testParseBinaryResource() { + + Binary val = ourCtx.newJsonParser().parseResource(Binary.class, "{\"resourceType\":\"Binary\",\"contentType\":\"foo\",\"content\":\"AQIDBA==\"}"); + assertEquals("foo", val.getContentType()); + assertArrayEquals(new byte[] { 1, 2, 3, 4 }, val.getContent()); + + } + @Test public void testParseBundle() throws DataFormatException, IOException { @@ -1123,61 +1044,6 @@ public class JsonParserTest { } - @Test - public void testParseBundleFromHI() throws DataFormatException, IOException { - - String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/bundle.json")); - IParser p = ourCtx.newJsonParser(); - Bundle bundle = p.parseBundle(msg); - - String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle); - ourLog.info(encoded); - - BundleEntry entry = bundle.getEntries().get(0); - - Patient res = (Patient) entry.getResource(); - assertEquals("444111234", res.getIdentifierFirstRep().getValue().getValue()); - - BundleEntry deletedEntry = bundle.getEntries().get(3); - assertEquals("2014-06-20T20:15:49Z", deletedEntry.getDeletedAt().getValueAsString()); - - } - - /** - * This sample has extra elements in that are not actually a part of the spec any more.. - */ - @Test - public void testParseFuroreMetadataWithExtraElements() throws IOException { - String msg = IOUtils.toString(JsonParserTest.class.getResourceAsStream("/furore-conformance.json")); - - IParser p = ourCtx.newJsonParser(); - Conformance conf = p.parseResource(Conformance.class, msg); - RestResource res = conf.getRestFirstRep().getResourceFirstRep(); - assertEquals("_id", res.getSearchParam().get(1).getName().getValue()); - } - - @Test - public void testParseWithContained() throws DataFormatException, IOException { - - String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/diagnostic-report.json")); - IParser p = ourCtx.newJsonParser(); - // ourLog.info("Reading in message: {}", msg); - DiagnosticReport res = p.parseResource(DiagnosticReport.class, msg); - - String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); - ourLog.info(encoded); - - ResourceReferenceDt reference = res.getResult().get(1); - Observation obs = (Observation) reference.getResource(); - - assertEquals("789-8", obs.getName().getCoding().get(0).getCode().getValue()); - } - - @BeforeClass - public static void beforeClass() { - ourCtx = new FhirContext(); - } - @Test public void testParseBundleDeletedEntry() { @@ -1218,45 +1084,132 @@ public class JsonParserTest { } @Test - public void testEncodeBundle() throws InterruptedException { - Bundle b = new Bundle(); + public void testParseBundleFromHI() throws DataFormatException, IOException { - InstantDt pub = InstantDt.withCurrentTime(); - Thread.sleep(2); + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/bundle.json")); + IParser p = ourCtx.newJsonParser(); + Bundle bundle = p.parseBundle(msg); - Patient p1 = new Patient(); - p1.addName().addFamily("Family1"); - BundleEntry entry = b.addEntry(); - entry.getId().setValue("1"); - entry.setResource(p1); - entry.getSummary().setValueAsString("this is the summary"); + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle); + ourLog.info(encoded); - Patient p2 = new Patient(); - p2.addName().addFamily("Family2"); - entry = b.addEntry(); - entry.getId().setValue("2"); - entry.setLinkAlternate(new StringDt("http://foo/bar")); - entry.setResource(p2); + BundleEntry entry = bundle.getEntries().get(0); - BundleEntry deletedEntry = b.addEntry(); - deletedEntry.setId(new IdDt("Patient/3")); - InstantDt nowDt = InstantDt.withCurrentTime(); - deletedEntry.setDeleted(nowDt); + Patient res = (Patient) entry.getResource(); + assertEquals("444111234", res.getIdentifierFirstRep().getValue().getValue()); - String bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); - ourLog.info(bundleString); + BundleEntry deletedEntry = bundle.getEntries().get(3); + assertEquals("2014-06-20T20:15:49Z", deletedEntry.getDeletedAt().getValueAsString()); - List strings = new ArrayList(); - strings.addAll(Arrays.asList("\"id\":\"1\"")); - strings.addAll(Arrays.asList("this is the summary")); - strings.addAll(Arrays.asList("\"id\":\"2\"", "\"rel\":\"alternate\"", "\"href\":\"http://foo/bar\"")); - strings.addAll(Arrays.asList("\"deleted\":\"" + nowDt.getValueAsString() + "\"", "\"id\":\"Patient/3\"")); - assertThat(bundleString, StringContainsInOrder.stringContainsInOrder(strings)); + } - b.getEntries().remove(2); - bundleString = ourCtx.newJsonParser().setPrettyPrint(true).encodeBundleToString(b); - assertThat(bundleString, not(containsString("deleted"))); + @Test + public void testParseEmptyNarrative() throws ConfigurationException, DataFormatException, IOException { + //@formatter:off + String text = "{\n" + + " \"resourceType\" : \"Patient\",\n" + + " \"extension\" : [\n" + + " {\n" + + " \"url\" : \"http://clairol.org/colour\",\n" + + " \"valueCode\" : \"B\"\n" + + " }\n" + + " ],\n" + + " \"text\" : {\n" + + " \"div\" : \"\"\n" + + " }" + + "}"; + //@formatter:on + Patient res = (Patient) ourCtx.newJsonParser().parseResource(text); + XhtmlDt div = res.getText().getDiv(); + String value = div.getValueAsString(); + + assertEquals("", value); + assertEquals(null, div.getValue()); + } + + /** + * This sample has extra elements in that are not actually a part of the spec any more.. + */ + @Test + public void testParseFuroreMetadataWithExtraElements() throws IOException { + String msg = IOUtils.toString(JsonParserTest.class.getResourceAsStream("/furore-conformance.json")); + + IParser p = ourCtx.newJsonParser(); + Conformance conf = p.parseResource(Conformance.class, msg); + RestResource res = conf.getRestFirstRep().getResourceFirstRep(); + assertEquals("_id", res.getSearchParam().get(1).getName().getValue()); + } + + @Test + public void testParseJsonProfile() throws IOException { + parseAndEncode("/patient.profile.json"); + parseAndEncode("/alert.profile.json"); + } + + @Test + public void testParseQuery() { + String msg = "{\n" + " \"resourceType\": \"Query\",\n" + " \"text\": {\n" + " \"status\": \"generated\",\n" + " \"div\": \"
[Put rendering here]
\"\n" + " },\n" + + " \"identifier\": \"urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376\",\n" + " \"parameter\": [\n" + " {\n" + " \"url\": \"http://hl7.org/fhir/query#_query\",\n" + + " \"valueString\": \"example\"\n" + " }\n" + " ]\n" + "}"; + Query query = ourCtx.newJsonParser().parseResource(Query.class, msg); + + assertEquals("urn:uuid:42b253f5-fa17-40d0-8da5-44aeb4230376", query.getIdentifier().getValueAsString()); + assertEquals("http://hl7.org/fhir/query#_query", query.getParameterFirstRep().getUrlAsString()); + assertEquals("example", query.getParameterFirstRep().getValueAsPrimitive().getValueAsString()); + + } + + @Test + public void testParseSingleQuotes() { + try { + ourCtx.newJsonParser().parseBundle("{ 'resourceType': 'Bundle' }"); + fail(); + } catch (DataFormatException e) { + // Should be an error message about how single quotes aren't valid JSON + assertThat(e.getMessage(), containsString("double quote")); + } + } + + @Test + public void testParseWithContained() throws DataFormatException, IOException { + + String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/diagnostic-report.json")); + IParser p = ourCtx.newJsonParser(); + // ourLog.info("Reading in message: {}", msg); + DiagnosticReport res = p.parseResource(DiagnosticReport.class, msg); + + String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res); + ourLog.info(encoded); + + ResourceReferenceDt reference = res.getResult().get(1); + Observation obs = (Observation) reference.getResource(); + + assertEquals("789-8", obs.getName().getCoding().get(0).getCode().getValue()); + } + + /** + * HAPI FHIR < 0.6 incorrectly used "resource" instead of "reference" + */ + @Test + public void testParseWithIncorrectReference() throws IOException { + String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.json")); + jsonString = jsonString.replace("\"reference\"", "\"resource\""); + Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, jsonString); + assertEquals("Organization/1", parsed.getManagingOrganization().getReference().getValue()); + } + + @SuppressWarnings("unused") + @Test + public void testParseWithIncorrectResourceType() { + String input = "{\"resourceType\":\"Patient\"}"; + try { + IParser parser = ourCtx.newJsonParser(); + Organization o = parser.parseResource(Organization.class, input); + fail(); + } catch (DataFormatException e) { + assertThat(e.getMessage(), containsString("expected \"Organization\" but found \"Patient\"")); + } } @Test @@ -1317,17 +1270,6 @@ public class JsonParserTest { } - /** - * HAPI FHIR < 0.6 incorrectly used "resource" instead of "reference" - */ - @Test - public void testParseWithIncorrectReference() throws IOException { - String jsonString = IOUtils.toString(JsonParser.class.getResourceAsStream("/example-patient-general.json")); - jsonString = jsonString.replace("\"reference\"", "\"resource\""); - Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, jsonString); - assertEquals("Organization/1", parsed.getManagingOrganization().getReference().getValue()); - } - @Test public void testSimpleResourceEncodeWithCustomType() throws IOException { @@ -1363,6 +1305,78 @@ public class JsonParserTest { } + @Test + public void testTagList() { + + //@formatter:off + String tagListStr = "{\n" + + " \"resourceType\" : \"TagList\", " + + " \"category\" : [" + + " { " + + " \"term\" : \"term0\", " + + " \"label\" : \"label0\", " + + " \"scheme\" : \"scheme0\" " + + " }," + + " { " + + " \"term\" : \"term1\", " + + " \"label\" : \"label1\", " + + " \"scheme\" : null " + + " }," + + " { " + + " \"term\" : \"term2\", " + + " \"label\" : \"label2\" " + + " }" + + " ] " + + "}"; + //@formatter:on + + TagList tagList = new FhirContext().newJsonParser().parseTagList(tagListStr); + assertEquals(3, tagList.size()); + assertEquals("term0", tagList.get(0).getTerm()); + assertEquals("label0", tagList.get(0).getLabel()); + assertEquals("scheme0", tagList.get(0).getScheme()); + assertEquals("term1", tagList.get(1).getTerm()); + assertEquals("label1", tagList.get(1).getLabel()); + assertEquals(null, tagList.get(1).getScheme()); + assertEquals("term2", tagList.get(2).getTerm()); + assertEquals("label2", tagList.get(2).getLabel()); + assertEquals(null, tagList.get(2).getScheme()); + + /* + * Encode + */ + + //@formatter:off + String expected = "{" + + "\"resourceType\":\"TagList\"," + + "\"category\":[" + + "{" + + "\"term\":\"term0\"," + + "\"label\":\"label0\"," + + "\"scheme\":\"scheme0\"" + + "}," + + "{" + + "\"term\":\"term1\"," + + "\"label\":\"label1\"" + + "}," + + "{" + + "\"term\":\"term2\"," + + "\"label\":\"label2\"" + + "}" + + "]" + + "}"; + //@formatter:on + + String encoded = new FhirContext().newJsonParser().encodeTagListToString(tagList); + assertEquals(expected, encoded); + + } + + @BeforeClass + public static void beforeClass() { + ourCtx = new FhirContext(); + } + @ResourceDef(name = "Patient") public static class MyPatientWithOneDeclaredAddressExtension extends Patient { diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java index 8cd975c631a..47d1060ebcc 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java @@ -75,77 +75,6 @@ public class XmlParserTest { private static FhirContext ourCtx; private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserTest.class); - - @Test - public void testParseErrorHandlerNoError() { - String input = ""; - ourCtx.newXmlParser().setParserErrorHandler(new StrictErrorHandler()).parseResource(Patient.class, input); - } - - @Test - public void testParseErrorHandlerUnexpectedElement() { - String input = ""; - try { - ourCtx.newXmlParser().setParserErrorHandler(new StrictErrorHandler()).parseResource(Patient.class, input); - fail(); - } catch (DataFormatException e) { - assertThat(e.getMessage(), containsString("'foo'")); - } - - Patient p = ourCtx.newXmlParser().setParserErrorHandler(new LenientErrorHandler()).parseResource(Patient.class, input); - assertEquals(p.getName().get(0).getFamily().get(0).getValue(), "AAA"); - } - - @Test - public void testParseErrorHandlerUnexpectedAttribute() { - String input = ""; - try { - ourCtx.newXmlParser().setParserErrorHandler(new StrictErrorHandler()).parseResource(Patient.class, input); - fail(); - } catch (DataFormatException e) { - assertThat(e.getMessage(), containsString("'foo'")); - } - - Patient p = ourCtx.newXmlParser().setParserErrorHandler(new LenientErrorHandler()).parseResource(Patient.class, input); - assertEquals(p.getName().get(0).getFamily().get(0).getValue(), "AAA"); - } - - /** - * see #144 and #146 - */ - @Test - public void testParseContained() { - - FhirContext c = FhirContext.forDstu1(); - IParser parser = c.newXmlParser().setPrettyPrint(true); - - Observation o = new Observation(); - o.getName().setText("obs text"); - - Patient p = new Patient(); - p.addName().addFamily("patient family"); - o.getSubject().setResource(p); - - String enc = parser.encodeResourceToString(o); - ourLog.info(enc); - - //@formatter:off - assertThat(enc, stringContainsInOrder( - "", - "", - "", - "", - "" - )); - //@formatter:on - - o = parser.parseResource(Observation.class, enc); - assertEquals("obs text", o.getName().getText().getValue()); - - assertNotNull(o.getSubject().getResource()); - p = (Patient) o.getSubject().getResource(); - assertEquals("patient family", p.getNameFirstRep().getFamilyAsSingleString()); - } @Test public void testComposition() { @@ -163,39 +92,76 @@ public class XmlParserTest { } /** - * See #131 + * Test for #82 - Not yet enabled because the test won't pass + */ + // @Test + public void testCustomTypeInExtension() throws DataFormatException { + + MyPatient patient = new MyPatient(); + patient.addName().addFamily("PatientName"); + + MyOrganization org = new MyOrganization(); + org.setName("OrgName"); + patient.getSomeOrganization().setResource(org); + + String str = ourCtx.newXmlParser().encodeResourceToString(patient); + ourLog.info(str); + + assertThat( + str, + Matchers.stringContainsInOrder("")); + + MyPatient parse = ourCtx.newXmlParser().parseResource(MyPatient.class, str); + assertEquals("PatientName", parse.getNameFirstRep().getFamilyAsSingleString()); + assertEquals("OrgName", ((MyOrganization) parse.getSomeOrganization().getResource()).getName().getValue()); + } + + /** + * Test for #82 - Not yet enabled because the test won't pass + */ + // @Test + public void testCustomTypeInReplaceParent() throws DataFormatException { + + MyPatient patient = new MyPatient(); + patient.addName().addFamily("PatientName"); + + MyOrganization org = new MyOrganization(); + org.setName("OrgName"); + patient.getManagingOrganization().setResource(org); + + String str = ourCtx.newXmlParser().encodeResourceToString(patient); + ourLog.info(str); + + assertThat( + str, + Matchers.stringContainsInOrder("")); + + MyPatient parse = ourCtx.newXmlParser().parseResource(MyPatient.class, str); + assertEquals("PatientName", parse.getNameFirstRep().getFamilyAsSingleString()); + assertEquals("OrgName", ((MyOrganization) parse.getManagingOrganization().getResource()).getName().getValue()); + } + + /** + * See #91 */ @Test - public void testParseAndReencodeCondition() { - FhirContext ctx = FhirContext.forDstu1(); - ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator()); - InputStreamReader reader = new InputStreamReader(XmlParserTest.class.getResourceAsStream("/condition.xml")); - Condition cond = ctx.newXmlParser().parseResource(Condition.class, reader); - - String enc = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(cond); - ourLog.info(enc); - - assertThat(enc, not(containsString("generated"))); - } - - @Test - public void testEncodeOmitsVersionAndBase() { - Patient p = new Patient(); - p.getManagingOrganization().setReference("http://example.com/base/Patient/1/_history/2"); - - String enc; - - enc = ourCtx.newXmlParser().encodeResourceToString(p); - ourLog.info(enc); - assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); - - enc = ourCtx.newXmlParser().setServerBaseUrl("http://example.com/base").encodeResourceToString(p); - ourLog.info(enc); - assertThat(enc, containsString("\"Patient/1\"")); + public void testCustomTypeWithUnoderedExtensions() { + MyPatientWithUnorderedExtensions pat = new MyPatientWithUnorderedExtensions(); + pat.getExtAtt1().setValue(true); + pat.getExtAtt2().setValue("val2"); + pat.getExtAtt3().setValueAsString("20110102"); + + String string = ourCtx.newXmlParser().encodeResourceToString(pat); + ourLog.info(string); + + //@formatter:off + assertThat(string, stringContainsInOrder(Arrays.asList( + "", + "", + "" + ))); + //@formatter:on - enc = ourCtx.newXmlParser().setServerBaseUrl("http://example.com/base2").encodeResourceToString(p); - ourLog.info(enc); - assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); } @Test @@ -217,43 +183,6 @@ public class XmlParserTest { } - @Test - public void testEncodeBinaryResource() { - - Binary patient = new Binary(); - patient.setContentType("foo"); - patient.setContent(new byte[] { 1, 2, 3, 4 }); - - String val = ourCtx.newXmlParser().encodeResourceToString(patient); - assertEquals("AQIDBA==", val); - - } - - @Test - public void testEncodeBinaryWithNoContentType() { - Binary b = new Binary(); - b.setContent(new byte[] { 1, 2, 3, 4 }); - - String output = ourCtx.newXmlParser().encodeResourceToString(b); - ourLog.info(output); - - assertEquals("AQIDBA==", output); - } - - @Test - public void testEncodeBoundCode() { - - Patient patient = new Patient(); - patient.addAddress().setUse(AddressUseEnum.HOME); - - patient.getGender().setValueAsEnum(AdministrativeGenderCodesEnum.M); - - String val = ourCtx.newXmlParser().encodeResourceToString(patient); - ourLog.info(val); - - } - - @Test public void testEncodeAndParseExtensions() throws Exception { @@ -301,8 +230,10 @@ public class XmlParserTest { enc, containsString("")); assertThat(enc, containsString("")); - assertThat(enc, containsString("")); - + assertThat( + enc, + containsString("")); + /* * Now parse this back */ @@ -341,6 +272,91 @@ public class XmlParserTest { } + /** + * See #103 + */ + @Test + public void testEncodeAndReEncodeContainedJson() { + Composition comp = new Composition(); + comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); + comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); + comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); + + 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().getContainedResources().size()); + } + + /** + * See #103 + */ + @Test + public void testEncodeAndReEncodeContainedXml() { + Composition comp = new Composition(); + comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); + comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); + comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); + + 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().getContainedResources().size()); + } + + @Test + public void testEncodeBinaryResource() { + + Binary patient = new Binary(); + patient.setContentType("foo"); + patient.setContent(new byte[] { 1, 2, 3, 4 }); + + String val = ourCtx.newXmlParser().encodeResourceToString(patient); + assertEquals("AQIDBA==", val); + + } + + @Test + public void testEncodeBinaryWithNoContentType() { + Binary b = new Binary(); + b.setContent(new byte[] { 1, 2, 3, 4 }); + + String output = ourCtx.newXmlParser().encodeResourceToString(b); + ourLog.info(output); + + assertEquals("AQIDBA==", output); + } + + @Test + public void testEncodeBoundCode() { + + Patient patient = new Patient(); + patient.addAddress().setUse(AddressUseEnum.HOME); + + patient.getGender().setValueAsEnum(AdministrativeGenderCodesEnum.M); + + String val = ourCtx.newXmlParser().encodeResourceToString(patient); + ourLog.info(val); + + } @Test public void testEncodeBundle() throws InterruptedException { @@ -761,6 +777,26 @@ public class XmlParserTest { } + @Test + public void testEncodeOmitsVersionAndBase() { + Patient p = new Patient(); + p.getManagingOrganization().setReference("http://example.com/base/Patient/1/_history/2"); + + String enc; + + enc = ourCtx.newXmlParser().encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); + + enc = ourCtx.newXmlParser().setServerBaseUrl("http://example.com/base").encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"Patient/1\"")); + + enc = ourCtx.newXmlParser().setServerBaseUrl("http://example.com/base2").encodeResourceToString(p); + ourLog.info(enc); + assertThat(enc, containsString("\"http://example.com/base/Patient/1\"")); + } + @Test public void testEncodePrettyPrint() throws DataFormatException { @@ -940,56 +976,6 @@ public class XmlParserTest { } - /** - * Test for #82 - Not yet enabled because the test won't pass - */ - // @Test - public void testCustomTypeInReplaceParent() throws DataFormatException { - - MyPatient patient = new MyPatient(); - patient.addName().addFamily("PatientName"); - - MyOrganization org = new MyOrganization(); - org.setName("OrgName"); - patient.getManagingOrganization().setResource(org); - - String str = ourCtx.newXmlParser().encodeResourceToString(patient); - ourLog.info(str); - - assertThat( - str, - Matchers.stringContainsInOrder("")); - - MyPatient parse = ourCtx.newXmlParser().parseResource(MyPatient.class, str); - assertEquals("PatientName", parse.getNameFirstRep().getFamilyAsSingleString()); - assertEquals("OrgName", ((MyOrganization) parse.getManagingOrganization().getResource()).getName().getValue()); - } - - /** - * Test for #82 - Not yet enabled because the test won't pass - */ - // @Test - public void testCustomTypeInExtension() throws DataFormatException { - - MyPatient patient = new MyPatient(); - patient.addName().addFamily("PatientName"); - - MyOrganization org = new MyOrganization(); - org.setName("OrgName"); - patient.getSomeOrganization().setResource(org); - - String str = ourCtx.newXmlParser().encodeResourceToString(patient); - ourLog.info(str); - - assertThat( - str, - Matchers.stringContainsInOrder("")); - - MyPatient parse = ourCtx.newXmlParser().parseResource(MyPatient.class, str); - assertEquals("PatientName", parse.getNameFirstRep().getFamilyAsSingleString()); - assertEquals("OrgName", ((MyOrganization) parse.getSomeOrganization().getResource()).getName().getValue()); - } - @Test public void testLoadAndAncodeMessage() throws SAXException, IOException { @@ -1246,14 +1232,14 @@ public class XmlParserTest { INarrativeGenerator gen = new INarrativeGenerator() { @Override - public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt theNarrative) throws DataFormatException { - theNarrative.getDiv().setValueAsString("
help
"); - theNarrative.getStatus().setValueAsString("generated"); + public void generateNarrative(IBaseResource theResource, BaseNarrativeDt theNarrative) { + throw new UnsupportedOperationException(); } @Override - public void generateNarrative(IBaseResource theResource, BaseNarrativeDt theNarrative) { - throw new UnsupportedOperationException(); + public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt theNarrative) throws DataFormatException { + theNarrative.getDiv().setValueAsString("
help
"); + theNarrative.getStatus().setValueAsString("generated"); } @Override @@ -1325,6 +1311,22 @@ public class XmlParserTest { } + /** + * See #131 + */ + @Test + public void testParseAndReencodeCondition() { + FhirContext ctx = FhirContext.forDstu1(); + ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator()); + InputStreamReader reader = new InputStreamReader(XmlParserTest.class.getResourceAsStream("/condition.xml")); + Condition cond = ctx.newXmlParser().parseResource(Condition.class, reader); + + String enc = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(cond); + ourLog.info(enc); + + assertThat(enc, not(containsString("generated"))); + } + @Test public void testParseBinaryResource() { @@ -1515,6 +1517,43 @@ public class XmlParserTest { assertEquals(Organization.class, b.getEntries().get(2).getResource().getClass()); } + /** + * see #144 and #146 + */ + @Test + public void testParseContained() { + + FhirContext c = FhirContext.forDstu1(); + IParser parser = c.newXmlParser().setPrettyPrint(true); + + Observation o = new Observation(); + o.getName().setText("obs text"); + + Patient p = new Patient(); + p.addName().addFamily("patient family"); + o.getSubject().setResource(p); + + String enc = parser.encodeResourceToString(o); + ourLog.info(enc); + + //@formatter:off + assertThat(enc, stringContainsInOrder( + "", + "", + "", + "", + "" + )); + //@formatter:on + + o = parser.parseResource(Observation.class, enc); + assertEquals("obs text", o.getName().getText().getValue()); + + assertNotNull(o.getSubject().getResource()); + p = (Patient) o.getSubject().getResource(); + assertEquals("patient family", p.getNameFirstRep().getFamilyAsSingleString()); + } + /** * Thanks to Alexander Kley! */ @@ -1597,6 +1636,40 @@ public class XmlParserTest { } + @Test + public void testParseErrorHandlerNoError() { + String input = ""; + ourCtx.newXmlParser().setParserErrorHandler(new StrictErrorHandler()).parseResource(Patient.class, input); + } + + @Test + public void testParseErrorHandlerUnexpectedAttribute() { + String input = ""; + try { + ourCtx.newXmlParser().setParserErrorHandler(new StrictErrorHandler()).parseResource(Patient.class, input); + fail(); + } catch (DataFormatException e) { + assertThat(e.getMessage(), containsString("'foo'")); + } + + Patient p = ourCtx.newXmlParser().setParserErrorHandler(new LenientErrorHandler()).parseResource(Patient.class, input); + assertEquals(p.getName().get(0).getFamily().get(0).getValue(), "AAA"); + } + + @Test + public void testParseErrorHandlerUnexpectedElement() { + String input = ""; + try { + ourCtx.newXmlParser().setParserErrorHandler(new StrictErrorHandler()).parseResource(Patient.class, input); + fail(); + } catch (DataFormatException e) { + assertThat(e.getMessage(), containsString("'foo'")); + } + + Patient p = ourCtx.newXmlParser().setParserErrorHandler(new LenientErrorHandler()).parseResource(Patient.class, input); + assertEquals(p.getName().get(0).getFamily().get(0).getValue(), "AAA"); + } + @Test public void testParseFeedWithListResource() throws ConfigurationException, DataFormatException, IOException { @@ -1646,6 +1719,17 @@ public class XmlParserTest { } + @Test + public void testParseWithIncorrectResourceType() { + String input = ""; + try { + ourCtx.newXmlParser().parseResource(Organization.class, input); + fail(); + } catch (DataFormatException e) { + assertThat(e.getMessage(), containsString("expected \"Organization\" but found \"Patient\"")); + } + } + @Test public void testParseWithXmlHeader() throws ConfigurationException, DataFormatException { IParser p = ourCtx.newXmlParser(); @@ -1695,29 +1779,6 @@ public class XmlParserTest { } - /** - * See #91 - */ - @Test - public void testCustomTypeWithUnoderedExtensions() { - MyPatientWithUnorderedExtensions pat = new MyPatientWithUnorderedExtensions(); - pat.getExtAtt1().setValue(true); - pat.getExtAtt2().setValue("val2"); - pat.getExtAtt3().setValueAsString("20110102"); - - String string = ourCtx.newXmlParser().encodeResourceToString(pat); - ourLog.info(string); - - //@formatter:off - assertThat(string, stringContainsInOrder(Arrays.asList( - "", - "", - "" - ))); - //@formatter:on - - } - @Test public void testSimpleResourceEncodeWithCustomType() throws IOException, SAXException { @@ -1816,60 +1877,10 @@ public class XmlParserTest { XMLUnit.setIgnoreWhitespace(true); ourCtx = new FhirContext(); } - + @BeforeClass public static void beforeClass2() { System.setProperty("file.encoding", "ISO-8859-1"); } - - /** - * See #103 - */ - @Test - public void testEncodeAndReEncodeContainedXml() { - Composition comp = new Composition(); - comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); - comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); - comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); - - 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().getContainedResources().size()); - } - - /** - * See #103 - */ - @Test - public void testEncodeAndReEncodeContainedJson() { - Composition comp = new Composition(); - comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); - comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); - comp.addSection().getContent().setResource(new AllergyIntolerance().addIdentifier("foo", "bar")); - - 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().getContainedResources().size()); - } } diff --git a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/SearchTest.java b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/SearchTest.java index 7ed69d040bc..eb8ff4c7704 100644 --- a/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/SearchTest.java +++ b/hapi-fhir-structures-dstu/src/test/java/ca/uhn/fhir/rest/client/SearchTest.java @@ -63,7 +63,11 @@ public class SearchTest { @Test public void testPostOnLongParamsList() throws Exception { - String retVal = "<id>bc59fca7-0a8f-4caf-abef-45c8d53ece6a</id><link rel=\"self\" href=\"http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Encounter?identifier=urn%3Aoid%3A1.3.6.1.4.1.12201.2%7C11410000159&_include=Encounter.participant&_include=Encounter.location.location&_include=Encounter.subject\"/><link rel=\"fhir-base\" href=\"http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">1</os:totalResults><author><name>HAPI FHIR Server</name></author><entry><title>Encounter 5994268http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Encounter/59942682014-08-05T12:00:11.000-04:002014-08-05T11:59:21.000-04:00
No narrative template available for resource profile: http://fhir.connectinggta.ca/Profile/encounter
Patient 5993715http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Patient/59937152014-08-08T14:46:16-04:00
Person CHA
IdentifierUHN MRN 7018614
Address100 Dundas street west
Toronto ON Can
Date of birth01 January 1988
Practitioner Practitioner/5738815http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Practitioner/57388152014-08-08T13:53:52.000-04:002009-12-04T13:43:11.000-05:00
No narrative template available for resource profile: http://hl7.org/fhir/profiles/Practitioner
Location Location/5994269http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Location/59942692014-08-08T14:46:16-04:00
No narrative template available for resource profile: http://hl7.org/fhir/profiles/Location
"; + String retVal = "<id>bc59fca7-0a8f-4caf-abef-45c8d53ece6a</id><link rel=\"self\" href=\"http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Encounter?identifier=urn%3Aoid%3A1.3.6.1.4.1.12201.2%7C11410000159&_include=Encounter.participant&_include=Encounter.location.location&_include=Encounter.subject\"/><link rel=\"fhir-base\" href=\"http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2\"/><os:totalResults xmlns:os=\"http://a9.com/-/spec/opensearch/1.1/\">1</os:totalResults><author><name>HAPI FHIR Server</name></author>" + + "<entry><title>Encounter 5994268http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Encounter/59942682014-08-05T12:00:11.000-04:002014-08-05T11:59:21.000-04:00
No narrative template available for resource profile: http://fhir.connectinggta.ca/Profile/encounter
" + + "Patient 5993715http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Patient/59937152014-08-08T14:46:16-04:00
Person CHA
IdentifierUHN MRN 7018614
Address100 Dundas street west
Toronto ON Can
Date of birth01 January 1988
" + + "Practitioner Practitioner/5738815http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Practitioner/57388152014-08-08T13:53:52.000-04:002009-12-04T13:43:11.000-05:00
No narrative template available for resource profile: http://hl7.org/fhir/profiles/Practitioner
" + + "Location Location/5994269http://uhnvesb01d.uhn.on.ca:25180/uhn-fhir-service-1.2/Location/59942692014-08-08T14:46:16-04:00
No narrative template available for resource profile: http://hl7.org/fhir/profiles/Location
"; ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(ourHttpClient.execute(capt.capture())).thenReturn(ourHttpResponse); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java index 0a0b9c93065..68e2470e2c3 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/client/GenericClientDstu2Test.java @@ -16,6 +16,7 @@ import org.apache.commons.io.input.ReaderInputStream; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; +import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpUriRequest; @@ -37,9 +38,11 @@ import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.dstu2.resource.Observation; import ca.uhn.fhir.model.dstu2.resource.Parameters; import ca.uhn.fhir.model.dstu2.resource.Patient; +import ca.uhn.fhir.model.primitive.DateDt; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.parser.IParser; +import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.EncodingEnum; @@ -48,11 +51,6 @@ public class GenericClientDstu2Test { private HttpClient myHttpClient; private HttpResponse myHttpResponse; - @BeforeClass - public static void beforeClass() { - ourCtx = FhirContext.forDstu2(); - } - @Before public void before() { myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs()); @@ -61,30 +59,9 @@ public class GenericClientDstu2Test { myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs()); } - @SuppressWarnings("unused") - @Test - public void testSearchWithReverseInclude() throws Exception { - - String msg = getPatientFeedWithOneResult(); - - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"))); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - //@formatter:off - Bundle response = client.search() - .forResource(Patient.class) - .encodedJson() - .revInclude(new Include("Provenance:target")) - .execute(); - //@formatter:on - - assertEquals("http://example.com/fhir/Patient?_revinclude=Provenance%3Atarget&_format=json", capt.getValue().getURI().toString()); - + private String extractBody(ArgumentCaptor capt, int count) throws IOException { + String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(count)).getEntity().getContent(), "UTF-8"); + return body; } private String getPatientFeedWithOneResult() { @@ -108,6 +85,122 @@ public class GenericClientDstu2Test { return msg; } + @Test + public void testCreate() throws Exception { + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, "")); + when(myHttpResponse.getEntity().getContent()).then(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + int idx = 0; + + Patient p = new Patient(); + p.addName().addFamily("FOOFAMILY"); + + client.create().resource(p).execute(); + + assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); + assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); + assertThat(extractBody(capt, idx), containsString("")); + assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString()); + assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + + p.setId("123"); + + client.create().resource(p).execute(); + assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); + assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); + String body = extractBody(capt, idx); + assertThat(body, containsString("")); + assertThat(body, not(containsString("123"))); + assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString()); + assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + + } + + @Test + public void testCreateConditional() throws Exception { + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, "")); + when(myHttpResponse.getEntity().getContent()).then(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + int idx = 0; + + Patient p = new Patient(); + p.addName().addFamily("FOOFAMILY"); + + client.create().resource(p).conditionalByUrl("Patient?name=foo").execute(); + assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); + assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); + assertThat(extractBody(capt, idx), containsString("")); + assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString()); + assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_IF_NONE_EXIST).getValue()); + assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + + client.create().resource(p).conditional().where(Patient.NAME.matches().value("foo")).execute(); + assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); + assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); + assertThat(extractBody(capt, idx), containsString("")); + assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString()); + assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_IF_NONE_EXIST).getValue()); + assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + + } + + @Test + public void testDeleteConditional() throws Exception { + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, "")); + // when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", + // Constants.CT_TEXT + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).then(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + int idx = 0; + + client.delete().resourceById(new IdDt("Patient/123")).execute(); + assertEquals("DELETE", capt.getAllValues().get(idx).getMethod()); + assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + client.delete().resourceConditionalByUrl("Patient?name=foo").execute(); + assertEquals("DELETE", capt.getAllValues().get(idx).getMethod()); + assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + client.delete().resourceConditionalByType("Patient").where(Patient.NAME.matches().value("foo")).execute(); + assertEquals("DELETE", capt.getAllValues().get(idx).getMethod()); + assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString()); + idx++; + + } + @Test public void testHistory() throws Exception { @@ -164,27 +257,253 @@ public class GenericClientDstu2Test { } @Test - public void testSearchByString() throws Exception { - String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}"; + public void testOperationAsGetWithInParameters() throws Exception { + IParser p = ourCtx.newXmlParser(); + + Parameters inParams = new Parameters(); + inParams.addParameter().setName("param1").setValue(new StringDt("STRINGVALIN1")); + inParams.addParameter().setName("param1").setValue(new StringDt("STRINGVALIN1b")); + inParams.addParameter().setName("param2").setValue(new StringDt("STRINGVALIN2")); + + Parameters outParams = new Parameters(); + outParams.addParameter().setValue(new StringDt("STRINGVALOUT1")); + outParams.addParameter().setValue(new StringDt("STRINGVALOUT2")); + final String respString = p.encodeResourceToString(outParams); ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"))); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + int idx = 0; + //@formatter:off - Bundle response = client.search() - .forResource("Patient") - .where(Patient.NAME.matches().value("james")) - .execute(); - //@formatter:on + Parameters resp = client + .operation() + .onServer() + .named("$SOMEOPERATION") + .withParameters(inParams) + .useHttpGet() + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/$SOMEOPERATION?param1=STRINGVALIN1¶m1=STRINGVALIN1b¶m2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals(respString, p.encodeResourceToString(resp)); + assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; - assertEquals("http://example.com/fhir/Patient?name=james", capt.getValue().getURI().toString()); - assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass()); + //@formatter:off + resp = client + .operation() + .onType(Patient.class) + .named("$SOMEOPERATION") + .withParameters(inParams) + .useHttpGet() + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION?param1=STRINGVALIN1¶m1=STRINGVALIN1b¶m2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals(respString, p.encodeResourceToString(resp)); + assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + //@formatter:off + resp = client + .operation() + .onInstance(new IdDt("Patient", "123")) + .named("$SOMEOPERATION") + .withParameters(inParams) + .useHttpGet() + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION?param1=STRINGVALIN1¶m1=STRINGVALIN1b¶m2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals(respString, p.encodeResourceToString(resp)); + assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + + // @formatter:off + resp = client + .operation() + .onInstance(new IdDt("http://foo.com/bar/baz/Patient/123/_history/22")) + .named("$SOMEOPERATION") + .withParameters(inParams) + .useHttpGet() + .execute(); + // @formatter:on + assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION?param1=STRINGVALIN1¶m1=STRINGVALIN1b¶m2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString()); + idx++; + } + + @Test + public void testOperationAsGetWithNoInParameters() throws Exception { + IParser p = ourCtx.newXmlParser(); + + Parameters outParams = new Parameters(); + outParams.addParameter().setValue(new StringDt("STRINGVALOUT1")); + outParams.addParameter().setValue(new StringDt("STRINGVALOUT2")); + final String respString = p.encodeResourceToString(outParams); + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + int idx = 0; + + //@formatter:off + Parameters resp = client + .operation() + .onServer() + .named("$SOMEOPERATION") + .withNoParameters(Parameters.class) + .useHttpGet() + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals(respString, p.encodeResourceToString(resp)); + assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + + //@formatter:off + resp = client + .operation() + .onType(Patient.class) + .named("$SOMEOPERATION") + .withNoParameters(Parameters.class) + .useHttpGet() + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals(respString, p.encodeResourceToString(resp)); + assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + + //@formatter:off + resp = client + .operation() + .onInstance(new IdDt("Patient", "123")) + .named("$SOMEOPERATION") + .withNoParameters(Parameters.class) + .useHttpGet() + .execute(); + //@formatter:on + assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals(respString, p.encodeResourceToString(resp)); + assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); + idx++; + + // @formatter:off + resp = client + .operation() + .onInstance(new IdDt("http://foo.com/bar/baz/Patient/123/_history/22")) + .named("$SOMEOPERATION") + .withNoParameters(Parameters.class) + .useHttpGet() + .execute(); + // @formatter:on + assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); + idx++; + } + + @Test + public void testOperationWithBundleResponseXml() throws Exception { + IParser p = ourCtx.newXmlParser(); + + Parameters inParams = new Parameters(); + inParams.addParameter().setValue(new StringDt("STRINGVALIN1")); + inParams.addParameter().setValue(new StringDt("STRINGVALIN2")); + String reqString = p.encodeResourceToString(inParams); + + ca.uhn.fhir.model.dstu2.resource.Bundle outParams = new ca.uhn.fhir.model.dstu2.resource.Bundle(); + outParams.setTotal(123); + final String respString = p.encodeResourceToString(outParams); + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + int idx = 0; + + //@formatter:off + Parameters resp = client + .operation() + .onServer() + .named("$SOMEOPERATION") + .withParameters(inParams).execute(); + //@formatter:on + assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); + assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); + assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); + assertEquals(extractBody(capt, idx), reqString); + assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); + assertEquals(1, resp.getParameter().size()); + assertEquals(ca.uhn.fhir.model.dstu2.resource.Bundle.class, resp.getParameter().get(0).getResource().getClass()); + idx++; + } + + @Test + public void testOperationWithBundleResponseJson() throws Exception { + + final String resp = "{\n" + + " \"resourceType\":\"Bundle\",\n" + + " \"id\":\"8cef5f2a-0ba9-43a5-be26-c8dde9ff0e19\",\n" + + " \"base\":\"http://fhirtest.uhn.ca/baseDstu2\"\n" + + "}"; + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { + @Override + public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { + return new ReaderInputStream(new StringReader(resp), Charset.forName("UTF-8")); + } + }); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://fhirtest.uhn.ca/baseDstu2"); + + client.registerInterceptor(new LoggingInterceptor(true)); + + // Create the input parameters to pass to the server + Parameters inParams = new Parameters(); + inParams.addParameter().setName("start").setValue(new DateDt("2001-01-01")); + inParams.addParameter().setName("end").setValue(new DateDt("2015-03-01")); + + // Invoke $everything on "Patient/1" + Parameters outParams = client.operation().onInstance(new IdDt("Patient", "18066")).named("$everything").withParameters(inParams).execute(); + + /* + * Note that the $everything operation returns a Bundle instead of a Parameters resource. The client operation methods return a Parameters instance however, so HAPI creates a Parameters object + * with a single parameter containing the value. + */ + ca.uhn.fhir.model.dstu2.resource.Bundle responseBundle = (ca.uhn.fhir.model.dstu2.resource.Bundle) outParams.getParameter().get(0).getResource(); + + // Print the response bundle + assertEquals("8cef5f2a-0ba9-43a5-be26-c8dde9ff0e19", responseBundle.getId().getIdPart()); } @Test @@ -352,14 +671,7 @@ public class GenericClientDstu2Test { } @Test - public void testOperationAsGetWithNoInParameters() throws Exception { - IParser p = ourCtx.newXmlParser(); - - Parameters outParams = new Parameters(); - outParams.addParameter().setValue(new StringDt("STRINGVALOUT1")); - outParams.addParameter().setValue(new StringDt("STRINGVALOUT2")); - final String respString = p.encodeResourceToString(outParams); - + public void testPageNext() throws Exception { ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); @@ -367,7 +679,7 @@ public class GenericClientDstu2Test { when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { @Override public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + return new ReaderInputStream(new StringReader(getPatientFeedWithOneResult()), Charset.forName("UTF-8")); } }); @@ -375,158 +687,37 @@ public class GenericClientDstu2Test { int idx = 0; + ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle(); + sourceBundle.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://foo.bar/prev"); + sourceBundle.getLinkOrCreate(IBaseBundle.LINK_NEXT).setUrl("http://foo.bar/next"); + //@formatter:off - Parameters resp = client - .operation() - .onServer() - .named("$SOMEOPERATION") - .withNoParameters(Parameters.class) - .useHttpGet() + ca.uhn.fhir.model.dstu2.resource.Bundle resp = client + .loadPage() + .next(sourceBundle) .execute(); //@formatter:on - assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); - assertEquals(respString, p.encodeResourceToString(resp)); - assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); + + assertEquals(1, resp.getEntry().size()); + assertEquals("http://foo.bar/next", capt.getAllValues().get(idx).getURI().toASCIIString()); idx++; - //@formatter:off - resp = client - .operation() - .onType(Patient.class) - .named("$SOMEOPERATION") - .withNoParameters(Parameters.class) - .useHttpGet() - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); - assertEquals(respString, p.encodeResourceToString(resp)); - assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - //@formatter:off - resp = client - .operation() - .onInstance(new IdDt("Patient", "123")) - .named("$SOMEOPERATION") - .withNoParameters(Parameters.class) - .useHttpGet() - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); - assertEquals(respString, p.encodeResourceToString(resp)); - assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - // @formatter:off - resp = client - .operation() - .onInstance(new IdDt("http://foo.com/bar/baz/Patient/123/_history/22")) - .named("$SOMEOPERATION") - .withNoParameters(Parameters.class) - .useHttpGet() - .execute(); - // @formatter:on - assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); - idx++; } @Test - public void testOperationAsGetWithInParameters() throws Exception { - IParser p = ourCtx.newXmlParser(); - - Parameters inParams = new Parameters(); - inParams.addParameter().setName("param1").setValue(new StringDt("STRINGVALIN1")); - inParams.addParameter().setName("param1").setValue(new StringDt("STRINGVALIN1b")); - inParams.addParameter().setName("param2").setValue(new StringDt("STRINGVALIN2")); - - Parameters outParams = new Parameters(); - outParams.addParameter().setValue(new StringDt("STRINGVALOUT1")); - outParams.addParameter().setValue(new StringDt("STRINGVALOUT2")); - final String respString = p.encodeResourceToString(outParams); - - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); - } - }); - + public void testPageNextNoLink() throws Exception { IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - int idx = 0; - - //@formatter:off - Parameters resp = client - .operation() - .onServer() - .named("$SOMEOPERATION") - .withParameters(inParams) - .useHttpGet() - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/$SOMEOPERATION?param1=STRINGVALIN1¶m1=STRINGVALIN1b¶m2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString()); - assertEquals(respString, p.encodeResourceToString(resp)); - assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - //@formatter:off - resp = client - .operation() - .onType(Patient.class) - .named("$SOMEOPERATION") - .withParameters(inParams) - .useHttpGet() - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient/$SOMEOPERATION?param1=STRINGVALIN1¶m1=STRINGVALIN1b¶m2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString()); - assertEquals(respString, p.encodeResourceToString(resp)); - assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - //@formatter:off - resp = client - .operation() - .onInstance(new IdDt("Patient", "123")) - .named("$SOMEOPERATION") - .withParameters(inParams) - .useHttpGet() - .execute(); - //@formatter:on - assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION?param1=STRINGVALIN1¶m1=STRINGVALIN1b¶m2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString()); - assertEquals(respString, p.encodeResourceToString(resp)); - assertEquals("GET", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - // @formatter:off - resp = client - .operation() - .onInstance(new IdDt("http://foo.com/bar/baz/Patient/123/_history/22")) - .named("$SOMEOPERATION") - .withParameters(inParams) - .useHttpGet() - .execute(); - // @formatter:on - assertEquals("http://example.com/fhir/Patient/123/$SOMEOPERATION?param1=STRINGVALIN1¶m1=STRINGVALIN1b¶m2=STRINGVALIN2", capt.getAllValues().get(idx).getURI().toASCIIString()); - idx++; + ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle(); + try { + client.loadPage().next(sourceBundle).execute(); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("Can not perform paging operation because no link was found in Bundle with relation \"next\"")); + } } @Test - public void testOperationWithBundleResponse() throws Exception { - IParser p = ourCtx.newXmlParser(); - - Parameters inParams = new Parameters(); - inParams.addParameter().setValue(new StringDt("STRINGVALIN1")); - inParams.addParameter().setValue(new StringDt("STRINGVALIN2")); - String reqString = p.encodeResourceToString(inParams); - - ca.uhn.fhir.model.dstu2.resource.Bundle outParams = new ca.uhn.fhir.model.dstu2.resource.Bundle(); - outParams.setTotal(123); - final String respString = p.encodeResourceToString(outParams); - + public void testPagePrev() throws Exception { ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); @@ -534,7 +725,7 @@ public class GenericClientDstu2Test { when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { @Override public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8")); + return new ReaderInputStream(new StringReader(getPatientFeedWithOneResult()), Charset.forName("UTF-8")); } }); @@ -542,21 +733,88 @@ public class GenericClientDstu2Test { int idx = 0; + ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle(); + sourceBundle.getLinkOrCreate("previous").setUrl("http://foo.bar/prev"); + //@formatter:off - Parameters resp = client - .operation() - .onServer() - .named("$SOMEOPERATION") - .withParameters(inParams).execute(); + ca.uhn.fhir.model.dstu2.resource.Bundle resp = client + .loadPage() + .previous(sourceBundle) + .execute(); //@formatter:on - assertEquals("http://example.com/fhir/$SOMEOPERATION", capt.getAllValues().get(idx).getURI().toASCIIString()); - assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); - assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); - assertEquals(extractBody(capt, idx), reqString); - assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); - assertEquals(1, resp.getParameter().size()); - assertEquals(ca.uhn.fhir.model.dstu2.resource.Bundle.class, resp.getParameter().get(0).getResource().getClass()); + + assertEquals(1, resp.getEntry().size()); + assertEquals("http://foo.bar/prev", capt.getAllValues().get(idx).getURI().toASCIIString()); idx++; + + /* + * Try with "prev" instead of "previous" + */ + + sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle(); + sourceBundle.getLinkOrCreate("prev").setUrl("http://foo.bar/prev"); + + //@formatter:off + resp = client + .loadPage() + .previous(sourceBundle) + .execute(); + //@formatter:on + + assertEquals(1, resp.getEntry().size()); + assertEquals("http://foo.bar/prev", capt.getAllValues().get(idx).getURI().toASCIIString()); + idx++; + + } + + @Test + public void testSearchByString() throws Exception { + String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}"; + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"))); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + //@formatter:off + Bundle response = client.search() + .forResource("Patient") + .where(Patient.NAME.matches().value("james")) + .execute(); + //@formatter:on + + assertEquals("http://example.com/fhir/Patient?name=james", capt.getValue().getURI().toString()); + assertEquals(Patient.class, response.getEntries().get(0).getResource().getClass()); + + } + + @SuppressWarnings("unused") + @Test + public void testSearchWithReverseInclude() throws Exception { + + String msg = getPatientFeedWithOneResult(); + + ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); + when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); + when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); + when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); + when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"))); + + IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); + + //@formatter:off + Bundle response = client.search() + .forResource(Patient.class) + .encodedJson() + .revInclude(new Include("Provenance:target")) + .execute(); + //@formatter:on + + assertEquals("http://example.com/fhir/Patient?_revinclude=Provenance%3Atarget&_format=json", capt.getValue().getURI().toString()); + } @Test @@ -709,122 +967,6 @@ public class GenericClientDstu2Test { assertEquals("Patient/2/_history/2", response.getEntry().get(1).getTransactionResponse().getLocation()); } - @Test - public void testDeleteConditional() throws Exception { - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, "")); - // when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", - // Constants.CT_TEXT + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).then(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - int idx = 0; - - client.delete().resourceById(new IdDt("Patient/123")).execute(); - assertEquals("DELETE", capt.getAllValues().get(idx).getMethod()); - assertEquals("http://example.com/fhir/Patient/123", capt.getAllValues().get(idx).getURI().toString()); - idx++; - - client.delete().resourceConditionalByUrl("Patient?name=foo").execute(); - assertEquals("DELETE", capt.getAllValues().get(idx).getMethod()); - assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString()); - idx++; - - client.delete().resourceConditionalByType("Patient").where(Patient.NAME.matches().value("foo")).execute(); - assertEquals("DELETE", capt.getAllValues().get(idx).getMethod()); - assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getURI().toString()); - idx++; - - } - - @Test - public void testCreateConditional() throws Exception { - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, "")); - when(myHttpResponse.getEntity().getContent()).then(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - int idx = 0; - - Patient p = new Patient(); - p.addName().addFamily("FOOFAMILY"); - - client.create().resource(p).conditionalByUrl("Patient?name=foo").execute(); - assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); - assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); - assertThat(extractBody(capt, idx), containsString("")); - assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString()); - assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_IF_NONE_EXIST).getValue()); - assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - client.create().resource(p).conditional().where(Patient.NAME.matches().value("foo")).execute(); - assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); - assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); - assertThat(extractBody(capt, idx), containsString("")); - assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString()); - assertEquals("http://example.com/fhir/Patient?name=foo", capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_IF_NONE_EXIST).getValue()); - assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - } - - @Test - public void testCreate() throws Exception { - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, "")); - when(myHttpResponse.getEntity().getContent()).then(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - int idx = 0; - - Patient p = new Patient(); - p.addName().addFamily("FOOFAMILY"); - - client.create().resource(p).execute(); - - assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); - assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); - assertThat(extractBody(capt, idx), containsString("")); - assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString()); - assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - p.setId("123"); - - client.create().resource(p).execute(); - assertEquals(1, capt.getAllValues().get(idx).getHeaders(Constants.HEADER_CONTENT_TYPE).length); - assertEquals(EncodingEnum.XML.getResourceContentType() + Constants.HEADER_SUFFIX_CT_UTF_8, capt.getAllValues().get(idx).getFirstHeader(Constants.HEADER_CONTENT_TYPE).getValue()); - String body = extractBody(capt, idx); - assertThat(body, containsString("")); - assertThat(body, not(containsString("123"))); - assertEquals("http://example.com/fhir/Patient", capt.getAllValues().get(idx).getURI().toString()); - assertEquals("POST", capt.getAllValues().get(idx).getRequestLine().getMethod()); - idx++; - - } - @Test public void testUpdateConditional() throws Exception { ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); @@ -878,106 +1020,9 @@ public class GenericClientDstu2Test { } - private String extractBody(ArgumentCaptor capt, int count) throws IOException { - String body = IOUtils.toString(((HttpEntityEnclosingRequestBase) capt.getAllValues().get(count)).getEntity().getContent(), "UTF-8"); - return body; - } - - @Test - public void testPageNext() throws Exception { - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(getPatientFeedWithOneResult()), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - int idx = 0; - - ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle(); - sourceBundle.getLinkOrCreate(IBaseBundle.LINK_PREV).setUrl("http://foo.bar/prev"); - sourceBundle.getLinkOrCreate(IBaseBundle.LINK_NEXT).setUrl("http://foo.bar/next"); - - //@formatter:off - ca.uhn.fhir.model.dstu2.resource.Bundle resp = client - .loadPage() - .next(sourceBundle) - .execute(); - //@formatter:on - - assertEquals(1, resp.getEntry().size()); - assertEquals("http://foo.bar/next", capt.getAllValues().get(idx).getURI().toASCIIString()); - idx++; - - } - - @Test - public void testPagePrev() throws Exception { - ArgumentCaptor capt = ArgumentCaptor.forClass(HttpUriRequest.class); - when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse); - when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK")); - when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8")); - when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer() { - @Override - public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable { - return new ReaderInputStream(new StringReader(getPatientFeedWithOneResult()), Charset.forName("UTF-8")); - } - }); - - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - int idx = 0; - - ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle(); - sourceBundle.getLinkOrCreate("previous").setUrl("http://foo.bar/prev"); - - //@formatter:off - ca.uhn.fhir.model.dstu2.resource.Bundle resp = client - .loadPage() - .previous(sourceBundle) - .execute(); - //@formatter:on - - assertEquals(1, resp.getEntry().size()); - assertEquals("http://foo.bar/prev", capt.getAllValues().get(idx).getURI().toASCIIString()); - idx++; - - /* - * Try with "prev" instead of "previous" - */ - - sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle(); - sourceBundle.getLinkOrCreate("prev").setUrl("http://foo.bar/prev"); - - //@formatter:off - resp = client - .loadPage() - .previous(sourceBundle) - .execute(); - //@formatter:on - - assertEquals(1, resp.getEntry().size()); - assertEquals("http://foo.bar/prev", capt.getAllValues().get(idx).getURI().toASCIIString()); - idx++; - - } - - @Test - public void testPageNextNoLink() throws Exception { - IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir"); - - ca.uhn.fhir.model.dstu2.resource.Bundle sourceBundle = new ca.uhn.fhir.model.dstu2.resource.Bundle(); - try { - client.loadPage().next(sourceBundle).execute(); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("Can not perform paging operation because no link was found in Bundle with relation \"next\"")); - } + @BeforeClass + public static void beforeClass() { + ourCtx = FhirContext.forDstu2(); } } diff --git a/pom.xml b/pom.xml index 80fb5ca333c..ecae7a34614 100644 --- a/pom.xml +++ b/pom.xml @@ -465,6 +465,9 @@ + + + @@ -833,6 +836,7 @@ hapi-fhir-base hapi-fhir-structures-dstu hapi-fhir-structures-dstu2 + hapi-fhir-structures-hl7org-dstu2 hapi-fhir-jpaserver-base examples diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e2c98ddb6e9..dcea5ed559e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -42,6 +42,16 @@ used to validate resources as they are being parsed, and optionally fail if invalid/unexpected elements are found in resource bodies during parsing. + + IParser#parseResource(Class, String) method, which is used to parse a resource into the given + structure will now throw a DataFormatException if the structure is for the wrong type of + resource for the one actually found in the input String (or Reader). For example, if a Patient + resource is being parsed into Organization.class this will now cause an error. Previously, + the XML parser would ignore the type and the JSON parser would fail. This also caused + operations to not parse correctly if they returned a resource type other than + parameters with JSON encoding (e.g. the $everything operation on UHN's test server). + Thanks to Avinash Shanbhag for reporting! + diff --git a/src/site/site.xml b/src/site/site.xml index eb1c53c6342..9f443d3091c 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -107,6 +107,7 @@ +