diff --git a/README.md b/README.md index e2756320bc1..8dbce63a151 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ HAPI FHIR - Java API for HL7 FHIR Clients and Servers [![Coverage Status](https://coveralls.io/repos/jamesagnew/hapi-fhir/badge.svg?branch=master&service=github)](https://coveralls.io/github/jamesagnew/hapi-fhir?branch=master) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/ca.uhn.hapi.fhir/hapi-fhir-base/badge.svg)](http://search.maven.org/#search|ga|1|ca.uhn.hapi.fhir) [![Dependency Status](https://www.versioneye.com/user/projects/55e1d0d9c6d8f2001c00043e/badge.svg?style=flat)](https://www.versioneye.com/user/projects/55e1d0d9c6d8f2001c00043e) -[![License](https://img.shields.io/badge/license-apache%202.0-ff69b4.svg)](https://github.com/jamesagnew/hapi-fhir/blob/master/LICENSE.txt) +[![License](https://img.shields.io/badge/license-apache%202.0-ff69b4.svg)](http://jamesagnew.github.io/hapi-fhir/license.html) Complete project documentation is available here: http://jamesagnew.github.io/hapi-fhir/ diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java index ad47f2feb5f..740957b517f 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/interceptor/LoggingInterceptor.java @@ -152,7 +152,7 @@ public class LoggingInterceptor implements IClientInterceptor { throw new InternalErrorException(e); } - myLog.info("Client response body:\n{}", new String(bytes)); + myLog.info("Client response body:\n{}", new String(bytes, "UTF-8")); theResponse.setEntity(new MyEntityWrapper(respEntity, bytes)); } else { myLog.info("Client response body: (none)"); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java index e592a78a3a0..264a9b77e9a 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java @@ -50,7 +50,6 @@ import org.codehaus.stax2.XMLOutputFactory2; import org.codehaus.stax2.io.EscapingWriterFactory; import com.ctc.wstx.api.WstxInputProperties; -import com.ctc.wstx.stax.WstxInputFactory; import com.ctc.wstx.stax.WstxOutputFactory; /** @@ -1550,6 +1549,7 @@ public class XmlUtil { if (ourInputFactory == null) { try { + // Detect if we're running with the Android lib, and force repackaged Woodstox to be used Class.forName("ca.uhn.fhir.repackage.javax.xml.stream.XMLInputFactory"); System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory"); } catch (ClassNotFoundException e) { @@ -1589,6 +1589,7 @@ public class XmlUtil { if (ourOutputFactory == null) { try { + // Detect if we're running with the Android lib, and force repackaged Woodstox to be used Class.forName("ca.uhn.fhir.repackage.javax.xml.stream.XMLOutputFactory"); System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory"); } catch (ClassNotFoundException e) { @@ -1708,7 +1709,7 @@ public class XmlUtil { @Override public Writer createEscapingWriterFor(OutputStream theOut, String theEnc) throws UnsupportedEncodingException { - return createEscapingWriterFor(new OutputStreamWriter(theOut), theEnc); + return createEscapingWriterFor(new OutputStreamWriter(theOut, theEnc), theEnc); } @Override diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java index cdd79782320..f6ac7af53cf 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java @@ -38,6 +38,7 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; +import org.apache.commons.io.IOUtils; import org.apache.commons.io.input.BOMInputStream; import org.hl7.fhir.instance.model.api.IBaseResource; import org.w3c.dom.ls.LSInput; @@ -203,6 +204,7 @@ class SchemaBaseValidator implements IValidatorModule { InputStream baseIs = FhirValidator.class.getResourceAsStream(pathToBase); if (baseIs == null) { + IOUtils.closeQuietly(baseIs); throw new InternalErrorException("Schema file not found: " + pathToBase); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchematronBaseValidator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchematronBaseValidator.java index 18d1c095d43..9e97c413a34 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchematronBaseValidator.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchematronBaseValidator.java @@ -28,6 +28,7 @@ import java.util.Map; import javax.xml.transform.stream.StreamSource; +import org.apache.commons.io.IOUtils; import org.hl7.fhir.instance.model.api.IBaseResource; import org.oclc.purl.dsdl.svrl.SchematronOutputType; @@ -120,12 +121,14 @@ public class SchematronBaseValidator implements IValidatorModule { return retVal; } - String pathToBase = myCtx.getVersion().getPathToSchemaDefinitions() + '/' + theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getName().toLowerCase() - + ".sch"; + String pathToBase = myCtx.getVersion().getPathToSchemaDefinitions() + '/' + theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getName().toLowerCase() + ".sch"; InputStream baseIs = FhirValidator.class.getResourceAsStream(pathToBase); - if (baseIs == null) { - throw new InternalErrorException("No schematron found for resource type: " - + theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getImplementingClass().getCanonicalName()); + try { + if (baseIs == null) { + throw new InternalErrorException("No schematron found for resource type: " + theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getImplementingClass().getCanonicalName()); + } + } finally { + IOUtils.closeQuietly(baseIs); } retVal = SchematronResourceSCH.fromClassPath(pathToBase); diff --git a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java index d1d5ed313ff..a1188da2ff6 100644 --- a/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java +++ b/hapi-fhir-structures-dstu2/src/main/java/ca/uhn/fhir/rest/server/provider/dstu2/ServerConformanceProvider.java @@ -160,7 +160,7 @@ public class ServerConformanceProvider implements IServerConformanceProvider" + + "" + + ""; + //@formatter:on + + ValidationResult output = myVal.validateWithResult(input); + assertEquals(output.toString(), 0, output.getMessages().size()); + } + + @Test + public void testValidateRawXmlResourceBadAttributes() { + // @formatter:off + String input = "" + "" + "" + + ""; + // @formatter:on + + ValidationResult output = myVal.validateWithResult(input); + assertEquals(output.toString(), 1, output.getMessages().size()); + ourLog.info(output.getMessages().get(0).getLocationString()); + ourLog.info(output.getMessages().get(0).getMessage()); + assertEquals("/f:Patient/f:foo", output.getMessages().get(0).getLocationString()); + assertEquals("Element is unknown or does not match any slice", output.getMessages().get(0).getMessage()); + } + @Test public void testValidateResourceFailingInvariant() { Observation input = new Observation(); @@ -158,6 +199,68 @@ public class FhirInstanceValidatorTest { } + @Test + public void testValidateResourceContainingProfileDeclarationDoesntResolve() { + addValidConcept("http://loinc.org", "12345"); + + Observation input = new Observation(); + input.getMeta().addProfile("http://foo/myprofile"); + + input.getCode().addCoding().setSystem("http://loinc.org").setCode("12345"); + input.setStatus(ObservationStatus.FINAL); + + myInstanceVal.setValidationSupport(myMockSupport); + ValidationResult output = myVal.validateWithResult(input); + List errors = logResultsAndReturnNonInformationalOnes(output); + assertEquals(errors.toString(), 1, errors.size()); + assertEquals("StructureDefinition reference \"http://foo/myprofile\" could not be resolved", errors.get(0).getMessage()); + } + + @Test + public void testValidateResourceContainingProfileDeclaration() { + addValidConcept("http://loinc.org", "12345"); + + Observation input = new Observation(); + input.getMeta().addProfile("http://hl7.org/fhir/StructureDefinition/devicemetricobservation"); + + input.addIdentifier().setSystem("http://acme").setValue("12345"); + input.getEncounter().setReference("http://foo.com/Encounter/9"); + input.setStatus(ObservationStatus.FINAL); + input.getCode().addCoding().setSystem("http://loinc.org").setCode("12345"); + + myInstanceVal.setValidationSupport(myMockSupport); + ValidationResult output = myVal.validateWithResult(input); + List errors = logResultsAndReturnNonInformationalOnes(output); + + assertThat(errors.toString(), containsString("Element '/f:Observation.subject': minimum required = 1, but only found 0")); + assertThat(errors.toString(), containsString("Element encounter @ /f:Observation: max allowed = 0, but found 1")); + assertThat(errors.toString(), containsString("Element '/f:Observation.device': minimum required = 1, but only found 0")); + assertThat(errors.toString(), containsString("")); + } + + @Test + public void testValidateResourceWithDefaultValueset() { + Observation input = new Observation(); + + input.setStatus(ObservationStatus.FINAL); + input.getCode().setText("No code here!"); + + ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(input)); + + ValidationResult output = myVal.validateWithResult(input); + assertEquals(output.getMessages().size(), 0); + } + + @Test + public void testValidateResourceWithDefaultValuesetBadCode() { + String input = "\n" + " \n" + + " \n" + " \n" + " \n" + ""; + ValidationResult output = myVal.validateWithResult(input); + assertEquals( + "Coded value notvalidcode is not in value set http://hl7.org/fhir/ValueSet/observation-status (http://hl7.org/fhir/ValueSet/observation-status)", + output.getMessages().get(0).getMessage()); + } + @Test public void testValidateResourceWithExampleBindingCodeValidationFailing() { Observation input = new Observation(); @@ -188,52 +291,4 @@ public class FhirInstanceValidatorTest { List errors = logResultsAndReturnNonInformationalOnes(output); assertEquals(errors.toString(), 0, errors.size()); } - - @Test - public void testValidateResourceWithDefaultValueset() { - Observation input = new Observation(); - - input.setStatus(ObservationStatus.FINAL); - input.getCode().setText("No code here!"); - - ourLog.info(ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(input)); - - ValidationResult output = myVal.validateWithResult(input); - assertEquals(output.getMessages().size(), 0); - } - - @Test - public void testValidateResourceWithDefaultValuesetBadCode() { - String input = "\n" + " \n" - + " \n" + " \n" + " \n" + ""; - ValidationResult output = myVal.validateWithResult(input); - assertEquals( - "Coded value notvalidcode is not in value set http://hl7.org/fhir/ValueSet/observation-status (http://hl7.org/fhir/ValueSet/observation-status)", - output.getMessages().get(0).getMessage()); - } - - @Test - public void testValidateXmlResource() { - // @formatter:off - String input = "" + "" + ""; - // @formatter:on - - ValidationResult output = myVal.validateWithResult(input); - assertEquals(output.toString(), 0, output.getMessages().size()); - } - - @Test - public void testValidateXmlResourceBadAttributes() { - // @formatter:off - String input = "" + "" + "" - + ""; - // @formatter:on - - ValidationResult output = myVal.validateWithResult(input); - assertEquals(output.toString(), 1, output.getMessages().size()); - ourLog.info(output.getMessages().get(0).getLocationString()); - ourLog.info(output.getMessages().get(0).getMessage()); - assertEquals("/f:Patient/f:foo", output.getMessages().get(0).getLocationString()); - assertEquals("Element is unknown or does not match any slice", output.getMessages().get(0).getMessage()); - } } diff --git a/pom.xml b/pom.xml index c496db99a7f..ce78e3f5f9f 100644 --- a/pom.xml +++ b/pom.xml @@ -783,9 +783,11 @@ + @@ -1164,7 +1166,9 @@ hapi-fhir-structures-dstu2 hapi-fhir-structures-hl7org-dstu2 hapi-fhir-jpaserver-base + examples diff --git a/src/site/site.xml b/src/site/site.xml index 438dc874a46..fdcb85d98ae 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -137,10 +137,9 @@ - + - - + diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index 2c164f93b19..1c6a1451793 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -24,6 +24,8 @@ Maven Central
VersionEye +
+ Apache 2.0 Licensed