From c1afb4f54d879e6386711053bf416b00b3fdaf68 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Thu, 7 Jan 2016 15:04:56 -0500 Subject: [PATCH] Get overlay working for DSTU2.1 --- .../BaseValidatingInterceptor.java | 18 ++- .../ca/uhn/fhirtest/TestRestfulServer.java | 4 - ...sponseValidatingInterceptorDstu21Test.java | 25 +++- .../java/ca/uhn/fhir/model/XhtmlNodeTest.java | 2 + .../java/ca/uhn/fhir/to/BaseController.java | 31 ++++- .../main/webapp/WEB-INF/templates/result.html | 116 +++++++++++++++++- .../ca/uhn/fhir/jpa/test/OverlayTestApp.java | 34 ++--- 7 files changed, 197 insertions(+), 33 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/BaseValidatingInterceptor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/BaseValidatingInterceptor.java index 57f594bc7e7..60965c5c072 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/BaseValidatingInterceptor.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/BaseValidatingInterceptor.java @@ -28,10 +28,13 @@ import java.util.List; import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.text.StrLookup; import org.apache.commons.lang3.text.StrSubstitutor; +import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; +import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; +import ca.uhn.fhir.util.OperationOutcomeUtil; import ca.uhn.fhir.validation.FhirValidator; import ca.uhn.fhir.validation.IValidatorModule; import ca.uhn.fhir.validation.ResultSeverityEnum; @@ -252,15 +255,22 @@ abstract class BaseValidatingInterceptor extends InterceptorAdapter { } if (myAddResponseOutcomeHeaderOnSeverity != null) { - boolean add = false; + IBaseOperationOutcome outcome = null; for (SingleValidationMessage next : validationResult.getMessages()) { if (next.getSeverity().ordinal() >= myAddResponseOutcomeHeaderOnSeverity) { - add = true; + outcome = validationResult.toOperationOutcome(); + break; } } - if (add) { + if (outcome == null && myAddResponseOutcomeHeaderOnSeverity != null && myAddResponseOutcomeHeaderOnSeverity == ResultSeverityEnum.INFORMATION.ordinal()) { + FhirContext ctx = theRequestDetails.getServer().getFhirContext(); + outcome = OperationOutcomeUtil.newInstance(ctx); + OperationOutcomeUtil.addIssue(ctx, outcome, "information", "No issues detected", "", "informational"); + } + + if (outcome != null) { IParser parser = theRequestDetails.getServer().getFhirContext().newJsonParser().setPrettyPrint(false); - String encoded = parser.encodeResourceToString(validationResult.toOperationOutcome()); + String encoded = parser.encodeResourceToString(outcome); theRequestDetails.getResponse().addHeader(myResponseOutcomeHeaderName, encoded); } } diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java index 1db036dcd27..ecebb7ba52a 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java @@ -9,7 +9,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -33,10 +32,7 @@ import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy; import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; -import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor; import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; -import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor; -import ca.uhn.fhir.validation.IValidatorModule; import ca.uhn.fhirtest.config.TestDstu21Config; import ca.uhn.fhirtest.config.TestDstu2Config; diff --git a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/rest/server/ResponseValidatingInterceptorDstu21Test.java b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/rest/server/ResponseValidatingInterceptorDstu21Test.java index f9a91bca105..94b61d4192a 100644 --- a/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/rest/server/ResponseValidatingInterceptorDstu21Test.java +++ b/hapi-fhir-structures-dstu2.1/src/test/java/ca/uhn/fhir/rest/server/ResponseValidatingInterceptorDstu21Test.java @@ -39,7 +39,7 @@ import ca.uhn.fhir.validation.ResultSeverityEnum; public class ResponseValidatingInterceptorDstu21Test { private static CloseableHttpClient ourClient; - + private static FhirContext ourCtx = FhirContext.forDstu2_1(); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseValidatingInterceptorDstu21Test.class); private static int ourPort; @@ -251,6 +251,29 @@ public class ResponseValidatingInterceptorDstu21Test { assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation"))); } + @Test + public void testOperationOutcome() throws Exception { + myInterceptor.setAddResponseOutcomeHeaderOnSeverity(ResultSeverityEnum.INFORMATION); + Patient patient = new Patient(); + patient.addIdentifier().setValue("002"); + patient.setGender(AdministrativeGender.MALE); + myReturnResource = patient; + + HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar"); + + HttpResponse status = ourClient.execute(httpPost); + + String responseContent = IOUtils.toString(status.getEntity().getContent()); + IOUtils.closeQuietly(status.getEntity().getContent()); + + ourLog.info("Response was:\n{}", status); + ourLog.trace("Response was:\n{}", responseContent); + + assertEquals(200, status.getStatusLine().getStatusCode()); + assertThat(status.toString(), (containsString("X-FHIR-Response-Validation: {\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"information\",\"code\":\"informational\",\"diagnostics\":\"No issues detected\"}]}"))); + } + + @AfterClass public static void afterClass() throws Exception { ourServer.stop(); diff --git a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/model/XhtmlNodeTest.java b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/model/XhtmlNodeTest.java index 36b77c32d08..a24e8a78c41 100644 --- a/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/model/XhtmlNodeTest.java +++ b/hapi-fhir-structures-hl7org-dstu2/src/test/java/ca/uhn/fhir/model/XhtmlNodeTest.java @@ -4,11 +4,13 @@ import static org.junit.Assert.*; import org.hl7.fhir.instance.model.Narrative; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +import org.junit.Ignore; import org.junit.Test; public class XhtmlNodeTest { @Test + @Ignore public void testNamespaces() { Narrative type = new Narrative(); diff --git a/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/BaseController.java b/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/BaseController.java index ada85b3920d..4287649fa18 100644 --- a/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/BaseController.java +++ b/hapi-fhir-testpage-overlay/src/main/java/ca/uhn/fhir/to/BaseController.java @@ -32,7 +32,9 @@ import org.hl7.fhir.dstu21.model.Conformance.ConformanceRestComponent; import org.hl7.fhir.dstu21.model.Conformance.ConformanceRestResourceComponent; import org.hl7.fhir.dstu21.model.DecimalType; import org.hl7.fhir.dstu21.model.Extension; +import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IDomainResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.ModelMap; import org.thymeleaf.TemplateEngine; @@ -492,8 +494,16 @@ public class BaseController { private String parseNarrative(HomeRequest theRequest, EncodingEnum theCtEnum, String theResultBody) { try { - IResource resource = (IResource) theCtEnum.newParser(getContext(theRequest)).parseResource(theResultBody); - String retVal = resource.getText().getDiv().getValueAsString(); + IBaseResource par = theCtEnum.newParser(getContext(theRequest)).parseResource(theResultBody); + String retVal; + if (par instanceof IResource) { + IResource resource = (IResource) par; + retVal = resource.getText().getDiv().getValueAsString(); + } else if (par instanceof IDomainResource) { + retVal = ((IDomainResource)par).getText().getDivAsString(); + } else { + retVal = null; + } return StringUtils.defaultString(retVal); } catch (Exception e) { ourLog.error("Failed to parse resource", e); @@ -553,7 +563,9 @@ public class BaseController { StringBuilder resultDescription = new StringBuilder(); Bundle bundle = null; + IBaseResource riBundle = null; + FhirContext context = getContext(theRequest); if (ctEnum == null) { resultDescription.append("Non-FHIR response"); } else { @@ -564,7 +576,11 @@ public class BaseController { resultDescription.append("JSON resource"); } else if (theResultType == ResultType.BUNDLE) { resultDescription.append("JSON bundle"); - bundle = getContext(theRequest).newJsonParser().parseBundle(resultBody); + if (context.getVersion().getVersion().isRi()) { + riBundle = context.newJsonParser().parseResource(resultBody); + } else { + bundle = context.newJsonParser().parseBundle(resultBody); + } } break; case XML: @@ -574,7 +590,11 @@ public class BaseController { resultDescription.append("XML resource"); } else if (theResultType == ResultType.BUNDLE) { resultDescription.append("XML bundle"); - bundle = getContext(theRequest).newXmlParser().parseBundle(resultBody); + if (context.getVersion().getVersion().isRi()) { + riBundle = context.newXmlParser().parseResource(resultBody); + } else { + bundle = context.newXmlParser().parseBundle(resultBody); + } } break; } @@ -584,7 +604,7 @@ public class BaseController { * DSTU2 no longer has a title in the bundle format, but it's still useful here.. */ if (bundle != null) { - INarrativeGenerator gen = getContext(theRequest).getNarrativeGenerator(); + INarrativeGenerator gen = context.getNarrativeGenerator(); if (gen != null) { for (BundleEntry next : bundle.getEntries()) { if (next.getTitle().isEmpty() && next.getResource() != null) { @@ -604,6 +624,7 @@ public class BaseController { theModelMap.put("resultDescription", resultDescription.toString()); theModelMap.put("action", action); theModelMap.put("bundle", bundle); + theModelMap.put("riBundle", riBundle); theModelMap.put("resultStatus", resultStatus); theModelMap.put("requestUrl", requestUrl); diff --git a/hapi-fhir-testpage-overlay/src/main/webapp/WEB-INF/templates/result.html b/hapi-fhir-testpage-overlay/src/main/webapp/WEB-INF/templates/result.html index f6b263c208f..5a6ce6eaf53 100644 --- a/hapi-fhir-testpage-overlay/src/main/webapp/WEB-INF/templates/result.html +++ b/hapi-fhir-testpage-overlay/src/main/webapp/WEB-INF/templates/result.html @@ -118,7 +118,9 @@ If the response is a bundle, this block will contain a collapsible table with a summary of each entry as well as paging buttons and controls for viewing/editing/etc results - --> + + NON-RI Bundle + -->
@@ -219,7 +221,117 @@ });
-
+
+ + + + +
+
+
+

+ Bundle contains no entries + + + + + + + + + + + + + + + +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
IDUpdated
+ + + + + + +
+
+
+ +
+
+ + +

Raw Message diff --git a/hapi-fhir-testpage-overlay/src/test/java/ca/uhn/fhir/jpa/test/OverlayTestApp.java b/hapi-fhir-testpage-overlay/src/test/java/ca/uhn/fhir/jpa/test/OverlayTestApp.java index e2c4ec66bce..44fcd73a2ea 100644 --- a/hapi-fhir-testpage-overlay/src/test/java/ca/uhn/fhir/jpa/test/OverlayTestApp.java +++ b/hapi-fhir-testpage-overlay/src/test/java/ca/uhn/fhir/jpa/test/OverlayTestApp.java @@ -120,7 +120,7 @@ public class OverlayTestApp { Organization o1 = new Organization(); o1.getName().setValue("Some Org"); - MethodOutcome create = client.create(o1); + MethodOutcome create = client.create().resource(o1).execute(); IdDt orgId = (IdDt) create.getId(); Patient p1 = new Patient(); @@ -132,24 +132,24 @@ public class OverlayTestApp { TagList list = new TagList(); list.addTag("http://hl7.org/fhir/tag", "urn:happytag", "This is a happy resource"); ResourceMetadataKeyEnum.TAG_LIST.put(p1, list); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); - client.create(p1); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); + client.create().resource(p1).execute(); client.setLogRequestAndResponse(true); - client.create(p1); + client.create().resource(p1).execute(); }