diff --git a/hapi-fhir-jpaserver-migrate/pom.xml b/hapi-fhir-jpaserver-migrate/pom.xml index 3eff9239bdb..57dc5d89480 100644 --- a/hapi-fhir-jpaserver-migrate/pom.xml +++ b/hapi-fhir-jpaserver-migrate/pom.xml @@ -61,9 +61,8 @@ - com.intellij + org.jetbrains annotations - 12.0 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 0b8c67b5eac..8316cfcd24a 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 @@ -13,6 +13,7 @@ import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4; import ca.uhn.fhir.jpa.provider.r4.TerminologyUploaderProviderR4; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; +import ca.uhn.fhir.jpa.util.ResourceProviderFactory; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.server.*; @@ -72,12 +73,12 @@ public class TestRestfulServer extends RestfulServer { // Depending on the version this server is supporing, we will // retrieve all the appropriate resource providers and the // conformance provider - List beans; + ResourceProviderFactory beans; @SuppressWarnings("rawtypes") IFhirSystemDao systemDao; ETagSupportEnum etagSupport; String baseUrlProperty; - List plainProviders = new ArrayList(); + List providers = new ArrayList<>(); switch (fhirVersionParam.trim().toUpperCase()) { case "TDL2": @@ -94,8 +95,8 @@ public class TestRestfulServer extends RestfulServer { } myAppCtx.refresh(); setFhirContext(FhirContext.forDstu2()); - beans = myAppCtx.getBean("myResourceProvidersDstu2", List.class); - plainProviders.add(myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class)); + beans = myAppCtx.getBean("myResourceProvidersDstu2", ResourceProviderFactory.class); + providers.add(myAppCtx.getBean("mySystemProviderDstu2", JpaSystemProviderDstu2.class)); systemDao = myAppCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class); etagSupport = ETagSupportEnum.ENABLED; JpaConformanceProviderDstu2 confProvider = new JpaConformanceProviderDstu2(this, systemDao, myAppCtx.getBean(DaoConfig.class)); @@ -117,14 +118,14 @@ public class TestRestfulServer extends RestfulServer { } myAppCtx.refresh(); setFhirContext(FhirContext.forDstu3()); - beans = myAppCtx.getBean("myResourceProvidersDstu3", List.class); - plainProviders.add(myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class)); + beans = myAppCtx.getBean("myResourceProvidersDstu3", ResourceProviderFactory.class); + providers.add(myAppCtx.getBean("mySystemProviderDstu3", JpaSystemProviderDstu3.class)); systemDao = myAppCtx.getBean("mySystemDaoDstu3", IFhirSystemDao.class); etagSupport = ETagSupportEnum.ENABLED; JpaConformanceProviderDstu3 confProvider = new JpaConformanceProviderDstu3(this, systemDao, myAppCtx.getBean(DaoConfig.class)); confProvider.setImplementationDescription(implDesc); setServerConformanceProvider(confProvider); - plainProviders.add(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); + providers.add(myAppCtx.getBean(TerminologyUploaderProviderDstu3.class)); break; } case "R4": { @@ -135,15 +136,15 @@ public class TestRestfulServer extends RestfulServer { baseUrlProperty = FHIR_BASEURL_R4; myAppCtx.refresh(); setFhirContext(FhirContext.forR4()); - beans = myAppCtx.getBean("myResourceProvidersR4", List.class); - plainProviders.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class)); + beans = myAppCtx.getBean("myResourceProvidersR4", ResourceProviderFactory.class); + providers.add(myAppCtx.getBean("mySystemProviderR4", JpaSystemProviderR4.class)); systemDao = myAppCtx.getBean("mySystemDaoR4", IFhirSystemDao.class); etagSupport = ETagSupportEnum.ENABLED; JpaConformanceProviderR4 confProvider = new JpaConformanceProviderR4(this, systemDao, myAppCtx.getBean(DaoConfig.class)); confProvider.setImplementationDescription(implDesc); setServerConformanceProvider(confProvider); - plainProviders.add(myAppCtx.getBean(TerminologyUploaderProviderR4.class)); - plainProviders.add(myAppCtx.getBean(GraphQLProvider.class)); + providers.add(myAppCtx.getBean(TerminologyUploaderProviderR4.class)); + providers.add(myAppCtx.getBean(GraphQLProvider.class)); break; } default: @@ -166,12 +167,8 @@ public class TestRestfulServer extends RestfulServer { * operations in this server) are all retrieved from the spring context above * and are provided to the server here. */ - for (IResourceProvider nextResourceProvider : beans) { - ourLog.info(" * Have resource provider for: {}", nextResourceProvider.getResourceType().getSimpleName()); - } - setResourceProviders(beans); - - registerProviders(plainProviders); + registerProviders(beans.createProviders()); + registerProviders(providers); /* * Enable CORS diff --git a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/model/Factory.java b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/model/Factory.java index d55ab23903e..3f8e6209b8b 100644 --- a/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/model/Factory.java +++ b/hapi-fhir-structures-r4/src/main/java/org/hl7/fhir/r4/model/Factory.java @@ -1,271 +1,273 @@ -package org.hl7.fhir.r4.model; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.text.ParseException; -import java.util.UUID; - -import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; -import org.hl7.fhir.r4.model.Narrative.NarrativeStatus; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.xhtml.XhtmlParser; - -/* -Copyright (c) 2011+, HL7, Inc -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of HL7 nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - - - -public class Factory { - - public static IdType newId(String value) { - if (value == null) - return null; - IdType res = new IdType(); - res.setValue(value); - return res; - } - - public static StringType newString_(String value) { - if (value == null) - return null; - StringType res = new StringType(); - res.setValue(value); - return res; - } - - public static UriType newUri(String value) throws URISyntaxException { - if (value == null) - return null; - UriType res = new UriType(); - res.setValue(value); - return res; - } - - public static UrlType newUrl(String value) throws URISyntaxException { - if (value == null) - return null; - UrlType res = new UrlType(); - res.setValue(value); - return res; - } - - public static CanonicalType newCanonical(String value) throws URISyntaxException { - if (value == null) - return null; - CanonicalType res = new CanonicalType(); - res.setValue(value); - return res; - } - - public static DateTimeType newDateTime(String value) throws ParseException { - if (value == null) - return null; - return new DateTimeType(value); - } - - public static DateType newDate(String value) throws ParseException { - if (value == null) - return null; - return new DateType(value); - } - - public static CodeType newCode(String value) { - if (value == null) - return null; - CodeType res = new CodeType(); - res.setValue(value); - return res; - } - - public static IntegerType newInteger(int value) { - IntegerType res = new IntegerType(); - res.setValue(value); - return res; - } - - public static IntegerType newInteger(java.lang.Integer value) { - if (value == null) - return null; - IntegerType res = new IntegerType(); - res.setValue(value); - return res; - } - - public static BooleanType newBoolean(boolean value) { - BooleanType res = new BooleanType(); - res.setValue(value); - return res; - } - - public static ContactPoint newContactPoint(ContactPointSystem system, String value) { - ContactPoint res = new ContactPoint(); - res.setSystem(system); - res.setValue(value); - return res; - } - - public static Extension newExtension(String uri, Type value, boolean evenIfNull) { - if (!evenIfNull && (value == null || value.isEmpty())) - return null; - Extension e = new Extension(); - e.setUrl(uri); - e.setValue(value); - return e; - } - - public static CodeableConcept newCodeableConcept(String code, String system, String display) { - CodeableConcept cc = new CodeableConcept(); - Coding c = new Coding(); - c.setCode(code); - c.setSystem(system); - c.setDisplay(display); - cc.getCoding().add(c); - return cc; - } - - public static Reference makeReference(String url) { - Reference rr = new Reference(); - rr.setReference(url); - return rr; - } - - public static Narrative newNarrative(NarrativeStatus status, String html) throws IOException, FHIRException { - Narrative n = new Narrative(); - n.setStatus(status); - try { - n.setDiv(new XhtmlParser().parseFragment("
"+Utilities.escapeXml(html)+"
")); - } catch (org.hl7.fhir.exceptions.FHIRException e) { - throw new FHIRException(e.getMessage(), e); - } - return n; - } - - public static Coding makeCoding(String code) throws FHIRException { - String[] parts = code.split("\\|"); - Coding c = new Coding(); - if (parts.length == 2) { - c.setSystem(parts[0]); - c.setCode(parts[1]); - } else if (parts.length == 3) { - c.setSystem(parts[0]); - c.setCode(parts[1]); - c.setDisplay(parts[2]); - } else - throw new FHIRException("Unable to understand the code '"+code+"'. Use the format system|code(|display)"); - return c; - } - - public static Reference makeReference(String url, String text) { - Reference rr = new Reference(); - rr.setReference(url); - if (!Utilities.noString(text)) - rr.setDisplay(text); - return rr; - } - - public static String createUUID() { - return "urn:uuid:"+UUID.randomUUID().toString().toLowerCase(); - } - - public Type create(String name) throws FHIRException { - if (name.equals("boolean")) - return new BooleanType(); - else if (name.equals("integer")) - return new IntegerType(); - else if (name.equals("decimal")) - return new DecimalType(); - else if (name.equals("base64Binary")) - return new Base64BinaryType(); - else if (name.equals("instant")) - return new InstantType(); - else if (name.equals("string")) - return new StringType(); - else if (name.equals("uri")) - return new UriType(); - else if (name.equals("url")) - return new UrlType(); - else if (name.equals("canonical")) - return new CanonicalType(); - else if (name.equals("date")) - return new DateType(); - else if (name.equals("dateTime")) - return new DateTimeType(); - else if (name.equals("time")) - return new TimeType(); - else if (name.equals("code")) - return new CodeType(); - else if (name.equals("oid")) - return new OidType(); - else if (name.equals("id")) - return new IdType(); - else if (name.equals("unsignedInt")) - return new UnsignedIntType(); - else if (name.equals("positiveInt")) - return new PositiveIntType(); - else if (name.equals("markdown")) - return new MarkdownType(); - else if (name.equals("Annotation")) - return new Annotation(); - else if (name.equals("Attachment")) - return new Attachment(); - else if (name.equals("Identifier")) - return new Identifier(); - else if (name.equals("CodeableConcept")) - return new CodeableConcept(); - else if (name.equals("Coding")) - return new Coding(); - else if (name.equals("Quantity")) - return new Quantity(); - else if (name.equals("Range")) - return new Range(); - else if (name.equals("Period")) - return new Period(); - else if (name.equals("Ratio")) - return new Ratio(); - else if (name.equals("SampledData")) - return new SampledData(); - else if (name.equals("Signature")) - return new Signature(); - else if (name.equals("HumanName")) - return new HumanName(); - else if (name.equals("Address")) - return new Address(); - else if (name.equals("ContactPoint")) - return new ContactPoint(); - else if (name.equals("Timing")) - return new Timing(); - else if (name.equals("Reference")) - return new Reference(); - else if (name.equals("Meta")) - return new Meta(); - else - throw new FHIRException("Unknown data type name "+name); - } -} +package org.hl7.fhir.r4.model; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.util.UUID; + +import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; +import org.hl7.fhir.r4.model.Narrative.NarrativeStatus; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.xhtml.XhtmlParser; + +/* +Copyright (c) 2011+, HL7, Inc +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of HL7 nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + + + +public class Factory { + + public static IdType newId(String value) { + if (value == null) + return null; + IdType res = new IdType(); + res.setValue(value); + return res; + } + + public static StringType newString_(String value) { + if (value == null) + return null; + StringType res = new StringType(); + res.setValue(value); + return res; + } + + public static UriType newUri(String value) throws URISyntaxException { + if (value == null) + return null; + UriType res = new UriType(); + res.setValue(value); + return res; + } + + public static UrlType newUrl(String value) throws URISyntaxException { + if (value == null) + return null; + UrlType res = new UrlType(); + res.setValue(value); + return res; + } + + public static CanonicalType newCanonical(String value) throws URISyntaxException { + if (value == null) + return null; + CanonicalType res = new CanonicalType(); + res.setValue(value); + return res; + } + + public static DateTimeType newDateTime(String value) throws ParseException { + if (value == null) + return null; + return new DateTimeType(value); + } + + public static DateType newDate(String value) throws ParseException { + if (value == null) + return null; + return new DateType(value); + } + + public static CodeType newCode(String value) { + if (value == null) + return null; + CodeType res = new CodeType(); + res.setValue(value); + return res; + } + + public static IntegerType newInteger(int value) { + IntegerType res = new IntegerType(); + res.setValue(value); + return res; + } + + public static IntegerType newInteger(java.lang.Integer value) { + if (value == null) + return null; + IntegerType res = new IntegerType(); + res.setValue(value); + return res; + } + + public static BooleanType newBoolean(boolean value) { + BooleanType res = new BooleanType(); + res.setValue(value); + return res; + } + + public static ContactPoint newContactPoint(ContactPointSystem system, String value) { + ContactPoint res = new ContactPoint(); + res.setSystem(system); + res.setValue(value); + return res; + } + + public static Extension newExtension(String uri, Type value, boolean evenIfNull) { + if (!evenIfNull && (value == null || value.isEmpty())) + return null; + Extension e = new Extension(); + e.setUrl(uri); + e.setValue(value); + return e; + } + + public static CodeableConcept newCodeableConcept(String code, String system, String display) { + CodeableConcept cc = new CodeableConcept(); + Coding c = new Coding(); + c.setCode(code); + c.setSystem(system); + c.setDisplay(display); + cc.getCoding().add(c); + return cc; + } + + public static Reference makeReference(String url) { + Reference rr = new Reference(); + rr.setReference(url); + return rr; + } + + public static Narrative newNarrative(NarrativeStatus status, String html) throws IOException, FHIRException { + Narrative n = new Narrative(); + n.setStatus(status); + try { + n.setDiv(new XhtmlParser().parseFragment("
"+Utilities.escapeXml(html)+"
")); + } catch (org.hl7.fhir.exceptions.FHIRException e) { + throw new FHIRException(e.getMessage(), e); + } + return n; + } + + public static Coding makeCoding(String code) throws FHIRException { + String[] parts = code.split("\\|"); + Coding c = new Coding(); + if (parts.length == 2) { + c.setSystem(parts[0]); + c.setCode(parts[1]); + } else if (parts.length == 3) { + c.setSystem(parts[0]); + c.setCode(parts[1]); + c.setDisplay(parts[2]); + } else + throw new FHIRException("Unable to understand the code '"+code+"'. Use the format system|code(|display)"); + return c; + } + + public static Reference makeReference(String url, String text) { + Reference rr = new Reference(); + rr.setReference(url); + if (!Utilities.noString(text)) + rr.setDisplay(text); + return rr; + } + + public static String createUUID() { + return "urn:uuid:"+UUID.randomUUID().toString().toLowerCase(); + } + + public Type create(String name) throws FHIRException { + if (name.equals("boolean")) + return new BooleanType(); + else if (name.equals("integer")) + return new IntegerType(); + else if (name.equals("decimal")) + return new DecimalType(); + else if (name.equals("base64Binary")) + return new Base64BinaryType(); + else if (name.equals("instant")) + return new InstantType(); + else if (name.equals("string")) + return new StringType(); + else if (name.equals("uri")) + return new UriType(); + else if (name.equals("url")) + return new UrlType(); + else if (name.equals("canonical")) + return new CanonicalType(); + else if (name.equals("date")) + return new DateType(); + else if (name.equals("dateTime")) + return new DateTimeType(); + else if (name.equals("time")) + return new TimeType(); + else if (name.equals("code")) + return new CodeType(); + else if (name.equals("oid")) + return new OidType(); + else if (name.equals("id")) + return new IdType(); + else if (name.equals("unsignedInt")) + return new UnsignedIntType(); + else if (name.equals("positiveInt")) + return new PositiveIntType(); + else if (name.equals("markdown")) + return new MarkdownType(); + else if (name.equals("Annotation")) + return new Annotation(); + else if (name.equals("Attachment")) + return new Attachment(); + else if (name.equals("Identifier")) + return new Identifier(); + else if (name.equals("CodeableConcept")) + return new CodeableConcept(); + else if (name.equals("Coding")) + return new Coding(); + else if (name.equals("Quantity")) + return new Quantity(); + else if (name.equals("Range")) + return new Range(); + else if (name.equals("Period")) + return new Period(); + else if (name.equals("Ratio")) + return new Ratio(); + else if (name.equals("SampledData")) + return new SampledData(); + else if (name.equals("Signature")) + return new Signature(); + else if (name.equals("HumanName")) + return new HumanName(); + else if (name.equals("Address")) + return new Address(); + else if (name.equals("ContactPoint")) + return new ContactPoint(); + else if (name.equals("Timing")) + return new Timing(); + else if (name.equals("Reference")) + return new Reference(); + else if (name.equals("Meta")) + return new Meta(); +// else if (name.equals("BackboneElement")) +// return new BackboneElement(); + else + throw new FHIRException("Unknown data type name "+name); + } +} diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/DefaultEnableWhenEvaluator.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/DefaultEnableWhenEvaluator.java index f3f9a3e0314..4a8b5af2037 100644 --- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/DefaultEnableWhenEvaluator.java +++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/DefaultEnableWhenEvaluator.java @@ -66,7 +66,10 @@ public class DefaultEnableWhenEvaluator implements IEnableWhenEvaluator { return new EnableWhenResult(result, linkId, enableCondition, questionnaireResponse); } - public Type convertToType(Element element) throws FHIRException { + private Type convertToType(Element element) throws FHIRException { + if (element.fhirType().equals("BackboneElement")) { + return null; + } Type b = new Factory().create(element.fhirType()); if (b instanceof PrimitiveType) { ((PrimitiveType) b).setValueAsString(element.primitiveValue()); @@ -92,6 +95,9 @@ public class DefaultEnableWhenEvaluator implements IEnableWhenEvaluator { } try { actualAnswer = convertToType(answer); + if (actualAnswer == null) { + return false; + } } catch (FHIRException e) { throw new UnprocessableEntityException("Unexpected answer type", e); } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java index e56936fe3fd..65c14acdcfe 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidatorDstu3Test.java @@ -342,6 +342,49 @@ public class FhirInstanceValidatorDstu3Test { } + @Test + public void testValidateQuestionnaireWithEnableWhenAndSubItems_ShouldNotBeEnabled() throws IOException { + CodeSystem csYesNo = loadResource("/dstu3/fmc01-cs-yesnounk.json", CodeSystem.class); + myCodeSystems.put(csYesNo.getUrl(), csYesNo); + CodeSystem csBinderRecommended = loadResource("/dstu3/fmc02-cs-binderrecomm.json", CodeSystem.class); + myCodeSystems.put(csBinderRecommended.getUrl(), csBinderRecommended); + ValueSet vsBinderRequired = loadResource("/dstu3/fmc02-vs-binderrecomm.json", ValueSet.class); + myValueSets.put(vsBinderRequired.getUrl(), vsBinderRequired); + myValueSets.put("ValueSet/" +vsBinderRequired.getIdElement().getIdPart(), vsBinderRequired); + ValueSet vsYesNo = loadResource("/dstu3/fmc01-vs-yesnounk.json", ValueSet.class); + myValueSets.put(vsYesNo.getUrl(), vsYesNo); + myValueSets.put("ValueSet/" + vsYesNo.getIdElement().getIdPart(), vsYesNo); + Questionnaire q = loadResource("/dstu3/fmc02-questionnaire.json", Questionnaire.class); + myQuestionnaires.put("Questionnaire/" + q.getIdElement().getIdPart(), q); + + QuestionnaireResponse qr = loadResource("/dstu3/fmc02-questionnaireresponse-01.json", QuestionnaireResponse.class); + ValidationResult result = myVal.validateWithResult(qr); + List errors = logResultsAndReturnNonInformationalOnes(result); + assertThat(errors.get(0).getMessage(), containsString("Item with linkId [BO_ConsDrop] has answer, even though it is not enabled")); + assertEquals(1, errors.size()); + } + + @Test + public void testValidateQuestionnaireWithEnableWhenAndSubItems_ShouldBeEnabled() throws IOException { + CodeSystem csYesNo = loadResource("/dstu3/fmc01-cs-yesnounk.json", CodeSystem.class); + myCodeSystems.put(csYesNo.getUrl(), csYesNo); + CodeSystem csBinderRecommended = loadResource("/dstu3/fmc02-cs-binderrecomm.json", CodeSystem.class); + myCodeSystems.put(csBinderRecommended.getUrl(), csBinderRecommended); + ValueSet vsBinderRequired = loadResource("/dstu3/fmc02-vs-binderrecomm.json", ValueSet.class); + myValueSets.put(vsBinderRequired.getUrl(), vsBinderRequired); + myValueSets.put("ValueSet/" +vsBinderRequired.getIdElement().getIdPart(), vsBinderRequired); + ValueSet vsYesNo = loadResource("/dstu3/fmc01-vs-yesnounk.json", ValueSet.class); + myValueSets.put(vsYesNo.getUrl(), vsYesNo); + myValueSets.put("ValueSet/" + vsYesNo.getIdElement().getIdPart(), vsYesNo); + Questionnaire q = loadResource("/dstu3/fmc02-questionnaire.json", Questionnaire.class); + myQuestionnaires.put("Questionnaire/" + q.getIdElement().getIdPart(), q); + + QuestionnaireResponse qr = loadResource("/dstu3/fmc02-questionnaireresponse-02.json", QuestionnaireResponse.class); + ValidationResult result = myVal.validateWithResult(qr); + List errors = logResultsAndReturnNonInformationalOnes(result); + assertThat(errors, empty()); + } + /** * See #872 */ diff --git a/hapi-fhir-validation/src/test/resources/dstu3/fmc02-cs-binderrecomm.json b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-cs-binderrecomm.json new file mode 100644 index 00000000000..345b6f50dbd --- /dev/null +++ b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-cs-binderrecomm.json @@ -0,0 +1,36 @@ +{ + "resourceType": "CodeSystem", + "id": "FMCBinderRecomm", + "meta": { + "versionId": "1", + "lastUpdated": "2019-04-27T19:40:17.693-04:00" + }, + "url": "http://fkcfhir.org/fhir/cs/FMCBinderRecomm", + "identifier": { + "value": "FMCBinderRecomm" + }, + "name": "FMCBinderRecomm", + "status": "active", + "publisher": "FMCNA", + "description": "CodeSystem for Binder Recommended", + "hierarchyMeaning": "grouped-by", + "content": "complete", + "concept": [ + { + "code": "Fosrenol", + "display": "Fosrenol" + }, + { + "code": "Velphoro", + "display": "Velphoro" + }, + { + "code": "Auryxia", + "display": "Auryxia" + }, + { + "code": "Renvela", + "display": "Renvela" + } + ] +} diff --git a/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaire.json b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaire.json new file mode 100644 index 00000000000..da6c11e2ad7 --- /dev/null +++ b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaire.json @@ -0,0 +1,44 @@ +{ + "resourceType": "Questionnaire", + "id": "FMCBinderOptimization", + "meta": { + "versionId": "1", + "lastUpdated": "2019-04-27T22:40:19.860-04:00" + }, + "name": "TestQ", + "item": [ + { + "linkId": "1", + "type": "group", + "item": [ + { + "linkId": "BO_RecCons", + "text": "Recommendation Consistent with binder optimization guidelines", + "type": "choice", + "options": { + "reference": "ValueSet/FMCYesNoUnk" + }, + "item": [ + { + "linkId": "BO_ConsDrop", + "text": "Binder Recommended", + "type": "choice", + "enableWhen": [ + { + "question": "BO_RecCons", + "answerCoding": { + "system": "http://fkcfhir.org/fhir/cs/FMCYesNoUnk", + "code": "Yes" + } + } + ], + "options": { + "reference": "ValueSet/FMCBinderRecomm" + } + } + ] + } + ] + } + ] +} diff --git a/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaireresponse-01.json b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaireresponse-01.json new file mode 100644 index 00000000000..36cfa5c26bb --- /dev/null +++ b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaireresponse-01.json @@ -0,0 +1,41 @@ +{ + "resourceType": "QuestionnaireResponse", + "id": "TestQR", + "questionnaire": { + "reference": "Questionnaire/FMCBinderOptimization" + }, + "status": "in-progress", + "item": [ + { + "linkId": "1", + "item": [ + { + "linkId": "BO_RecCons", + "text": "Recommendation Consistent with binder optimization guidelines", + "answer": [ + { + "valueCoding": { + "system": "http://fkcfhir.org/fhir/cs/FMCYesNoUnk", + "code": "No" + }, + "item": [ + { + "linkId": "BO_ConsDrop", + "text": "Binder Recommended", + "answer": [ + { + "valueCoding": { + "system": "http://fkcfhir.org/fhir/cs/FMCBinderRecomm", + "code": "Velphoro" + } + } + ] + } + ] + } + ] + } + ] + } + ] +} diff --git a/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaireresponse-02.json b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaireresponse-02.json new file mode 100644 index 00000000000..e8f71459e4b --- /dev/null +++ b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-questionnaireresponse-02.json @@ -0,0 +1,41 @@ +{ + "resourceType": "QuestionnaireResponse", + "id": "TestQR", + "questionnaire": { + "reference": "Questionnaire/FMCBinderOptimization" + }, + "status": "in-progress", + "item": [ + { + "linkId": "1", + "item": [ + { + "linkId": "BO_RecCons", + "text": "Recommendation Consistent with binder optimization guidelines", + "answer": [ + { + "valueCoding": { + "system": "http://fkcfhir.org/fhir/cs/FMCYesNoUnk", + "code": "Yes" + }, + "item": [ + { + "linkId": "BO_ConsDrop", + "text": "Binder Recommended", + "answer": [ + { + "valueCoding": { + "system": "http://fkcfhir.org/fhir/cs/FMCBinderRecomm", + "code": "Velphoro" + } + } + ] + } + ] + } + ] + } + ] + } + ] +} diff --git a/hapi-fhir-validation/src/test/resources/dstu3/fmc02-vs-binderrecomm.json b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-vs-binderrecomm.json new file mode 100644 index 00000000000..660f6869d59 --- /dev/null +++ b/hapi-fhir-validation/src/test/resources/dstu3/fmc02-vs-binderrecomm.json @@ -0,0 +1,26 @@ +{ + "resourceType": "ValueSet", + "id": "FMCBinderRecomm", + "meta": { + "versionId": "1", + "lastUpdated": "2019-04-27T19:42:40.566-04:00" + }, + "url": "http://fkcfhir.org/fhir/vs/FMCBinderRecomm", + "identifier": [ + { + "value": "FMCBinderRecomm" + } + ], + "name": "FMCBinderRecomm", + "title": "Binder Recommended", + "status": "active", + "publisher": "FMCNA", + "description": "ValueSet for Binder Recommended Choice", + "compose": { + "include": [ + { + "system": "http://fkcfhir.org/fhir/cs/FMCBinderRecomm" + } + ] + } +} diff --git a/pom.xml b/pom.xml index cb312c07a82..9aec2e68043 100755 --- a/pom.xml +++ b/pom.xml @@ -726,6 +726,11 @@ commons-compress 1.18 + + org.jetbrains + annotations + 16.0.3 + commons-io commons-io diff --git a/src/changes/changes.xml b/src/changes/changes.xml index fd87aa39108..caac7ee6a06 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -190,6 +190,10 @@ Expunges are now done in batches in multiple threads. Both the number of expunge threads and batch size are configurable in DaoConfig. + + Validation errors were fixed when using a Questionnaire with enableWhen on a question that + contains sub-items. +