Add NPM validation support module (#2782)
* Add NPM validation support module * Add changelog
This commit is contained in:
parent
3e7bc2a81e
commit
95306c3d64
|
@ -56,18 +56,25 @@ public class ClasspathUtil {
|
|||
|
||||
/**
|
||||
* Load a classpath resource, throw an {@link InternalErrorException} if not found
|
||||
*
|
||||
* @throws InternalErrorException If the resource can't be found
|
||||
*/
|
||||
@Nonnull
|
||||
public static InputStream loadResourceAsStream(String theClasspath) {
|
||||
InputStream retVal = ClasspathUtil.class.getResourceAsStream(theClasspath);
|
||||
String classpath = theClasspath;
|
||||
if (classpath.startsWith("classpath:")) {
|
||||
classpath = classpath.substring("classpath:".length());
|
||||
}
|
||||
|
||||
InputStream retVal = ClasspathUtil.class.getResourceAsStream(classpath);
|
||||
if (retVal == null) {
|
||||
if (theClasspath.startsWith("/")) {
|
||||
retVal = ClasspathUtil.class.getResourceAsStream(theClasspath.substring(1));
|
||||
if (classpath.startsWith("/")) {
|
||||
retVal = ClasspathUtil.class.getResourceAsStream(classpath.substring(1));
|
||||
} else {
|
||||
retVal = ClasspathUtil.class.getResourceAsStream("/" + theClasspath);
|
||||
retVal = ClasspathUtil.class.getResourceAsStream("/" + classpath);
|
||||
}
|
||||
if (retVal == null) {
|
||||
throw new InternalErrorException("Unable to find classpath resource: " + theClasspath);
|
||||
throw new InternalErrorException("Unable to find classpath resource: " + classpath);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
|
|
|
@ -40,8 +40,10 @@ import org.apache.commons.io.filefilter.WildcardFileFilter;
|
|||
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.NpmPackageValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.PrePopulatedValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.RemoteTerminologyServiceValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.SnapshotGeneratingValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||
|
@ -437,5 +439,45 @@ public class ValidatorExamples {
|
|||
|
||||
// END SNIPPET: validateFiles
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static void npm() throws Exception {
|
||||
// START SNIPPET: npm
|
||||
// Create an NPM Package Support module and load one package in from
|
||||
// the classpath
|
||||
FhirContext ctx = FhirContext.forR4();
|
||||
NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(ctx);
|
||||
npmPackageSupport.loadPackageFromClasspath("classpath:package/UK.Core.r4-1.1.0.tgz");
|
||||
|
||||
// Create a support chain including the NPM Package Support
|
||||
ValidationSupportChain validationSupportChain = new ValidationSupportChain(
|
||||
npmPackageSupport,
|
||||
new DefaultProfileValidationSupport(ctx),
|
||||
new CommonCodeSystemsTerminologyService(ctx),
|
||||
new InMemoryTerminologyServerValidationSupport(ctx),
|
||||
new SnapshotGeneratingValidationSupport(ctx)
|
||||
);
|
||||
CachingValidationSupport validationSupport = new CachingValidationSupport(validationSupportChain);
|
||||
|
||||
// Create a validator. Note that for good performance you can create as many validator objects
|
||||
// as you like, but you should reuse the same validation support object in all of the,.
|
||||
FhirValidator validator = ctx.newValidator();
|
||||
FhirInstanceValidator instanceValidator = new FhirInstanceValidator(validationSupport);
|
||||
validator.registerValidatorModule(instanceValidator);
|
||||
|
||||
// Create a test patient to validate
|
||||
Patient patient = new Patient();
|
||||
patient.getMeta().addProfile("https://fhir.nhs.uk/R4/StructureDefinition/UKCore-Patient");
|
||||
// System but not value set for NHS identifier (this should generate an error)
|
||||
patient.addIdentifier().setSystem("https://fhir.nhs.uk/Id/nhs-number");
|
||||
|
||||
// Perform the validation
|
||||
ValidationResult outcome = validator.validateWithResult(patient);
|
||||
// END SNIPPET: npm
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: add
|
||||
issue: 2782
|
||||
title: "A new Validation Support Module has been added that can use NPM Packages to supply
|
||||
validation conformance artifacts programatcally to the validator."
|
|
@ -59,6 +59,23 @@ to validate the resource. It will not work unless you include the
|
|||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|instanceValidator}}
|
||||
```
|
||||
|
||||
<a name="packages"/>
|
||||
|
||||
# Validating Using Packages
|
||||
|
||||
HAPI FHIR supports the use of FHIR NPM Packages for supplying validation artifacts.
|
||||
|
||||
When using the HAPI FHIR [JPA Server](../server_jpa/) you can simply upload your packages into the JPA Server package registry and the contents will be made available to the validator.
|
||||
|
||||
If you are using the validator as a standalone service (i.e. you are invoking it via a Java call) you will need to explcitly make your packages available to the validation support chain.
|
||||
|
||||
The following example shows the use of [NpmPackageValidationSupport](./validation_support_modules.html#npmpackagevalidationsupport) to load a package and use it to validate a resource.
|
||||
|
||||
```java
|
||||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/ValidatorExamples.java|npm}}
|
||||
```
|
||||
|
||||
|
||||
<a name="migrating-to-5x"></a>
|
||||
|
||||
# Migrating to HAPI FHIR 5.x
|
||||
|
|
|
@ -12,43 +12,53 @@ There are a several implementations of the [IValidationSupport](/hapi-fhir/apido
|
|||
|
||||
# ValidationSupportChain
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.html) / [Source](https://github.com/hapifhir/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.html) / [Source](https://github.com/hapifhir/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/ValidationSupportChain.java)
|
||||
|
||||
This module can be used to combine multiple implementations together so that for every request, each support class instance in the chain is tried in sequence. Note that nearly all methods in the [IValidationSupport](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/context/support/IValidationSupport.html) interface are permitted to return `null` if they are not able to service a particular method call. So for example, if a call to the [`validateCode`](/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/context/support/IValidationSupport.html#validateCode(ca.uhn.fhir.context.support.ValidationSupportContext,ca.uhn.fhir.context.support.ConceptValidationOptions,java.lang.String,java.lang.String,java.lang.String,java.lang.String)) method is made, the validator will try each module in the chain until one of them returns a non-null response.
|
||||
|
||||
# DefaultProfileValidationSupport
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-base/undefined/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.html) / [Source](https://github.com/hapifhir/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-base/undefined/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.html) / [Source](https://github.com/hapifhir/hapi-fhir/blob/master/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/DefaultProfileValidationSupport.java)
|
||||
|
||||
This module supplies the built-in FHIR core structure definitions, including both FHIR resource definitions (StructureDefinition resources) and FHIR built-in vocabulary (ValueSet and CodeSystem resources).
|
||||
|
||||
# InMemoryTerminologyServerValidationSupport
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java)
|
||||
|
||||
This module acts as a simple terminology service that can validate codes against ValueSet and CodeSystem resources purely in-memory (i.e. with no database). This is sufficient in many basic cases, although it is not able to validate CodeSystems with external content (i.e CodeSystems where the `CodeSystem.content` field is `external`, such as the LOINC and SNOMED CT CodeSystems).
|
||||
|
||||
# PrePopulatedValidationSupport
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/PrePopulatedValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/PrePopulatedValidationSupport.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/PrePopulatedValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/PrePopulatedValidationSupport.java)
|
||||
|
||||
This module contains a series of HashMaps that store loaded conformance resources in memory. Typically this is initialized at startup in order to add custom conformance resources into the chain.
|
||||
|
||||
|
||||
<a name="npmpackagevalidationsupport"/>
|
||||
|
||||
# NpmPackageValidationSupport
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/NpmPackageValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/NpmPackageValidationSupport.java)
|
||||
|
||||
This module can be used to load FHIR NPM Packages and supply the conformance resources within them to the validator. See [Validating Using Packages](./instance_validator.html#packages) for am example of how to use this module.
|
||||
|
||||
|
||||
# CachingValidationSupport
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/CachingValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/CachingValidationSupport.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/CachingValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/CachingValidationSupport.java)
|
||||
|
||||
This module caches results of calls to a wrapped service implementation for a period of time. This class can be a significant help in terms of performance if you are loading conformance resources or performing terminology operations from a database or disk, but it also has value even for purely in-memory validation since validating codes against a ValueSet can require the expansion of that ValueSet.
|
||||
|
||||
# SnapshotGeneratingValidationSupport
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/SnapshotGeneratingValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/SnapshotGeneratingValidationSupport.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/SnapshotGeneratingValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/SnapshotGeneratingValidationSupport.java)
|
||||
|
||||
This module generates StructureDefinition snapshots as needed. This should be added to your chain if you are working wiith differential StructureDefinitions that do not include the snapshot view.
|
||||
|
||||
# CommonCodeSystemsTerminologyService
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/CommonCodeSystemsTerminologyService.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/CommonCodeSystemsTerminologyService.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/CommonCodeSystemsTerminologyService.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/CommonCodeSystemsTerminologyService.java)
|
||||
|
||||
This module validates codes in CodeSystems that are not distributed with the FHIR specification because they are difficult to distribute but are commonly used in FHIR resources.
|
||||
|
||||
|
@ -132,7 +142,7 @@ The following table lists vocabulary that is validated by this module:
|
|||
|
||||
# RemoteTerminologyServiceValidationSupport
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.java)
|
||||
|
||||
This module validates codes using a remote FHIR-based terminology server.
|
||||
|
||||
|
@ -145,7 +155,7 @@ This module will invoke the following operations on the remote terminology serve
|
|||
|
||||
# UnknownCodeSystemWarningValidationSupport
|
||||
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/UnknownCodeSystemWarningValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/ja_20200218_validation_api_changes/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/UnknownCodeSystemWarningValidationSupport.java)
|
||||
[JavaDoc](/hapi-fhir/apidocs/hapi-fhir-validation/org/hl7/fhir/common/hapi/validation/support/UnknownCodeSystemWarningValidationSupport.html) / [Source](https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/UnknownCodeSystemWarningValidationSupport.java)
|
||||
|
||||
This validation support module may be placed at the end of a ValidationSupportChain in order to configure the validator to generate a warning if a resource being validated contains an unknown code system.
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package org.hl7.fhir.common.hapi.validation.support;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.util.ClasspathUtil;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.hl7.fhir.utilities.npm.NpmPackage;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* This interceptor loads and parses FHIR NPM Conformance Packages, and makes the
|
||||
* artifacts foudn within them available to the FHIR validator.
|
||||
*
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public class NpmPackageValidationSupport extends PrePopulatedValidationSupport {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public NpmPackageValidationSupport(@Nonnull FhirContext theFhirContext) {
|
||||
super(theFhirContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an NPM package using a classpath specification, e.g. <code>/path/to/resource/my_package.tgz</code>. The
|
||||
* classpath spec can optionally be prefixed with the string <code>classpath:</code>
|
||||
*
|
||||
* @throws InternalErrorException If the classpath file can't be found
|
||||
*/
|
||||
public void loadPackageFromClasspath(String theClasspath) throws IOException {
|
||||
try (InputStream is = ClasspathUtil.loadResourceAsStream(theClasspath)) {
|
||||
NpmPackage pkg = NpmPackage.fromPackage(is);
|
||||
if (pkg.getFolders().containsKey("package")) {
|
||||
NpmPackage.NpmPackageFolder packageFolder = pkg.getFolders().get("package");
|
||||
|
||||
for (String nextFile : packageFolder.listFiles()) {
|
||||
if (nextFile.toLowerCase(Locale.US).endsWith(".json")) {
|
||||
String input = new String(packageFolder.getContent().get(nextFile), StandardCharsets.UTF_8);
|
||||
IBaseResource resource = getFhirContext().newJsonParser().parseResource(input);
|
||||
super.addResource(resource);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@ import org.hl7.fhir.r4.model.CodeSystem;
|
|||
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -26,7 +27,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
*/
|
||||
public class PrePopulatedValidationSupport extends BaseStaticResourceValidationSupport implements IValidationSupport {
|
||||
|
||||
private final FhirContext myFhirContext;
|
||||
private final Map<String, IBaseResource> myCodeSystems;
|
||||
private final Map<String, IBaseResource> myStructureDefinitions;
|
||||
private final Map<String, IBaseResource> myValueSets;
|
||||
|
@ -55,7 +55,6 @@ public class PrePopulatedValidationSupport extends BaseStaticResourceValidationS
|
|||
Validate.notNull(theStructureDefinitions, "theStructureDefinitions must not be null");
|
||||
Validate.notNull(theValueSets, "theValueSets must not be null");
|
||||
Validate.notNull(theCodeSystems, "theCodeSystems must not be null");
|
||||
myFhirContext = theFhirContext;
|
||||
myStructureDefinitions = theStructureDefinitions;
|
||||
myValueSets = theValueSets;
|
||||
myCodeSystems = theCodeSystems;
|
||||
|
@ -82,7 +81,7 @@ public class PrePopulatedValidationSupport extends BaseStaticResourceValidationS
|
|||
|
||||
private String processResourceAndReturnUrl(IBaseResource theCodeSystem, String theResourceName) {
|
||||
Validate.notNull(theCodeSystem, "the" + theResourceName + " must not be null");
|
||||
RuntimeResourceDefinition resourceDef = myFhirContext.getResourceDefinition(theCodeSystem);
|
||||
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(theCodeSystem);
|
||||
String actualResourceName = resourceDef.getName();
|
||||
Validate.isTrue(actualResourceName.equals(theResourceName), "the" + theResourceName + " must be a " + theResourceName + " - Got: " + actualResourceName);
|
||||
|
||||
|
@ -113,16 +112,16 @@ public class PrePopulatedValidationSupport extends BaseStaticResourceValidationS
|
|||
addToMap(theStructureDefinition, myStructureDefinitions, url);
|
||||
}
|
||||
|
||||
private <T extends IBaseResource> void addToMap(T theStructureDefinition, Map<String, T> map, String theUrl) {
|
||||
private <T extends IBaseResource> void addToMap(T theResource, Map<String, T> theMap, String theUrl) {
|
||||
if (isNotBlank(theUrl)) {
|
||||
map.put(theUrl, theStructureDefinition);
|
||||
theMap.put(theUrl, theResource);
|
||||
|
||||
int lastSlashIdx = theUrl.lastIndexOf('/');
|
||||
if (lastSlashIdx != -1) {
|
||||
map.put(theUrl.substring(lastSlashIdx + 1), theStructureDefinition);
|
||||
theMap.put(theUrl.substring(lastSlashIdx + 1), theResource);
|
||||
int previousSlashIdx = theUrl.lastIndexOf('/', lastSlashIdx - 1);
|
||||
if (previousSlashIdx != -1) {
|
||||
map.put(theUrl.substring(previousSlashIdx + 1), theStructureDefinition);
|
||||
theMap.put(theUrl.substring(previousSlashIdx + 1), theResource);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,12 +142,33 @@ public class PrePopulatedValidationSupport extends BaseStaticResourceValidationS
|
|||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public void addValueSet(ValueSet theValueSet) {
|
||||
public void addValueSet(IBaseResource theValueSet) {
|
||||
String url = processResourceAndReturnUrl(theValueSet, "ValueSet");
|
||||
addToMap(theValueSet, myValueSets, url);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param theResource The resource. This method delegates to the type-specific methods (e.g. {@link #addCodeSystem(IBaseResource)})
|
||||
* and will do nothing if the resource type is not supported by this class.
|
||||
* @since 5.5.0
|
||||
*/
|
||||
public void addResource(@Nonnull IBaseResource theResource) {
|
||||
Validate.notNull(theResource, "theResource must not be null");
|
||||
|
||||
switch (getFhirContext().getResourceType(theResource)) {
|
||||
case "StructureDefinition":
|
||||
addStructureDefinition(theResource);
|
||||
break;
|
||||
case "CodeSystem":
|
||||
addCodeSystem(theResource);
|
||||
break;
|
||||
case "ValueSet":
|
||||
addValueSet(theResource);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IBaseResource> fetchAllConformanceResources() {
|
||||
ArrayList<IBaseResource> retVal = new ArrayList<>();
|
||||
|
@ -159,7 +179,7 @@ public class PrePopulatedValidationSupport extends BaseStaticResourceValidationS
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<IBaseResource> fetchAllStructureDefinitions() {
|
||||
public <T extends IBaseResource> List<T> fetchAllStructureDefinitions() {
|
||||
return toList(myStructureDefinitions);
|
||||
}
|
||||
|
||||
|
@ -187,5 +207,4 @@ public class PrePopulatedValidationSupport extends BaseStaticResourceValidationS
|
|||
public boolean isValueSetSupported(ValidationSupportContext theValidationSupportContext, String theValueSetUrl) {
|
||||
return myValueSets.containsKey(theValueSetUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package org.hl7.fhir.common.hapi.validation.support;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
||||
public class PrePopulatedValidationSupportTest {
|
||||
|
||||
private final PrePopulatedValidationSupport mySvc = new PrePopulatedValidationSupport(FhirContext.forR4Cached());
|
||||
|
||||
@Test
|
||||
public void testAddResource() {
|
||||
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setUrl("http://cs");
|
||||
mySvc.addResource(cs);
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl("http://vs");
|
||||
mySvc.addResource(vs);
|
||||
|
||||
StructureDefinition sd = new StructureDefinition();
|
||||
sd.setUrl("http://sd");
|
||||
mySvc.addResource(sd);
|
||||
|
||||
assertSame(cs, mySvc.fetchCodeSystem("http://cs"));
|
||||
assertSame(vs, mySvc.fetchValueSet("http://vs"));
|
||||
assertSame(sd, mySvc.fetchStructureDefinition("http://sd"));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package org.hl7.fhir.r4.validation;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.NpmPackageValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.SnapshotGeneratingValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class NpmPackageValidationSupportTest {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(NpmPackageValidationSupportTest.class);
|
||||
private FhirContext myFhirContext = FhirContext.forR4Cached();
|
||||
|
||||
@Test
|
||||
public void testValidateWithPackage() throws IOException {
|
||||
|
||||
// Create an NPM Package Support module and load one package in from
|
||||
// the classpath
|
||||
NpmPackageValidationSupport npmPackageSupport = new NpmPackageValidationSupport(myFhirContext);
|
||||
npmPackageSupport.loadPackageFromClasspath("classpath:package/UK.Core.r4-1.1.0.tgz");
|
||||
|
||||
// Create a support chain including the NPM Package Support
|
||||
ValidationSupportChain validationSupportChain = new ValidationSupportChain(
|
||||
npmPackageSupport,
|
||||
new DefaultProfileValidationSupport(myFhirContext),
|
||||
new CommonCodeSystemsTerminologyService(myFhirContext),
|
||||
new InMemoryTerminologyServerValidationSupport(myFhirContext),
|
||||
new SnapshotGeneratingValidationSupport(myFhirContext)
|
||||
);
|
||||
CachingValidationSupport validationSupport = new CachingValidationSupport(validationSupportChain);
|
||||
|
||||
// Create a validator
|
||||
FhirValidator validator = myFhirContext.newValidator();
|
||||
FhirInstanceValidator instanceValidator = new FhirInstanceValidator(validationSupport);
|
||||
validator.registerValidatorModule(instanceValidator);
|
||||
|
||||
// Create a test patient to validate
|
||||
Patient patient = new Patient();
|
||||
patient.getMeta().addProfile("https://fhir.nhs.uk/R4/StructureDefinition/UKCore-Patient");
|
||||
// System but not value set for NHS identifier (this should generate an error)
|
||||
patient.addIdentifier().setSystem("https://fhir.nhs.uk/Id/nhs-number");
|
||||
|
||||
// Perform the validation
|
||||
ValidationResult outcome = validator.validateWithResult(patient);
|
||||
|
||||
String outcomeSerialized = myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome.toOperationOutcome());
|
||||
ourLog.info(outcomeSerialized);
|
||||
assertThat(outcomeSerialized, containsString("Patient.identifier:nhsNumber.value: minimum required = 1, but only found 0"));
|
||||
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue