Extension domains configuration for the fhr instance validator (#917)
* Fix the url of the StructureDefinition extensions http://hl7.org/fhir/tools/StructureDefinition/ -> http://hl7.org/fhir/StructureDefinition/ That makes the entry for the structuredefinition-expression superfluous. The url behind IG_DEPENDSON_PACKAGE_EXTENSION does not point is not (yet?) valid too. * Add ability to configure custom extension domains. * Testing the extension domains configuration * Fix obvious bug when determining resource name The for loop was completely superfluous beforehand. Either fix it as e.g. in this patch or remove it. * small improvements and TODO's for possible NPE's - javadoc see - use diamond operator for generics - remove throws clause when exception is not thrown - add TODO's for some cases a NPE might occur. My knowledge of the context is not sufficient to suggest the proper way to solve this.
This commit is contained in:
parent
1afe36e60a
commit
89ede0e524
|
@ -60,6 +60,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
private IValidationSupport myValidationSupport;
|
||||
private boolean noTerminologyChecks = false;
|
||||
private volatile WorkerContextWrapper myWrappedWorkerContext;
|
||||
private List<String> extensionDomains = Collections.emptyList();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -81,18 +82,52 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
myValidationSupport = theValidationSupport;
|
||||
}
|
||||
|
||||
private String determineResourceName(Document theDocument) {
|
||||
Element root = null;
|
||||
/**
|
||||
* Every element in a resource or data type includes an optional <it>extension</it> child element
|
||||
* which is identified by it's {@code url attribute}. There exists a number of predefined
|
||||
* extension urls or extension domains:<ul>
|
||||
* <li>any url which contains {@code example.org}, {@code nema.org}, or {@code acme.com}.</li>
|
||||
* <li>any url which starts with {@code http://hl7.org/fhir/StructureDefinition/}.</li>
|
||||
* </ul>
|
||||
* It is possible to extend this list of known extension by defining custom extensions:
|
||||
* Any url which starts which one of the elements in the list of custom extension domains is
|
||||
* considered as known.
|
||||
* <p>
|
||||
* Any unknown extension domain will result in an information message when validating a resource.
|
||||
* </p>
|
||||
*/
|
||||
public FhirInstanceValidator setCustomExtensionDomains(List<String> extensionDomains) {
|
||||
this.extensionDomains = extensionDomains;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every element in a resource or data type includes an optional <it>extension</it> child element
|
||||
* which is identified by it's {@code url attribute}. There exists a number of predefined
|
||||
* extension urls or extension domains:<ul>
|
||||
* <li>any url which contains {@code example.org}, {@code nema.org}, or {@code acme.com}.</li>
|
||||
* <li>any url which starts with {@code http://hl7.org/fhir/StructureDefinition/}.</li>
|
||||
* </ul>
|
||||
* It is possible to extend this list of known extension by defining custom extensions:
|
||||
* Any url which starts which one of the elements in the list of custom extension domains is
|
||||
* considered as known.
|
||||
* <p>
|
||||
* Any unknown extension domain will result in an information message when validating a resource.
|
||||
* </p>
|
||||
*/
|
||||
public FhirInstanceValidator setCustomExtensionDomains(String... extensionDomains) {
|
||||
this.extensionDomains = Arrays.asList(extensionDomains);
|
||||
return this;
|
||||
}
|
||||
|
||||
private String determineResourceName(Document theDocument) {
|
||||
NodeList list = theDocument.getChildNodes();
|
||||
for (int i = 0; i < list.getLength(); i++) {
|
||||
if (list.item(i) instanceof Element) {
|
||||
root = (Element) list.item(i);
|
||||
break;
|
||||
return list.item(i).getLocalName();
|
||||
}
|
||||
}
|
||||
root = theDocument.getDocumentElement();
|
||||
return root.getLocalName();
|
||||
return theDocument.getDocumentElement().getLocalName();
|
||||
}
|
||||
|
||||
private ArrayList<String> determineIfProfilesSpecified(Document theDocument) {
|
||||
|
@ -138,7 +173,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
* guielines will be ignored.
|
||||
* </p>
|
||||
*
|
||||
* @see {@link #setBestPracticeWarningLevel(BestPracticeWarningLevel)}
|
||||
* @see #setBestPracticeWarningLevel(BestPracticeWarningLevel)
|
||||
*/
|
||||
public BestPracticeWarningLevel getBestPracticeWarningLevel() {
|
||||
return myBestPracticeWarningLevel;
|
||||
|
@ -235,6 +270,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
v.setAnyExtensionsAllowed(isAnyExtensionsAllowed());
|
||||
v.setResourceIdRule(IdStatus.OPTIONAL);
|
||||
v.setNoTerminologyChecks(isNoTerminologyChecks());
|
||||
v.addExtensionDomains(extensionDomains);
|
||||
|
||||
List<ValidationMessage> messages = new ArrayList<>();
|
||||
|
||||
|
@ -343,7 +379,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
private LoadingCache<ResourceKey, org.hl7.fhir.r4.model.Resource> myFetchResourceCache;
|
||||
private org.hl7.fhir.r4.model.Parameters myExpansionProfile;
|
||||
|
||||
public WorkerContextWrapper(HapiWorkerContext theWorkerContext) {
|
||||
WorkerContextWrapper(HapiWorkerContext theWorkerContext) {
|
||||
myWrap = theWorkerContext;
|
||||
myConverter = new VersionConvertor_30_40();
|
||||
|
||||
|
@ -424,7 +460,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
}
|
||||
|
||||
@Override
|
||||
public void cacheResource(org.hl7.fhir.r4.model.Resource res) throws FHIRException {
|
||||
public void cacheResource(org.hl7.fhir.r4.model.Resource res) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -446,7 +482,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
|
||||
@Override
|
||||
public ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r4.model.ValueSet source, boolean cacheOk, boolean heiarchical) {
|
||||
ValueSet convertedSource = null;
|
||||
ValueSet convertedSource;
|
||||
try {
|
||||
convertedSource = VersionConvertor_30_40.convertValueSet(source);
|
||||
} catch (FHIRException e) {
|
||||
|
@ -470,7 +506,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
}
|
||||
|
||||
@Override
|
||||
public ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heiarchical) throws FHIRException {
|
||||
public ValueSetExpander.ValueSetExpansionOutcome expandVS(org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heiarchical) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -637,7 +673,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
}
|
||||
|
||||
@Override
|
||||
public IResourceValidator newValidator() throws FHIRException {
|
||||
public IResourceValidator newValidator() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -662,7 +698,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSystem(String system) throws TerminologyServiceException {
|
||||
public boolean supportsSystem(String system) {
|
||||
return myWrap.supportsSystem(system);
|
||||
}
|
||||
|
||||
|
@ -679,6 +715,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
@Override
|
||||
public ValidationResult validateCode(String system, String code, String display) {
|
||||
org.hl7.fhir.dstu3.context.IWorkerContext.ValidationResult result = myWrap.validateCode(system, code, display);
|
||||
// TODO: converted code might be null -> NPE
|
||||
return convertValidationResult(result);
|
||||
}
|
||||
|
||||
|
@ -729,6 +766,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
||||
// TODO: converted code might be null -> NPE
|
||||
org.hl7.fhir.dstu3.context.IWorkerContext.ValidationResult result = myWrap.validateCode(convertedCode, convertedVs);
|
||||
return convertValidationResult(result);
|
||||
}
|
||||
|
@ -749,6 +787,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
throw new InternalErrorException(e);
|
||||
}
|
||||
|
||||
// TODO: converted code might be null -> NPE
|
||||
org.hl7.fhir.dstu3.context.IWorkerContext.ValidationResult result = myWrap.validateCode(convertedCode, convertedVs);
|
||||
return convertValidationResult(result);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||
import java.io.StringReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -45,6 +46,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
private DocumentBuilderFactory myDocBuilderFactory;
|
||||
private boolean myNoTerminologyChecks;
|
||||
private StructureDefinition myStructureDefintion;
|
||||
private List<String> extensionDomains = Collections.emptyList();
|
||||
|
||||
private IValidationSupport myValidationSupport;
|
||||
|
||||
|
@ -68,18 +70,52 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
myValidationSupport = theValidationSupport;
|
||||
}
|
||||
|
||||
private String determineResourceName(Document theDocument) {
|
||||
Element root = null;
|
||||
/**
|
||||
* Every element in a resource or data type includes an optional <it>extension</it> child element
|
||||
* which is identified by it's {@code url attribute}. There exists a number of predefined
|
||||
* extension urls or extension domains:<ul>
|
||||
* <li>any url which contains {@code example.org}, {@code nema.org}, or {@code acme.com}.</li>
|
||||
* <li>any url which starts with {@code http://hl7.org/fhir/StructureDefinition/}.</li>
|
||||
* </ul>
|
||||
* It is possible to extend this list of known extension by defining custom extensions:
|
||||
* Any url which starts which one of the elements in the list of custom extension domains is
|
||||
* considered as known.
|
||||
* <p>
|
||||
* Any unknown extension domain will result in an information message when validating a resource.
|
||||
* </p>
|
||||
*/
|
||||
public FhirInstanceValidator setCustomExtensionDomains(List<String> extensionDomains) {
|
||||
this.extensionDomains = extensionDomains;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every element in a resource or data type includes an optional <it>extension</it> child element
|
||||
* which is identified by it's {@code url attribute}. There exists a number of predefined
|
||||
* extension urls or extension domains:<ul>
|
||||
* <li>any url which contains {@code example.org}, {@code nema.org}, or {@code acme.com}.</li>
|
||||
* <li>any url which starts with {@code http://hl7.org/fhir/StructureDefinition/}.</li>
|
||||
* </ul>
|
||||
* It is possible to extend this list of known extension by defining custom extensions:
|
||||
* Any url which starts which one of the elements in the list of custom extension domains is
|
||||
* considered as known.
|
||||
* <p>
|
||||
* Any unknown extension domain will result in an information message when validating a resource.
|
||||
* </p>
|
||||
*/
|
||||
public FhirInstanceValidator setCustomExtensionDomains(String... extensionDomains) {
|
||||
this.extensionDomains = Arrays.asList(extensionDomains);
|
||||
return this;
|
||||
}
|
||||
|
||||
private String determineResourceName(Document theDocument) {
|
||||
NodeList list = theDocument.getChildNodes();
|
||||
for (int i = 0; i < list.getLength(); i++) {
|
||||
if (list.item(i) instanceof Element) {
|
||||
root = (Element) list.item(i);
|
||||
break;
|
||||
return list.item(i).getLocalName();
|
||||
}
|
||||
}
|
||||
root = theDocument.getDocumentElement();
|
||||
return root.getLocalName();
|
||||
return theDocument.getDocumentElement().getLocalName();
|
||||
}
|
||||
|
||||
private ArrayList<String> determineIfProfilesSpecified(Document theDocument) {
|
||||
|
@ -120,8 +156,8 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
* reported at the ERROR level. If this setting is set to {@link BestPracticeWarningLevel#Ignore}, best practice
|
||||
* guielines will be ignored.
|
||||
* </p>
|
||||
*
|
||||
* @see {@link #setBestPracticeWarningLevel(BestPracticeWarningLevel)}
|
||||
*
|
||||
* @see #setBestPracticeWarningLevel(BestPracticeWarningLevel)
|
||||
*/
|
||||
public BestPracticeWarningLevel getBestPracticeWarningLevel() {
|
||||
return myBestPracticeWarningLevel;
|
||||
|
@ -211,8 +247,9 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
v.setAnyExtensionsAllowed(isAnyExtensionsAllowed());
|
||||
v.setResourceIdRule(IdStatus.OPTIONAL);
|
||||
v.setNoTerminologyChecks(isNoTerminologyChecks());
|
||||
v.addExtensionDomains(extensionDomains);
|
||||
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
List<ValidationMessage> messages = new ArrayList<>();
|
||||
|
||||
if (theEncoding == EncodingEnum.XML) {
|
||||
Document document;
|
||||
|
@ -312,7 +349,7 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
public static class NullEvaluationContext implements IEvaluationContext {
|
||||
|
||||
@Override
|
||||
public TypeDetails checkFunction(Object theAppContext, String theFunctionName, List<TypeDetails> theParameters) throws PathEngineException {
|
||||
public TypeDetails checkFunction(Object theAppContext, String theFunctionName, List<TypeDetails> theParameters) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -327,12 +364,12 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IValid
|
|||
}
|
||||
|
||||
@Override
|
||||
public Base resolveConstant(Object theAppContext, String theName) throws PathEngineException {
|
||||
public Base resolveConstant(Object theAppContext, String theName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeDetails resolveConstantType(Object theAppContext, String theName) throws PathEngineException {
|
||||
public TypeDetails resolveConstantType(Object theAppContext, String theName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -416,8 +416,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
private boolean allowUnknownExtension(String url) {
|
||||
if (url.contains("example.org") || url.contains("acme.com") || url.contains("nema.org") || url.startsWith("http://hl7.org/fhir/tools/StructureDefinition/") || url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-expression"))
|
||||
// Added structuredefinition-expression explicitly because it wasn't defined in the version of the spec it needs to be used with
|
||||
if (isPredefinedExtension(url))
|
||||
return true;
|
||||
for (String s : extensionDomains)
|
||||
if (url.startsWith(s))
|
||||
|
@ -426,8 +425,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
private boolean isKnownExtension(String url) {
|
||||
// Added structuredefinition-expression and following extensions explicitly because they weren't defined in the version of the spec they need to be used with
|
||||
if (url.contains("example.org") || url.contains("acme.com") || url.contains("nema.org") || url.startsWith("http://hl7.org/fhir/tools/StructureDefinition/") || url.equals("http://hl7.org/fhir/StructureDefinition/structuredefinition-expression") || url.equals(VersionConvertorConstants.IG_DEPENDSON_PACKAGE_EXTENSION))
|
||||
if (isPredefinedExtension(url))
|
||||
return true;
|
||||
for (String s : extensionDomains)
|
||||
if (url.startsWith(s))
|
||||
|
@ -435,6 +433,14 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return false;
|
||||
}
|
||||
|
||||
private boolean isPredefinedExtension(String url) {
|
||||
return url.contains("example.org")
|
||||
|| url.contains("acme.com")
|
||||
|| url.contains("nema.org")
|
||||
|| url.startsWith("http://hl7.org/fhir/StructureDefinition/")
|
||||
|| url.equals(VersionConvertorConstants.IG_DEPENDSON_PACKAGE_EXTENSION);
|
||||
}
|
||||
|
||||
private void bpCheck(List<ValidationMessage> errors, IssueType invalid, int line, int col, String literalPath, boolean test, String message) {
|
||||
if (bpWarnings != null) {
|
||||
switch (bpWarnings) {
|
||||
|
@ -1950,6 +1956,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return extensionDomains;
|
||||
}
|
||||
|
||||
public InstanceValidator addExtensionDomains(List<String> extensionDomains) {
|
||||
this.extensionDomains.addAll(extensionDomains);
|
||||
return this;
|
||||
}
|
||||
|
||||
private Element getFromBundle(Element bundle, String ref, String fullUrl, List<ValidationMessage> errors, String path) {
|
||||
String targetUrl = null;
|
||||
String version = "";
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
package org.hl7.fhir.dstu3.hapi.validation;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.dstu3.model.Questionnaire;
|
||||
import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class QuestionnaireValidatorDstu3Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(QuestionnaireValidatorDstu3Test.class);
|
||||
private static DefaultProfileValidationSupport myDefaultValidationSupport = new DefaultProfileValidationSupport();
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
private FhirInstanceValidator myInstanceVal;
|
||||
private FhirValidator myVal;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
IValidationSupport myValSupport = mock(IValidationSupport.class);
|
||||
|
||||
myVal = ourCtx.newValidator();
|
||||
myVal.setValidateAgainstStandardSchema(false);
|
||||
myVal.setValidateAgainstStandardSchematron(false);
|
||||
|
||||
ValidationSupportChain validationSupport = new ValidationSupportChain(myValSupport, myDefaultValidationSupport);
|
||||
myInstanceVal = new FhirInstanceValidator(validationSupport);
|
||||
|
||||
myVal.registerValidatorModule(myInstanceVal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuestionnaireWithPredefinedExtensionDomainsForCoding() {
|
||||
String[] extensionDomainsToTest = new String[] {
|
||||
"http://example.org/questionnaire-color-control-1",
|
||||
"https://example.org/questionnaire-color-control-2",
|
||||
"http://acme.com/questionnaire-color-control-3",
|
||||
"https://acme.com/questionnaire-color-control-4",
|
||||
"http://nema.org/questionnaire-color-control-5",
|
||||
"https://nema.org/questionnaire-color-control-6",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-scoreItem",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-expression",
|
||||
};
|
||||
for (String extensionDomainToTest : extensionDomainsToTest) {
|
||||
Questionnaire q = new Questionnaire();
|
||||
q.setStatus(PublicationStatus.ACTIVE)
|
||||
.addItem()
|
||||
.setLinkId("link0")
|
||||
.setType(QuestionnaireItemType.STRING)
|
||||
.addExtension()
|
||||
.setUrl(extensionDomainToTest)
|
||||
.setValue(new Coding(null, "text-box", null));
|
||||
|
||||
ValidationResult errors = myVal.validateWithResult(q);
|
||||
ourLog.info(errors.toString());
|
||||
assertThat(errors.isSuccessful(), Matchers.is(true));
|
||||
assertThat(errors.getMessages(), Matchers.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuestionnaireWithPredefinedExtensionDomainsForCodeableConcept() {
|
||||
String[] extensionDomainsToTest = new String[] {
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
|
||||
};
|
||||
for (String extensionDomainToTest : extensionDomainsToTest) {
|
||||
Questionnaire q = new Questionnaire();
|
||||
q.setStatus(PublicationStatus.ACTIVE)
|
||||
.addItem()
|
||||
.setLinkId("link0")
|
||||
.setType(QuestionnaireItemType.STRING)
|
||||
.addExtension()
|
||||
.setUrl(extensionDomainToTest)
|
||||
.setValue(new CodeableConcept().addCoding(new Coding(null, "text-box", null)));
|
||||
|
||||
ValidationResult errors = myVal.validateWithResult(q);
|
||||
ourLog.info(errors.toString());
|
||||
assertThat(errors.isSuccessful(), Matchers.is(true));
|
||||
assertThat(errors.getMessages(), Matchers.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuestionnaireWithCustomExtensionDomain() {
|
||||
Questionnaire q = new Questionnaire();
|
||||
String extensionUrl = "http://my.own.domain/StructureDefinition/";
|
||||
q.setStatus(PublicationStatus.ACTIVE)
|
||||
.addItem()
|
||||
.setLinkId("link0")
|
||||
.setType(QuestionnaireItemType.STRING)
|
||||
.addExtension()
|
||||
.setUrl(extensionUrl + "questionnaire-itemControl")
|
||||
.setValue(new Coding(null, "text-box", null));
|
||||
|
||||
ValidationResult errors = myVal.validateWithResult(q);
|
||||
|
||||
ourLog.info(errors.toString());
|
||||
assertThat(errors.isSuccessful(), Matchers.is(true));
|
||||
assertThat(errors.getMessages(), Matchers.hasSize(1));
|
||||
assertEquals(errors.getMessages().get(0).getSeverity(), ResultSeverityEnum.INFORMATION);
|
||||
assertThat(errors.getMessages().get(0).getMessage(), Matchers.startsWith("Unknown extension " + extensionUrl));
|
||||
|
||||
myInstanceVal.setCustomExtensionDomains(Collections.singletonList(extensionUrl));
|
||||
errors = myVal.validateWithResult(q);
|
||||
|
||||
ourLog.info(errors.toString());
|
||||
assertThat(errors.isSuccessful(), Matchers.is(true));
|
||||
assertThat(errors.getMessages(), Matchers.empty());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
myDefaultValidationSupport.flush();
|
||||
myDefaultValidationSupport = null;
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
package org.hl7.fhir.r4.validation;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
|
||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
|
||||
import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator;
|
||||
import org.hl7.fhir.r4.hapi.validation.ValidationSupportChain;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r4.model.Narrative;
|
||||
import org.hl7.fhir.r4.model.Narrative.NarrativeStatus;
|
||||
import org.hl7.fhir.r4.model.Questionnaire;
|
||||
import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class QuestionnaireValidatorR4Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(QuestionnaireValidatorR4Test.class);
|
||||
private static DefaultProfileValidationSupport myDefaultValidationSupport = new DefaultProfileValidationSupport();
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
private FhirInstanceValidator myInstanceVal;
|
||||
private FhirValidator myVal;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
IValidationSupport myValSupport = mock(IValidationSupport.class);
|
||||
|
||||
myVal = ourCtx.newValidator();
|
||||
myVal.setValidateAgainstStandardSchema(false);
|
||||
myVal.setValidateAgainstStandardSchematron(false);
|
||||
|
||||
ValidationSupportChain validationSupport = new ValidationSupportChain(myValSupport, myDefaultValidationSupport);
|
||||
myInstanceVal = new FhirInstanceValidator(validationSupport);
|
||||
|
||||
myVal.registerValidatorModule(myInstanceVal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuestionnaireWithPredefinedExtensionDomains() {
|
||||
String[] extensionDomainsToTest = new String[] {
|
||||
"http://example.org/questionnaire-color-control-1",
|
||||
"https://example.org/questionnaire-color-control-2",
|
||||
"http://acme.com/questionnaire-color-control-3",
|
||||
"https://acme.com/questionnaire-color-control-4",
|
||||
"http://nema.org/questionnaire-color-control-5",
|
||||
"https://nema.org/questionnaire-color-control-6",
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-scoreItem",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-expression",
|
||||
|
||||
};
|
||||
for (String extensionDomainToTest : extensionDomainsToTest) {
|
||||
Questionnaire q = minimalValidQuestionnaire();
|
||||
q.addItem()
|
||||
.setLinkId("link0")
|
||||
.setType(QuestionnaireItemType.STRING)
|
||||
.addExtension()
|
||||
.setUrl(extensionDomainToTest)
|
||||
.setValue(new Coding(null, "text-box", null));
|
||||
|
||||
ValidationResult errors = myVal.validateWithResult(q);
|
||||
ourLog.info(errors.toString());
|
||||
assertThat(errors.isSuccessful(), Matchers.is(true));
|
||||
assertThat(errors.getMessages(), Matchers.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuestionnaireWithPredefinedExtensionDomainsForCodeableConcept() {
|
||||
String[] extensionDomainsToTest = new String[] {
|
||||
"http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
|
||||
};
|
||||
for (String extensionDomainToTest : extensionDomainsToTest) {
|
||||
Questionnaire q = minimalValidQuestionnaire();
|
||||
q.addItem()
|
||||
.setLinkId("link0")
|
||||
.setType(QuestionnaireItemType.STRING)
|
||||
.addExtension()
|
||||
.setUrl(extensionDomainToTest)
|
||||
.setValue(new CodeableConcept().addCoding(new Coding(null, "text-box", null)));
|
||||
|
||||
ValidationResult errors = myVal.validateWithResult(q);
|
||||
ourLog.info(errors.toString());
|
||||
assertThat(errors.isSuccessful(), Matchers.is(true));
|
||||
assertThat(errors.getMessages(), Matchers.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuestionnaireWithCustomExtensionDomain() {
|
||||
String extensionUrl = "http://my.own.domain/StructureDefinition/";
|
||||
Questionnaire q = minimalValidQuestionnaire();
|
||||
q.addItem()
|
||||
.setLinkId("link0")
|
||||
.setType(QuestionnaireItemType.STRING)
|
||||
.addExtension()
|
||||
.setUrl(extensionUrl + "questionnaire-itemControl")
|
||||
.setValue(new Coding(null, "text-box", null));
|
||||
|
||||
ValidationResult errors = myVal.validateWithResult(q);
|
||||
|
||||
ourLog.info(errors.toString());
|
||||
assertThat(errors.isSuccessful(), Matchers.is(true));
|
||||
assertThat(errors.getMessages(), Matchers.hasSize(1));
|
||||
assertEquals(errors.getMessages().get(0).getSeverity(), ResultSeverityEnum.INFORMATION);
|
||||
assertThat(errors.getMessages().get(0).getMessage(), Matchers.startsWith("Unknown extension " + extensionUrl));
|
||||
|
||||
myInstanceVal.setCustomExtensionDomains(extensionUrl);
|
||||
errors = myVal.validateWithResult(q);
|
||||
|
||||
ourLog.info(errors.toString());
|
||||
assertThat(errors.isSuccessful(), Matchers.is(true));
|
||||
assertThat(errors.getMessages(), Matchers.empty());
|
||||
}
|
||||
|
||||
private Questionnaire minimalValidQuestionnaire() {
|
||||
Narrative n = new Narrative().setStatus(NarrativeStatus.GENERATED);
|
||||
n.setDivAsString("simple example");
|
||||
Questionnaire q = new Questionnaire();
|
||||
q.setText(n);
|
||||
q.setName("SomeName");
|
||||
q.setStatus(PublicationStatus.ACTIVE);
|
||||
return q;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
myDefaultValidationSupport.flush();
|
||||
myDefaultValidationSupport = null;
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue