Merge pull request #813 from hapifhir/gg-202205-ts-conv

Gg 202205 ts conv
This commit is contained in:
Grahame Grieve 2022-05-20 08:17:04 +10:00 committed by GitHub
commit f3bed096c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 6613 additions and 24 deletions

View File

@ -1,7 +1,9 @@
## Validator Changes
* no changes
* alter per-1 to handle different precision on start/end
* Add support for a -jurisdiction parameter, preparing for jurisdictionally specific constraints in profiles
## Other code changes
* no changes
* extend FHIRPath to support lowBoundary(), highBoundary() and precision()
* Fix for inefficiency in StructureMap engine

View File

@ -1,13 +1,33 @@
package org.hl7.fhir.convertors.advisors.impl;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import org.hl7.fhir.convertors.advisors.interfaces.BaseAdvisor50;
import org.hl7.fhir.exceptions.FHIRException;
public class BaseAdvisor_40_50 extends BaseAdvisor50<org.hl7.fhir.r4.model.Extension> {
private static final List<String> TestScriptIgnoredUrls = Arrays.asList("http://hl7.org/fhir/5.0/StructureDefinition/extension-TestScript.scope");
public BaseAdvisor_40_50() {
}
public BaseAdvisor_40_50(Boolean failFast) {
this.failFast = failFast;
}
@Override
public boolean ignoreExtension(@Nonnull String path,
@Nonnull String url) throws FHIRException {
List<String> paths = Arrays.asList(path.split(","));
if ((paths.get(paths.size() - 1).equals("TestScript")) && (TestScriptIgnoredUrls.contains(url))) {
return true;
} else
return false;
}
}

View File

@ -9,6 +9,8 @@ import org.hl7.fhir.convertors.conv40_50.datatypes40_50.metadata40_50.UsageConte
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.*;
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.special40_50.Reference40_50;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.utils.ToolingExtensions;
import org.hl7.fhir.r5.model.TestScript.TestScriptScopeComponent;
/*
Copyright (c) 2011+, HL7, Inc.
@ -46,6 +48,19 @@ public class TestScript40_50 {
return null;
org.hl7.fhir.r5.model.TestScript tgt = new org.hl7.fhir.r5.model.TestScript();
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyDomainResource(src, tgt);
for (org.hl7.fhir.r4.model.Extension ext : src.getExtensionsByUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-TestScript.scope")) {
// the advisor will get this ignored.
TestScriptScopeComponent scope = tgt.addScope();
scope.setArtifact(ext.getExtensionString("artifact"));
org.hl7.fhir.r4.model.Extension se = ext.getExtensionByUrl("conformance");
if (se != null) {
scope.setConformance(CodeableConcept40_50.convertCodeableConcept((org.hl7.fhir.r4.model.CodeableConcept) se.getValue()));
}
se = ext.getExtensionByUrl("phase");
if (se != null) {
scope.setPhase(CodeableConcept40_50.convertCodeableConcept((org.hl7.fhir.r4.model.CodeableConcept) se.getValue()));
}
}
if (src.hasUrl())
tgt.setUrlElement(Uri40_50.convertUri(src.getUrlElement()));
if (src.hasIdentifier())
@ -148,6 +163,25 @@ public class TestScript40_50 {
tgt.addTest(convertTestScriptTestComponent(t));
if (src.hasTeardown())
tgt.setTeardown(convertTestScriptTeardownComponent(src.getTeardown()));
for (TestScriptScopeComponent scope : src.getScope()) {
org.hl7.fhir.r4.model.Extension ext = tgt.addExtension();
ext.setUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-TestScript.scope");
if (scope.hasArtifact()) {
org.hl7.fhir.r4.model.Extension se = ext.addExtension();
se.setUrl("artifact");
se.setValue(Canonical40_50.convertCanonical(scope.getArtifactElement()));
}
if (scope.hasConformance()) {
org.hl7.fhir.r4.model.Extension se = ext.addExtension();
se.setUrl("conformance");
se.setValue(CodeableConcept40_50.convertCodeableConcept(scope.getConformance()));
}
if (scope.hasPhase()) {
org.hl7.fhir.r4.model.Extension se = ext.addExtension();
se.setUrl("phase");
se.setValue(CodeableConcept40_50.convertCodeableConcept(scope.getPhase()));
}
}
return tgt;
}

View File

@ -0,0 +1,47 @@
package org.hl7.fhir.convertors.conv40_50;
import java.io.IOException;
import java.io.InputStream;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
public class TestScript40_50Test {
@Test
@DisplayName("Test TestScript R4 <-> R5 with resoutce scope extension")
public void testValueExpressionConversion40_10() throws IOException {
InputStream r4_stream = this.getClass().getResourceAsStream("/test_script_r4.json");
org.hl7.fhir.r4.model.TestScript r4_input = (org.hl7.fhir.r4.model.TestScript) new org.hl7.fhir.r4.formats.JsonParser().parse(r4_stream);
InputStream r5_stream = this.getClass().getResourceAsStream("/test_script_r5.json");
org.hl7.fhir.r5.model.TestScript r5_input = (org.hl7.fhir.r5.model.TestScript) new org.hl7.fhir.r5.formats.JsonParser().parse(r5_stream);
org.hl7.fhir.r5.model.TestScript r5_output = (org.hl7.fhir.r5.model.TestScript) VersionConvertorFactory_40_50.convertResource(r4_input);
org.hl7.fhir.r4.model.TestScript r4_output = (org.hl7.fhir.r4.model.TestScript) VersionConvertorFactory_40_50.convertResource(r5_input);
org.hl7.fhir.r5.formats.JsonParser r5_parser = new org.hl7.fhir.r5.formats.JsonParser();
String r5_in = r5_parser.setOutputStyle(OutputStyle.PRETTY).composeString(r5_input);
String r5_out = r5_parser.composeString(r5_output);
boolean pass = r5_input.equalsDeep(r5_output);
if (!pass) {
System.out.println("R5. Expected out ->\n"+ r5_in + "\n\nActual out ->\n" + r5_out);
}
Assertions.assertTrue(pass);
org.hl7.fhir.r4.formats.JsonParser r4_parser = new org.hl7.fhir.r4.formats.JsonParser();
String r4_in = r4_parser.composeString(r4_input);
String r4_out = r4_parser.composeString(r4_output);
pass = r4_input.equalsDeep(r4_output);
if (!pass) {
System.out.println("R4. Expected out ->\n"+ r4_in + "\n\nActual out ->\n" + r4_out);
}
Assertions.assertTrue(pass);
}
}

View File

@ -0,0 +1,208 @@
{
"resourceType": "TestScript",
"extension" : [{
"url" : "http://hl7.org/fhir/5.0/StructureDefinition/extension-TestScript.scope",
"extension" : [{
"url" : "artifact",
"valueCanonical" : "http://somewhere.org/fhir/uv/myig/StructureDefinition/mypatient"
},{
"url" : "conformance",
"valueCodeableConcept" : {
"coding" : [
{
"system" : "http://terminology.hl7.org/CodeSystem/testscript-scope-conformance-codes",
"code" : "required",
"display" : "Required"
}
]
}
}]
}],
"id": "testscript-example-readtest",
"version": "1.0",
"name": "TestScript Example Read Test",
"status": "draft",
"experimental": true,
"date": "2017-01-18",
"publisher": "HL7",
"contact": [
{
"name": "Support",
"telecom": [
{
"system": "email",
"value": "support@HL7.org",
"use": "work"
}
]
}
],
"description": "TestScript example resource for simple read test.",
"purpose": "Patient Read Operation",
"copyright": "© HL7.org 2011+",
"metadata": {
"link": [
{
"url": "http://hl7.org/fhir/patient.html",
"description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services."
}
]
},
"profile": [
{
"id": "patient-profile",
"reference": "http://hl7.org/fhir/StructureDefinition/Patient"
}
],
"variable": [
{
"name": "KnownPatientResourceId",
"defaultValue": "example"
},
{
"name": "NonExistsPatientResourceId",
"defaultValue": "does-not-exist"
}
],
"test": [
{
"id": "R001",
"name": "Sprinkler Read Test R001",
"description": "Read a known Patient and validate response.",
"action": [
{
"operation": {
"type": {
"system": "http://terminology.hl7.org/CodeSystem/testscript-operation-codes",
"code": "read"
},
"resource": "Patient",
"description": "Read the known Patient resource on the destination test system using the user defined dynamic variable ${KnownPatientResourceId}.",
"accept": "xml",
"encodeRequestUrl": true,
"params": "/${KnownPatientResourceId}"
}
},
{
"assert": {
"description": "Confirm that the returned HTTP status is 200(OK).",
"response": "okay",
"warningOnly": false
}
},
{
"assert": {
"description": "Confirm that the returned format is XML.",
"contentType": "xml",
"warningOnly": false
}
},
{
"assert": {
"description": "Confirm that the returned HTTP Header Last-Modified is present. Warning only as the server might not support versioning.",
"headerField": "Last-Modified",
"operator": "notEmpty",
"warningOnly": true
}
},
{
"assert": {
"description": "Confirm that the returned resource type is Patient.",
"resource": "Patient",
"warningOnly": false
}
},
{
"assert": {
"description": "Confirm that the returned Patient conforms to the base FHIR specification.",
"validateProfileId": "patient-profile",
"warningOnly": false
}
}
]
},
{
"id": "R002",
"name": "Sprinkler Read Test R002",
"description": "Read an unknown Resource Type and validate response.",
"action": [
{
"operation": {
"type": {
"system": "http://terminology.hl7.org/CodeSystem/testscript-operation-codes",
"code": "read"
},
"resource": "Patient",
"description": "Attempt to read the Parameters resource type. What we really want here is an illegal type but the build process won't allow that. Parameters is a valid resource which doesn't have an end-point so, this should fail.",
"accept": "xml",
"encodeRequestUrl": true,
"params": "/1"
}
},
{
"assert": {
"description": "Confirm that the returned HTTP status is 404(Not Found).",
"response": "notFound",
"warningOnly": false
}
}
]
},
{
"id": "R003",
"name": "Sprinkler Read Test R003",
"description": "Read a known, non-existing Patient and validate response.",
"action": [
{
"operation": {
"type": {
"system": "http://terminology.hl7.org/CodeSystem/testscript-operation-codes",
"code": "read"
},
"resource": "Patient",
"description": "Attempt to read the non-existing Patient resource on the destination test system using the user defined dynamic variable ${NonExistsPatientResourceId}.",
"accept": "xml",
"encodeRequestUrl": true,
"params": "/${NonExistsPatientResourceId}"
}
},
{
"assert": {
"description": "Confirm that the returned HTTP status is 404(Not Found).",
"response": "notFound",
"warningOnly": false
}
}
]
},
{
"id": "R004",
"name": "Sprinkler Read Test R004",
"description": "Read a Patient using a known bad formatted resource id and validate response.",
"action": [
{
"operation": {
"type": {
"system": "http://terminology.hl7.org/CodeSystem/testscript-operation-codes",
"code": "read"
},
"resource": "Patient",
"description": "Attempt to read a Patient resource on the destination test system using known bad formatted resource id.",
"accept": "xml",
"encodeRequestUrl": true,
"params": "/ID-may-not-contain-CAPITALS"
}
},
{
"assert": {
"description": "Confirm that the returned HTTP status is 400(Bad Request).",
"response": "bad",
"warningOnly": false
}
}
]
}
]
}

View File

@ -0,0 +1,202 @@
{
"resourceType": "TestScript",
"id": "testscript-example-readtest",
"scope": [
{
"artifact": "http://somewhere.org/fhir/uv/myig/StructureDefinition/mypatient",
"conformance": {
"coding": [
{
"system" : "http://terminology.hl7.org/CodeSystem/testscript-scope-conformance-codes",
"code" : "required",
"display" : "Required"
}
]
}
}
],
"version": "1.0",
"name": "TestScript Example Read Test",
"status": "draft",
"experimental": true,
"date": "2017-01-18",
"publisher": "HL7",
"contact": [
{
"name": "Support",
"telecom": [
{
"system": "email",
"value": "support@HL7.org",
"use": "work"
}
]
}
],
"description": "TestScript example resource for simple read test.",
"purpose": "Patient Read Operation",
"copyright": "© HL7.org 2011+",
"metadata": {
"link": [
{
"url": "http://hl7.org/fhir/patient.html",
"description": "Demographics and other administrative information about an individual or animal receiving care or other health-related services."
}
]
},
"profile": [
{
"id": "patient-profile",
"reference": "http://hl7.org/fhir/StructureDefinition/Patient"
}
],
"variable": [
{
"name": "KnownPatientResourceId",
"defaultValue": "example"
},
{
"name": "NonExistsPatientResourceId",
"defaultValue": "does-not-exist"
}
],
"test": [
{
"id": "R001",
"name": "Sprinkler Read Test R001",
"description": "Read a known Patient and validate response.",
"action": [
{
"operation": {
"type": {
"system": "http://terminology.hl7.org/CodeSystem/testscript-operation-codes",
"code": "read"
},
"resource": "Patient",
"description": "Read the known Patient resource on the destination test system using the user defined dynamic variable ${KnownPatientResourceId}.",
"accept": "xml",
"encodeRequestUrl": true,
"params": "/${KnownPatientResourceId}"
}
},
{
"assert": {
"description": "Confirm that the returned HTTP status is 200(OK).",
"response": "okay",
"warningOnly": false
}
},
{
"assert": {
"description": "Confirm that the returned format is XML.",
"contentType": "xml",
"warningOnly": false
}
},
{
"assert": {
"description": "Confirm that the returned HTTP Header Last-Modified is present. Warning only as the server might not support versioning.",
"headerField": "Last-Modified",
"operator": "notEmpty",
"warningOnly": true
}
},
{
"assert": {
"description": "Confirm that the returned resource type is Patient.",
"resource": "Patient",
"warningOnly": false
}
},
{
"assert": {
"description": "Confirm that the returned Patient conforms to the base FHIR specification.",
"validateProfileId": "patient-profile",
"warningOnly": false
}
}
]
},
{
"id": "R002",
"name": "Sprinkler Read Test R002",
"description": "Read an unknown Resource Type and validate response.",
"action": [
{
"operation": {
"type": {
"system": "http://terminology.hl7.org/CodeSystem/testscript-operation-codes",
"code": "read"
},
"resource": "Patient",
"description": "Attempt to read the Parameters resource type. What we really want here is an illegal type but the build process won't allow that. Parameters is a valid resource which doesn't have an end-point so, this should fail.",
"accept": "xml",
"encodeRequestUrl": true,
"params": "/1"
}
},
{
"assert": {
"description": "Confirm that the returned HTTP status is 404(Not Found).",
"response": "notFound",
"warningOnly": false
}
}
]
},
{
"id": "R003",
"name": "Sprinkler Read Test R003",
"description": "Read a known, non-existing Patient and validate response.",
"action": [
{
"operation": {
"type": {
"system": "http://terminology.hl7.org/CodeSystem/testscript-operation-codes",
"code": "read"
},
"resource": "Patient",
"description": "Attempt to read the non-existing Patient resource on the destination test system using the user defined dynamic variable ${NonExistsPatientResourceId}.",
"accept": "xml",
"encodeRequestUrl": true,
"params": "/${NonExistsPatientResourceId}"
}
},
{
"assert": {
"description": "Confirm that the returned HTTP status is 404(Not Found).",
"response": "notFound",
"warningOnly": false
}
}
]
},
{
"id": "R004",
"name": "Sprinkler Read Test R004",
"description": "Read a Patient using a known bad formatted resource id and validate response.",
"action": [
{
"operation": {
"type": {
"system": "http://terminology.hl7.org/CodeSystem/testscript-operation-codes",
"code": "read"
},
"resource": "Patient",
"description": "Attempt to read a Patient resource on the destination test system using known bad formatted resource id.",
"accept": "xml",
"encodeRequestUrl": true,
"params": "/ID-may-not-contain-CAPITALS"
}
},
{
"assert": {
"description": "Confirm that the returned HTTP status is 400(Bad Request).",
"response": "bad",
"warningOnly": false
}
}
]
}
]
}

View File

@ -69,6 +69,8 @@ import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.model.StructureMap.StructureMapModelMode;
import org.hl7.fhir.r5.model.StructureMap.StructureMapStructureComponent;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
import org.hl7.fhir.r5.terminologies.TerminologyClient;
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.XVerExtensionManager;
@ -579,7 +581,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
public IResourceValidator newValidator() throws FHIRException {
if (validatorFactory == null)
throw new Error(formatMessage(I18nConstants.NO_VALIDATOR_CONFIGURED));
return validatorFactory.makeValidator(this, xverManager);
return validatorFactory.makeValidator(this, xverManager).setJurisdiction(JurisdictionUtilities.getJurisdictionCodingFromLocale(Locale.getDefault().getCountry()));
}

View File

@ -50,6 +50,7 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
import org.hl7.fhir.r5.model.CodeSystem.PropertyType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.DateTimeType;
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
@ -532,5 +533,10 @@ public class CodeSystemUtilities {
}
}
}
public static Coding readCoding(String jurisdiction) {
return jurisdiction == null || !jurisdiction.contains("#") ? null : new Coding().setCode(jurisdiction.substring(jurisdiction.indexOf("#")+1)).setSystem(jurisdiction.substring(0, jurisdiction.indexOf("#")));
}
}

View File

@ -33,6 +33,7 @@ package org.hl7.fhir.r5.utils.validation;
import com.google.gson.JsonObject;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
import org.hl7.fhir.r5.utils.validation.constants.CheckDisplayOption;
@ -145,6 +146,9 @@ public interface IResourceValidator {
boolean isValidateValueSetCodesOnTxServer();
void setValidateValueSetCodesOnTxServer(boolean value);
public Coding getJurisdiction();
public IResourceValidator setJurisdiction(Coding jurisdiction);
/**
* Bundle validation rules allow for requesting particular entries in a bundle get validated against particular profiles
* Typically this is used from the command line to avoid having to construct profile just to validate a particular resource

View File

@ -121,6 +121,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
protected List<TrackedLocationRelatedMessage> trackedMessages = new ArrayList<>();
protected List<ValidationMessage> messagesToRemove = new ArrayList<>();
private ValidationLevel level = ValidationLevel.HINTS;
protected Coding jurisdiction;
public BaseValidator(IWorkerContext context, XVerExtensionManager xverManager) {
super();
@ -1102,4 +1103,5 @@ public class BaseValidator implements IValidationContextResourceLoader {
return level;
}
}

View File

@ -167,6 +167,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
@Getter @Setter private ValidationLevel level = ValidationLevel.HINTS;
@Getter @Setter private FHIRPathEngine fhirPathEngine;
@Getter @Setter private IgLoader igLoader;
@Getter @Setter private Coding jurisdiction;
/**
* Systems that host the ValidationEngine can use this to control what validation the validator performs.
@ -623,7 +624,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
if (format == FhirFormat.SHC) {
igLoader.loadIg(getIgs(), getBinaries(), SHCParser.CURRENT_PACKAGE, true);
}
validator.setJurisdiction(jurisdiction);
return validator;
}

View File

@ -60,6 +60,7 @@ POSSIBILITY OF SUCH DAMAGE.
import org.hl7.fhir.r5.model.ImplementationGuide;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
import org.hl7.fhir.utilities.TimeTracker;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
@ -231,6 +232,8 @@ public class ValidatorCli {
if (cliContext.getSv() == null) {
cliContext.setSv(validationService.determineVersion(cliContext));
}
System.out.println(" Jurisdiction: "+JurisdictionUtilities.displayJurisdiction(cliContext.getJurisdiction()));
System.out.println("Loading");
// Comment this out because definitions filename doesn't necessarily contain version (and many not even be 14 characters long).
// Version gets spit out a couple of lines later after we've loaded the context

View File

@ -7,6 +7,8 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
import org.hl7.fhir.r5.utils.validation.BundleValidationRule;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.validation.cli.utils.QuestionnaireMode;
@ -111,7 +113,9 @@ public class CliContext {
// TODO: Mark what goes here?
private List<BundleValidationRule> bundleValidationRules = new ArrayList<>();
@JsonProperty("jurisdiction")
private String jurisdiction = JurisdictionUtilities.getJurisdictionFromLocale(Locale.getDefault().getCountry());
@JsonProperty("map")
public String getMap() {
return map;
@ -564,6 +568,14 @@ public class CliContext {
this.noUnicodeBiDiControlChars = noUnicodeBiDiControlChars;
}
public String getJurisdiction() {
return jurisdiction;
}
public void setJurisdiction(String jurisdiction) {
this.jurisdiction = jurisdiction;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -604,6 +616,7 @@ public class CliContext {
mode == that.mode &&
Objects.equals(locale, that.locale) &&
Objects.equals(outputStyle, that.outputStyle) &&
Objects.equals(jurisdiction, that.jurisdiction) &&
Objects.equals(locations, that.locations);
}
@ -611,7 +624,7 @@ public class CliContext {
public int hashCode() {
return Objects.hash(doNative, extensions, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching,
noExtensibleBindingMessages, noInvariants, wantInvariantsInMessages, map, output, htmlOutput, txServer, sv, txLog, txCache, mapLog, lang, fhirpath, snomedCT,
targetVer, igs, questionnaireMode, level, profiles, sources, mode, locale, locations, crumbTrails, showTimes, allowExampleUrls, outputStyle, noUnicodeBiDiControlChars);
targetVer, igs, questionnaireMode, level, profiles, sources, mode, locale, locations, crumbTrails, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars);
}
@Override
@ -650,6 +663,7 @@ public class CliContext {
", securityChecks=" + securityChecks +
", crumbTrails=" + crumbTrails +
", outputStyle=" + outputStyle +
", jurisdiction=" + jurisdiction +
", allowExampleUrls=" + allowExampleUrls +
", showTimes=" + showTimes +
", locale='" + locale + '\'' +

View File

@ -16,6 +16,7 @@ import org.hl7.fhir.r5.renderers.spreadsheets.CodeSystemSpreadsheetGenerator;
import org.hl7.fhir.r5.renderers.spreadsheets.ConceptMapSpreadsheetGenerator;
import org.hl7.fhir.r5.renderers.spreadsheets.StructureDefinitionSpreadsheetGenerator;
import org.hl7.fhir.r5.renderers.spreadsheets.ValueSetSpreadsheetGenerator;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.TextFile;
@ -364,6 +365,7 @@ public class ValidationService {
validator.setFetcher(fetcher);
validator.getContext().setLocator(fetcher);
validator.getBundleValidationRules().addAll(cliContext.getBundleValidationRules());
validator.setJurisdiction(CodeSystemUtilities.readCoding(cliContext.getJurisdiction()));
TerminologyCache.setNoCaching(cliContext.isNoInternalCaching());
validator.prepare(); // generate any missing snapshots
System.out.println(" go (" + tt.milestone() + ")");
@ -373,6 +375,7 @@ public class ValidationService {
return sessionId;
}
public String determineVersion(CliContext cliContext) throws Exception {
return determineVersion(cliContext, null);
}

View File

@ -3,6 +3,7 @@ package org.hl7.fhir.validation.cli.utils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.ToolsVersion;

View File

@ -1,5 +1,8 @@
package org.hl7.fhir.validation.cli.utils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
import org.hl7.fhir.r5.utils.validation.BundleValidationRule;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.validation.cli.model.CliContext;
@ -65,6 +68,7 @@ public class Params {
public static final String SHOW_TIMES = "-show-times";
public static final String ALLOW_EXAMPLE_URLS = "-allow-example-urls";
public static final String OUTPUT_STYLE = "-output-style";
private static final Object JURISDICTION = "-jurisdiction";
/**
* Checks the list of passed in params to see if it contains the passed in param.
@ -249,6 +253,11 @@ public class Params {
throw new Error("Specified -language without indicating language");
else
cliContext.setLang(args[++i]);
} else if (args[i].equals(JURISDICTION)) {
if (i + 1 == args.length)
throw new Error("Specified -jurisdiction without indicating jurisdiction");
else
cliContext.setJurisdiction(processJurisdiction(args[++i]));
} else if (args[i].equals(IMPLEMENTATION_GUIDE) || args[i].equals(DEFINITION)) {
if (i + 1 == args.length)
throw new Error("Specified " + args[i] + " without indicating ig file");
@ -290,6 +299,19 @@ public class Params {
return cliContext;
}
private static String processJurisdiction(String s) {
if (s.startsWith("urn:iso:std:iso:3166#") || s.startsWith("urn:iso:std:iso:3166:-2#") || s.startsWith("http://unstats.un.org/unsd/methods/m49/m49.htm#")) {
return s;
} else {
String v = JurisdictionUtilities.getJurisdictionFromLocale(s);
if (v != null) {
return v;
} else {
throw new FHIRException("Unable to understand Jurisdiction '"+s+"'");
}
}
}
public static String getTerminologyServerLog(String[] args) {
String txLog = null;
if (hasParam(args, "-txLog")) {

View File

@ -4529,27 +4529,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
public void checkSpecials(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element element, NodeStack stack, boolean checkSpecials) {
// specific known special validations
if (element.getType().equals(BUNDLE)) {
new BundleValidator(context, serverBase, this, xverManager).validateBundle(errors, element, stack, checkSpecials, hostContext);
new BundleValidator(context, serverBase, this, xverManager, jurisdiction).validateBundle(errors, element, stack, checkSpecials, hostContext);
} else if (element.getType().equals("Observation")) {
validateObservation(errors, element, stack);
} else if (element.getType().equals("Questionnaire")) {
new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker, questionnaireMode, xverManager).validateQuestionannaire(errors, element, element, stack);
new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker, questionnaireMode, xverManager, jurisdiction).validateQuestionannaire(errors, element, element, stack);
} else if (element.getType().equals("QuestionnaireResponse")) {
new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker, questionnaireMode, xverManager).validateQuestionannaireResponse(hostContext, errors, element, stack);
new QuestionnaireValidator(context, myEnableWhenEvaluator, fpe, timeTracker, questionnaireMode, xverManager, jurisdiction).validateQuestionannaireResponse(hostContext, errors, element, stack);
} else if (element.getType().equals("Measure")) {
new MeasureValidator(context, timeTracker, xverManager).validateMeasure(hostContext, errors, element, stack);
new MeasureValidator(context, timeTracker, xverManager, jurisdiction).validateMeasure(hostContext, errors, element, stack);
} else if (element.getType().equals("MeasureReport")) {
new MeasureValidator(context, timeTracker, xverManager).validateMeasureReport(hostContext, errors, element, stack);
new MeasureValidator(context, timeTracker, xverManager, jurisdiction).validateMeasureReport(hostContext, errors, element, stack);
} else if (element.getType().equals("CapabilityStatement")) {
validateCapabilityStatement(errors, element, stack);
} else if (element.getType().equals("CodeSystem")) {
new CodeSystemValidator(context, timeTracker, xverManager).validateCodeSystem(errors, element, stack, baseOptions.setLanguage(stack.getWorkingLang()));
new CodeSystemValidator(context, timeTracker, xverManager, jurisdiction).validateCodeSystem(errors, element, stack, baseOptions.setLanguage(stack.getWorkingLang()));
} else if (element.getType().equals("SearchParameter")) {
new SearchParameterValidator(context, timeTracker, fpe, xverManager).validateSearchParameter(errors, element, stack);
new SearchParameterValidator(context, timeTracker, fpe, xverManager, jurisdiction).validateSearchParameter(errors, element, stack);
} else if (element.getType().equals("StructureDefinition")) {
new StructureDefinitionValidator(context, timeTracker, fpe, wantCheckSnapshotUnchanged, xverManager).validateStructureDefinition(errors, element, stack);
new StructureDefinitionValidator(context, timeTracker, fpe, wantCheckSnapshotUnchanged, xverManager, jurisdiction).validateStructureDefinition(errors, element, stack);
} else if (element.getType().equals("ValueSet")) {
new ValueSetValidator(context, timeTracker, this, xverManager).validateValueSet(errors, element, stack);
new ValueSetValidator(context, timeTracker, this, xverManager, jurisdiction).validateValueSet(errors, element, stack);
}
}
@ -5954,7 +5954,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
child.setParentForValidator(element);
setParentsInner(child);
}
}
public void setQuestionnaireMode(QuestionnaireMode questionnaireMode) {
@ -5989,4 +5988,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
this.noUnicodeBiDiControlChars = noUnicodeBiDiControlChars;
}
public Coding getJurisdiction() {
return jurisdiction;
}
public IResourceValidator setJurisdiction(Coding jurisdiction) {
this.jurisdiction = jurisdiction;
return this;
}
}

View File

@ -10,6 +10,7 @@ import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
import org.hl7.fhir.r5.model.StructureDefinition;
@ -32,10 +33,11 @@ public class BundleValidator extends BaseValidator {
private String serverBase;
private InstanceValidator validator;
public BundleValidator(IWorkerContext context, String serverBase, InstanceValidator validator, XVerExtensionManager xverManager) {
public BundleValidator(IWorkerContext context, String serverBase, InstanceValidator validator, XVerExtensionManager xverManager, Coding jurisdiction) {
super(context, xverManager);
this.serverBase = serverBase;
this.validator = validator;
this.jurisdiction = jurisdiction;
}
public void validateBundle(List<ValidationMessage> errors, Element bundle, NodeStack stack, boolean checkSpecials, ValidatorHostContext hostContext) {

View File

@ -6,6 +6,7 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.utilities.Utilities;
@ -22,10 +23,12 @@ import ca.uhn.fhir.validation.ValidationResult;
public class CodeSystemValidator extends BaseValidator {
public CodeSystemValidator(IWorkerContext context, TimeTracker timeTracker, XVerExtensionManager xverManager) {
public CodeSystemValidator(IWorkerContext context, TimeTracker timeTracker, XVerExtensionManager xverManager, Coding jurisdiction) {
super(context, xverManager);
source = Source.InstanceValidator;
this.timeTracker = timeTracker;
this.jurisdiction = jurisdiction;
}
public void validateCodeSystem(List<ValidationMessage> errors, Element cs, NodeStack stack, ValidationOptions options) {

View File

@ -42,10 +42,12 @@ import org.w3c.dom.Document;
public class MeasureValidator extends BaseValidator {
public MeasureValidator(IWorkerContext context, TimeTracker timeTracker, XVerExtensionManager xverManager) {
public MeasureValidator(IWorkerContext context, TimeTracker timeTracker, XVerExtensionManager xverManager, Coding jurisdiction) {
super(context, xverManager);
source = Source.InstanceValidator;
this.timeTracker = timeTracker;
this.jurisdiction = jurisdiction;
}
public void validateMeasure(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element element, NodeStack stack) throws FHIRException {

View File

@ -119,13 +119,14 @@ public class QuestionnaireValidator extends BaseValidator {
private FHIRPathEngine fpe;
private QuestionnaireMode questionnaireMode;
public QuestionnaireValidator(IWorkerContext context, EnableWhenEvaluator myEnableWhenEvaluator, FHIRPathEngine fpe, TimeTracker timeTracker, QuestionnaireMode questionnaireMode, XVerExtensionManager xverManager) {
public QuestionnaireValidator(IWorkerContext context, EnableWhenEvaluator myEnableWhenEvaluator, FHIRPathEngine fpe, TimeTracker timeTracker, QuestionnaireMode questionnaireMode, XVerExtensionManager xverManager, Coding jurisdiction) {
super(context, xverManager);
source = Source.InstanceValidator;
this.myEnableWhenEvaluator = myEnableWhenEvaluator;
this.fpe = fpe;
this.timeTracker = timeTracker;
this.questionnaireMode = questionnaireMode;
this.jurisdiction = jurisdiction;
}
public void validateQuestionannaire(List<ValidationMessage> errors, Element element, Element element2, NodeStack stack) {

View File

@ -7,6 +7,7 @@ import java.util.List;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ExpressionNode;
import org.hl7.fhir.r5.model.ExpressionNode.Kind;
import org.hl7.fhir.r5.model.ExpressionNode.Operation;
@ -35,11 +36,12 @@ public class SearchParameterValidator extends BaseValidator {
private FHIRPathEngine fpe;
public SearchParameterValidator(IWorkerContext context, TimeTracker timeTracker, FHIRPathEngine fpe, XVerExtensionManager xverManager) {
public SearchParameterValidator(IWorkerContext context, TimeTracker timeTracker, FHIRPathEngine fpe, XVerExtensionManager xverManager, Coding jurisdiction) {
super(context, xverManager);
source = Source.InstanceValidator;
this.fpe = fpe;
this.timeTracker = timeTracker;
this.jurisdiction = jurisdiction;
}
public void validateSearchParameter(List<ValidationMessage> errors, Element cs, NodeStack stack) {

View File

@ -56,12 +56,13 @@ public class StructureDefinitionValidator extends BaseValidator {
private FHIRPathEngine fpe;
private boolean wantCheckSnapshotUnchanged;
public StructureDefinitionValidator(IWorkerContext context, TimeTracker timeTracker, FHIRPathEngine fpe, boolean wantCheckSnapshotUnchanged, XVerExtensionManager xverManager) {
public StructureDefinitionValidator(IWorkerContext context, TimeTracker timeTracker, FHIRPathEngine fpe, boolean wantCheckSnapshotUnchanged, XVerExtensionManager xverManager, Coding jurisdiction) {
super(context, xverManager);
source = Source.InstanceValidator;
this.fpe = fpe;
this.timeTracker = timeTracker;
this.wantCheckSnapshotUnchanged = wantCheckSnapshotUnchanged;
this.jurisdiction = jurisdiction;
}
public void validateStructureDefinition(List<ValidationMessage> errors, Element src, NodeStack stack) {

View File

@ -43,11 +43,13 @@ public class ValueSetValidator extends BaseValidator {
private InstanceValidator parent;
public ValueSetValidator(IWorkerContext context, TimeTracker timeTracker, InstanceValidator parent, XVerExtensionManager xverManager) {
public ValueSetValidator(IWorkerContext context, TimeTracker timeTracker, InstanceValidator parent, XVerExtensionManager xverManager, Coding jurisdiction) {
super(context, xverManager);
source = Source.InstanceValidator;
this.timeTracker = timeTracker;
this.parent = parent;
this.jurisdiction = jurisdiction;
}
public void validateValueSet(List<ValidationMessage> errors, Element vs, NodeStack stack) {