Refactor how observation profiles are registered in order to generalise management of extra profiles

This commit is contained in:
Grahame Grieve 2024-06-01 22:54:17 +10:00
parent 04e95f4e05
commit 2f38cb544c
12 changed files with 190 additions and 171 deletions

View File

@ -0,0 +1,11 @@
package org.hl7.fhir.r5.utils.validation;
import java.util.List;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
public interface IMessagingServices {
ValidationMessage signpost(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, String theMessage, Object... theMessageArguments);
}

View File

@ -31,6 +31,7 @@ package org.hl7.fhir.r5.utils.validation;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
@ -54,6 +55,8 @@ import java.util.List;
*/ */
public interface IResourceValidator { public interface IResourceValidator {
IWorkerContext getContext();
/** /**
* how much to check displays for coded elements * how much to check displays for coded elements
*/ */

View File

@ -10,7 +10,6 @@ import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.validation.instance.BasePolicyAdvisorForMandatoryProfiles;
import org.hl7.fhir.r5.utils.validation.constants.CodedContentValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.CodedContentValidationPolicy;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.ElementValidationAction; import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.ElementValidationAction;
import org.hl7.fhir.r5.utils.validation.constants.BindingKind; import org.hl7.fhir.r5.utils.validation.constants.BindingKind;
@ -135,7 +134,7 @@ public interface IValidationPolicyAdvisor {
/** /**
* This is called after a resource has been validated against the base structure, * This is called after a resource has been validated against the base structure,
* but before any profiles specified in .meta.profile or in the parameters are applied. * but before it's validated against any profiles specified in .meta.profile or in the parameters.
* This can be used to determine what additional profiles should be applied, for instance * This can be used to determine what additional profiles should be applied, for instance
* those derived from the http://hl7.org/fhir/tools/StructureDefinition/profile-mapping extension * those derived from the http://hl7.org/fhir/tools/StructureDefinition/profile-mapping extension
* *
@ -144,9 +143,9 @@ public interface IValidationPolicyAdvisor {
* might be any version from R2-R6) * might be any version from R2-R6)
* *
* The base implementation applies the mandatory vital signs to observations that have LOINC or SNOMED CT * The base implementation applies the mandatory vital signs to observations that have LOINC or SNOMED CT
* codes that indicate that they are vital signs. Note that these profiles are not optional; all resources * codes that indicate that they are vital signs. Note that these profiles are not optional; all vital sign resources
* are required to conform to them. For this reason, if you're providing your own policy advisor, you should * are required to conform to them. For this reason, if you're providing your own policy advisor, you should
* keep a reference to the default one, or call BasePolicyAdvisorForMandatoryProfiles. You can choose not to, * keep a reference to the default one, or call BasePolicyAdvisorForFullValidation directly. You can choose not to,
* but if you do, you are allowing for resources that deviate from the FHIR specification (in a way that the * but if you do, you are allowing for resources that deviate from the FHIR specification (in a way that the
* community considers clinically unsafe, since it means that software (probably) will miss vital signs for * community considers clinically unsafe, since it means that software (probably) will miss vital signs for
* patients). * patients).
@ -161,13 +160,14 @@ public interface IValidationPolicyAdvisor {
* @param messages all the validation messages. Implementations can inspect this, but the real purpose is to populate the messages with information messages explaining why profiles were (or weren't) applied * @param messages all the validation messages. Implementations can inspect this, but the real purpose is to populate the messages with information messages explaining why profiles were (or weren't) applied
* @return * @return
*/ */
List<StructureDefinition> getImpliedProfilesForInstance(IResourceValidator validator, List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator,
Object appContext, Object appContext,
String stackPath, String stackPath,
ElementDefinition definition, ElementDefinition definition,
StructureDefinition structure, StructureDefinition structure,
Element resource, Element resource,
boolean valid, boolean valid,
IMessagingServices msgServices,
List<ValidationMessage> messages); List<ValidationMessage> messages);
} }

View File

@ -67,6 +67,7 @@ import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus; import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus;
import org.hl7.fhir.r5.utils.validation.IMessagingServices;
import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher; import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.IValidationContextResourceLoader; import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.IValidationContextResourceLoader;
@ -87,7 +88,7 @@ import org.hl7.fhir.validation.cli.utils.ValidationLevel;
import org.hl7.fhir.validation.instance.utils.IndexedElement; import org.hl7.fhir.validation.instance.utils.IndexedElement;
import org.hl7.fhir.validation.instance.utils.NodeStack; import org.hl7.fhir.validation.instance.utils.NodeStack;
public class BaseValidator implements IValidationContextResourceLoader { public class BaseValidator implements IValidationContextResourceLoader, IMessagingServices {
public static class BooleanHolder { public static class BooleanHolder {
private boolean value = true; private boolean value = true;
@ -411,7 +412,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
return thePass; return thePass;
} }
protected ValidationMessage signpost(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, String theMessage, Object... theMessageArguments) { public ValidationMessage signpost(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, String theMessage, Object... theMessageArguments) {
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
return addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage).setSignpost(true); return addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage).setSignpost(true);
} }

View File

@ -67,6 +67,7 @@ import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities; import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities;
import org.hl7.fhir.r5.utils.validation.BundleValidationRule; import org.hl7.fhir.r5.utils.validation.BundleValidationRule;
import org.hl7.fhir.r5.utils.validation.IMessagingServices;
import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher; import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
@ -104,6 +105,7 @@ import org.hl7.fhir.validation.cli.utils.ProfileLoader;
import org.hl7.fhir.validation.cli.utils.QuestionnaireMode; import org.hl7.fhir.validation.cli.utils.QuestionnaireMode;
import org.hl7.fhir.validation.cli.utils.SchemaValidator; import org.hl7.fhir.validation.cli.utils.SchemaValidator;
import org.hl7.fhir.validation.cli.utils.ValidationLevel; import org.hl7.fhir.validation.cli.utils.ValidationLevel;
import org.hl7.fhir.validation.instance.BasePolicyAdvisorForFullValidation;
import org.hl7.fhir.validation.instance.InstanceValidator; import org.hl7.fhir.validation.instance.InstanceValidator;
import org.hl7.fhir.validation.instance.utils.ValidationContext; import org.hl7.fhir.validation.instance.utils.ValidationContext;
import org.hl7.fhir.utilities.ByteProvider; import org.hl7.fhir.utilities.ByteProvider;
@ -1253,4 +1255,12 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
return res; return res;
} }
@Override
public List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator, Object appContext,
String stackPath, ElementDefinition definition, StructureDefinition structure, Element resource, boolean valid,
IMessagingServices msgServices, List<ValidationMessage> messages) {
return new BasePolicyAdvisorForFullValidation().getImpliedProfilesForResource(validator, appContext, stackPath,
definition, structure, resource, valid, msgServices, messages);
}
} }

View File

@ -42,11 +42,12 @@ import org.hl7.fhir.utilities.json.parser.JsonParser;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager; import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage; import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.validation.cli.utils.Common; import org.hl7.fhir.validation.cli.utils.Common;
import org.hl7.fhir.validation.instance.BasePolicyAdvisorForFullValidation;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IValidationPolicyAdvisor, IWorkerContextManager.ICanonicalResourceLocator { public class StandAloneValidatorFetcher extends BasePolicyAdvisorForFullValidation implements IValidatorResourceFetcher, IValidationPolicyAdvisor, IWorkerContextManager.ICanonicalResourceLocator {
List<String> mappingsUris = new ArrayList<>(); List<String> mappingsUris = new ArrayList<>();
private FilesystemPackageCacheManager pcm; private FilesystemPackageCacheManager pcm;
@ -76,31 +77,6 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IV
return ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS; return ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS;
} }
@Override
public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator,
Object appContext,
StructureDefinition structure,
ElementDefinition element,
String containerType,
String containerId,
Element.SpecialElement containingResourceType,
String path,
String url) {
return ContainedReferenceValidationPolicy.CHECK_VALID;
}
@Override
public EnumSet<ResourceValidationAction> policyForResource(IResourceValidator validator, Object appContext,
StructureDefinition type, String path) {
return EnumSet.allOf(ResourceValidationAction.class);
}
@Override
public EnumSet<ElementValidationAction> policyForElement(IResourceValidator validator, Object appContext,
StructureDefinition structure, ElementDefinition element, String path) {
return EnumSet.allOf(ElementValidationAction.class);
}
@Override @Override
public boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type, boolean canonical) throws IOException, FHIRException { public boolean resolveURL(IResourceValidator validator, Object appContext, String path, String url, String type, boolean canonical) throws IOException, FHIRException {
if (!Utilities.isAbsoluteUrl(url)) { if (!Utilities.isAbsoluteUrl(url)) {
@ -316,19 +292,6 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IV
} }
} }
@Override
public EnumSet<CodedContentValidationAction> policyForCodedContent(IResourceValidator validator,
Object appContext,
String stackPath,
ElementDefinition definition,
StructureDefinition structure,
BindingKind kind,
AdditionalBindingPurpose purpose,
ValueSet valueSet,
List<String> systems) {
return EnumSet.allOf(CodedContentValidationAction.class);
}
@Override @Override
public Set<String> fetchCanonicalResourceVersions(IResourceValidator validator, Object appContext, String url) { public Set<String> fetchCanonicalResourceVersions(IResourceValidator validator, Object appContext, String url) {
return new HashSet<>(); return new HashSet<>();

View File

@ -1,65 +1,166 @@
package org.hl7.fhir.validation.instance; package org.hl7.fhir.validation.instance;
import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.elementmodel.Element.SpecialElement; import org.hl7.fhir.r5.elementmodel.Element.SpecialElement;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.utils.validation.IMessagingServices;
import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.AdditionalBindingPurpose;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.CodedContentValidationAction;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.ElementValidationAction;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.ResourceValidationAction;
import org.hl7.fhir.r5.utils.validation.constants.BindingKind; import org.hl7.fhir.r5.utils.validation.constants.BindingKind;
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
public class BasePolicyAdvisorForFullValidation implements IValidationPolicyAdvisor { public class BasePolicyAdvisorForFullValidation implements IValidationPolicyAdvisor {
@Override @Override
public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, String url) {
String url) { return ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS;
// TODO Auto-generated method stub
return null;
} }
@Override @Override
public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, Object appContext, public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, Object appContext,
StructureDefinition structure, ElementDefinition element, String containerType, String containerId, StructureDefinition structure, ElementDefinition element, String containerType, String containerId,
SpecialElement containingResourceType, String path, String url) { SpecialElement containingResourceType, String path, String url) {
// TODO Auto-generated method stub
return null; return ContainedReferenceValidationPolicy.CHECK_VALID;
} }
@Override @Override
public EnumSet<ResourceValidationAction> policyForResource(IResourceValidator validator, Object appContext, public EnumSet<ResourceValidationAction> policyForResource(IResourceValidator validator, Object appContext,
StructureDefinition type, String path) { StructureDefinition type, String path) {
// TODO Auto-generated method stub return EnumSet.allOf(ResourceValidationAction.class);
return null;
} }
@Override @Override
public EnumSet<ElementValidationAction> policyForElement(IResourceValidator validator, Object appContext, public EnumSet<ElementValidationAction> policyForElement(IResourceValidator validator, Object appContext,
StructureDefinition structure, ElementDefinition element, String path) { StructureDefinition structure, ElementDefinition element, String path) {
// TODO Auto-generated method stub return EnumSet.allOf(ElementValidationAction.class);
return null;
} }
@Override @Override
public EnumSet<CodedContentValidationAction> policyForCodedContent(IResourceValidator validator, Object appContext, public EnumSet<CodedContentValidationAction> policyForCodedContent(IResourceValidator validator,
String stackPath, ElementDefinition definition, StructureDefinition structure, BindingKind kind, Object appContext,
AdditionalBindingPurpose purpose, ValueSet valueSet, List<String> systems) { String stackPath,
// TODO Auto-generated method stub ElementDefinition definition,
return null; StructureDefinition structure,
BindingKind kind,
AdditionalBindingPurpose purpose,
ValueSet valueSet,
List<String> systems) {
return EnumSet.allOf(CodedContentValidationAction.class);
} }
@Override @Override
public List<StructureDefinition> getImpliedProfilesForInstance(IResourceValidator validator, Object appContext, public List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator, Object appContext,
String stackPath, ElementDefinition definition, StructureDefinition structure, Element resource, boolean valid, String stackPath, ElementDefinition definition, StructureDefinition structure, Element resource, boolean valid,
List<ValidationMessage> messages) { IMessagingServices msgServices, List<ValidationMessage> messages) {
// TODO Auto-generated method stub List<StructureDefinition> profiles = new ArrayList<StructureDefinition>();
return null; if ("Observation".equals(resource.fhirType()) && VersionUtilities.isR4Plus(validator.getContext().getVersion())) {
getImpliedProfilesForObservation(profiles, msgServices, messages, validator.getContext(), stackPath, resource);
}
return profiles;
} }
private void getImpliedProfilesForObservation(List<StructureDefinition> profiles, IMessagingServices msgServices, List<ValidationMessage> messages, IWorkerContext context, String stackPath, Element resource) {
Element code = resource.getNamedChild("code", false);
List<String> codes = new ArrayList<>();
if (hasLoincCode(code, codes, "85353-1")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/vitalspanel", "Vital Signs Panel", "LOINC", codes);
} else if (hasLoincCode(code, codes, "9279-1", "76170-0", "76172-6", "76171-8", "19840-8", "33438-3", "76270-8", "11291-2")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/resprate", "Respiratory Rate", "LOINC", codes);
} else if (hasLoincCode(code, codes, "60978-4", "73795-7", "73799-9", "76476-1", "76477-9", "8867-4", "8889-8", "8890-6", "8891-4", "8892-2", "8893-0", "40443-4", "55425-3", "68999-2", "11328-2", "69000-8", "69000-8", "60978-4", "60978-4", "8890-6", "8886-4", "68999-2", "68999-2")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/heartrate", "Heart rate", "LOINC", codes);
} else if (hasLoincCode(code, codes, "2708-6", "19224-5", "20564-1", "2709-4", "2710-2", "2713-6", "51733-4", "59408-5", "59417-6", "89276-0", "97549-0")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/oxygensat", "Oxygen saturation", "LOINC", codes);
} else if (hasLoincCode(code, codes, "8310-5", "60834-9", "60835-6", "60836-4", "60838-0", "60955-2", "61009-7", "75539-7", "75987-8", "76010-8", "76011-6", "76278-1", "8309-7", "8310-5", "8328-7", "8329-5", "8330-3", "8331-1", "8332-9", "8333-7", "8334-5", "91371-5", "98657-0", "98663-8")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bodytemp", "Body temperature", "LOINC", codes);
} else if (hasLoincCode(code, codes, "8302-2", "3137-7", "3138-5", "8302-2", "8306-3", "8308-9")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bodyheight", "Body height", "LOINC", codes);
} else if (hasLoincCode(code, codes, "9843-4", "8287-5", "9843-4")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/headcircum", "Head circumference", "LOINC", codes);
} else if (hasLoincCode(code, codes, "29463-7", "29463-7", "3141-9", "3142-7", "75292-3", "79348-9", "8350-1", "8351-9")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bodyweight", "Body weight", "LOINC", codes);
} else if (hasLoincCode(code, codes, "39156-5", "39156-5", "59574-4", "89270-3")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bmi", "Body mass index", "LOINC", codes);
} else if (hasLoincCode(code, codes, "85354-9", "35094-2", "8459-0", "85354-9", "76534-7", "55284-4", "8480-6")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bp", "Blood pressure systolic and diastolic", "LOINC", codes);
} else if (hasSctCode(code, codes, "46680005")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/vitalspanel", "Vital Signs Panel", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "86290005", "271625008", "271306003")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bp", "Blood pressure systolic and diastolic", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "271306003", "249043002", "444981005", "399017001", "251670001", "429525003", "429614003")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/heartrate", "Heart rate", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "103228002", "103228002", "442349007", "442476006", "442440005", "431314004", "442734002", "713194001")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/oxygensat", "Oxygen saturation", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "386725007", "276885007", "300076005", "1222808002", "364246006", "307047009", "708499008", "708499008", "431598003", "698831002", "698832009", "415882003", "415974002", "415929009", "415945006")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bodytemp", "Body temperature", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "1153637007", "1162419008", "50373000", "1162418000", "1230278008", "1162392001", "1162417005")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bodyheight", "Body height", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "363812007", "169876006", "1269262007", "363811000")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/headcircum", "Head circumference", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "363811000", "60621009", "735395000", "425024002", "424927000", "784399000", "1162416001", "1162415002")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bodyweight", "Body weight", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "60621009")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bmi", "Body mass index", "SNOMED CT", codes);
} else if (hasSctCode(code, codes, "75367002", "251076008", "163033001", "163035008", "386534000", "386536003", "271649006", "271649006", "271650006", "407556006", "407554009", "716579001", "399304008")) {
addProfile(profiles, msgServices, messages, context, stackPath, resource, "http://hl7.org/fhir/StructureDefinition/bp", "Blood pressure systolic and diastolic", "SNOMED CT", codes);
}
}
private void addProfile(List<StructureDefinition> profiles, IMessagingServices msgServices, List<ValidationMessage> messages, IWorkerContext context, String stackPath, Element resource, String url, String name, String systemName, List<String> codes) {
resource.addMessage(msgServices.signpost(messages, null, IssueType.INFORMATIONAL, resource.line(), resource.col(), stackPath, I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_OBS, url, name, systemName, codes.get(0)));
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
if (sd != null) {
profiles.add(sd);
} else {
// complain?
}
}
protected boolean hasLoincCode(Element code, List<String> codes, String... values) {
if (code != null) {
List<Element> codings = code.getChildren("coding");
for (Element coding : codings) {
if ("http://loinc.org".equals(coding.getNamedChildValue("system", false)) && Utilities.existsInList(coding.getNamedChildValue("code", false), values)) {
codes.add(coding.getNamedChildValue("code", false));
return true;
}
}
}
return false;
}
protected boolean hasSctCode(Element code, List<String> codes, String... values) {
if (code != null) {
List<Element> codings = code.getChildren("coding");
for (Element coding : codings) {
if ("http://snomed.info/sct".equals(coding.getNamedChildValue("system", false)) && Utilities.existsInList(coding.getNamedChildValue("code", false), values)) {
codes.add(coding.getNamedChildValue("code", false));
return true;
}
}
}
return false;
}
} }

View File

@ -173,6 +173,7 @@ import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus; import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus;
import org.hl7.fhir.r5.utils.sql.Validator; import org.hl7.fhir.r5.utils.sql.Validator;
import org.hl7.fhir.r5.utils.validation.BundleValidationRule; import org.hl7.fhir.r5.utils.validation.BundleValidationRule;
import org.hl7.fhir.r5.utils.validation.IMessagingServices;
import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
import org.hl7.fhir.r5.utils.validation.IValidationProfileUsageTracker; import org.hl7.fhir.r5.utils.validation.IValidationProfileUsageTracker;
@ -595,7 +596,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean noBindingMsgSuppressed; private boolean noBindingMsgSuppressed;
private Map<String, Element> fetchCache = new HashMap<>(); private Map<String, Element> fetchCache = new HashMap<>();
private HashMap<Element, ResourceValidationTracker> resourceTracker = new HashMap<>(); private HashMap<Element, ResourceValidationTracker> resourceTracker = new HashMap<>();
private IValidationPolicyAdvisor policyAdvisor; private IValidationPolicyAdvisor policyAdvisor = new BasePolicyAdvisorForFullValidation();
long time = 0; long time = 0;
long start = 0; long start = 0;
long lastlog = 0; long lastlog = 0;
@ -691,6 +692,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
@Override @Override
public IResourceValidator setPolicyAdvisor(IValidationPolicyAdvisor advisor) { public IResourceValidator setPolicyAdvisor(IValidationPolicyAdvisor advisor) {
if (advisor == null) {
throw new Error("Cannot set advisor to null");
}
this.policyAdvisor = advisor; this.policyAdvisor = advisor;
return this; return this;
} }
@ -3111,7 +3115,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
if (!found) { if (!found) {
if (type.equals("canonical")) { if (type.equals("canonical")) {
ReferenceValidationPolicy rp = policyAdvisor == null ? ReferenceValidationPolicy.CHECK_VALID : policyAdvisor.policyForReference(this, valContext, path, url); ReferenceValidationPolicy rp = policyAdvisor.policyForReference(this, valContext, path, url);
if (rp == ReferenceValidationPolicy.CHECK_EXISTS || rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE) { if (rp == ReferenceValidationPolicy.CHECK_EXISTS || rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE) {
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_CANONICAL_RESOLVE, url) && ok;
} else { } else {
@ -3128,7 +3132,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} else { } else {
if (type.equals("canonical")) { if (type.equals("canonical")) {
ReferenceValidationPolicy rp = policyAdvisor == null ? ReferenceValidationPolicy.CHECK_VALID : policyAdvisor.policyForReference(this, valContext, path, url); ReferenceValidationPolicy rp = policyAdvisor.policyForReference(this, valContext, path, url);
if (rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE || rp == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS || rp == ReferenceValidationPolicy.CHECK_VALID) { if (rp == ReferenceValidationPolicy.CHECK_EXISTS_AND_TYPE || rp == ReferenceValidationPolicy.CHECK_TYPE_IF_EXISTS || rp == ReferenceValidationPolicy.CHECK_VALID) {
try { try {
Resource r = null; Resource r = null;
@ -3581,8 +3585,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ok = false; ok = false;
} }
} else { } else {
EnumSet<CodedContentValidationAction> validationPolicy = getPolicyAdvisor() == null ? EnumSet<CodedContentValidationAction> validationPolicy = policyAdvisor.policyForCodedContent(this, valContext, stack.getLiteralPath(), elementContext, profile, BindingKind.PRIMARY, null, vs, new ArrayList<>());
EnumSet.allOf(CodedContentValidationAction.class) : getPolicyAdvisor().policyForCodedContent(this, valContext, stack.getLiteralPath(), elementContext, profile, BindingKind.PRIMARY, null, vs, new ArrayList<>());
if (!validationPolicy.isEmpty()) { if (!validationPolicy.isEmpty()) {
long t = System.nanoTime(); long t = System.nanoTime();
@ -3918,11 +3921,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (refType.equals("contained") || refType.equals("bundled")) { if (refType.equals("contained") || refType.equals("bundled")) {
pol = ReferenceValidationPolicy.CHECK_VALID; pol = ReferenceValidationPolicy.CHECK_VALID;
} else { } else {
if (policyAdvisor == null) { pol = policyAdvisor.policyForReference(this, valContext.getAppContext(), path, ref);
pol = ReferenceValidationPolicy.IGNORE;
} else {
pol = policyAdvisor.policyForReference(this, valContext.getAppContext(), path, ref);
}
} }
if (conditional) { if (conditional) {
@ -5705,15 +5704,22 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ok = false; ok = false;
} }
if (checkSpecials) { if (checkSpecials) {
ok = checkSpecials(valContext, errors, element, stack, checkSpecials, pct, mode, fromContained) && ok; ok = checkSpecials(valContext, errors, element, stack, checkSpecials, pct, mode, fromContained, ok) && ok;
ok = validateResourceRules(errors, element, stack) && ok; ok = validateResourceRules(errors, element, stack) && ok;
} }
return ok; return ok;
} }
public boolean checkSpecials(ValidationContext valContext, List<ValidationMessage> errors, Element element, NodeStack stack, boolean checkSpecials, PercentageTracker pct, ValidationMode mode, boolean contained) { public boolean checkSpecials(ValidationContext valContext, List<ValidationMessage> errors, Element element, NodeStack stack, boolean checkSpecials, PercentageTracker pct, ValidationMode mode, boolean contained, boolean isOk) {
boolean ok = true; boolean ok = true;
// first, does the policy advisor have profiles it wants us to check?
List<StructureDefinition> profiles = policyAdvisor.getImpliedProfilesForResource(this, valContext.getAppContext(), stack.getLiteralPath(),
element.getProperty().getDefinition(), element.getProperty().getStructure(), element, isOk, this, errors);
for (StructureDefinition sd : profiles) {
ok = startInner(valContext, errors, element, element, sd, stack, false, pct, mode, false) && ok;
}
long t = System.nanoTime(); long t = System.nanoTime();
try { try {
if (VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(element.getType())) { if (VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(element.getType())) {
@ -5966,8 +5972,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else { } else {
SpecialElement special = element.getSpecial(); SpecialElement special = element.getSpecial();
ContainedReferenceValidationPolicy containedValidationPolicy = getPolicyAdvisor() == null ? ContainedReferenceValidationPolicy containedValidationPolicy = policyAdvisor.policyForContained(this,
ContainedReferenceValidationPolicy.CHECK_VALID : getPolicyAdvisor().policyForContained(this,
valContext, parentProfile, child, context.fhirType(), context.getId(), special, path, parentProfile.getUrl()); valContext, parentProfile, child, context.fhirType(), context.getId(), special, path, parentProfile.getUrl());
if (containedValidationPolicy.ignore()) { if (containedValidationPolicy.ignore()) {
@ -6021,7 +6026,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
checkSpecials(valContext, errors, element, stack, ok, pct, mode, true); checkSpecials(valContext, errors, element, stack, ok, pct, mode, true, ok);
if (typeForResource.getProfile().size() == 1) { if (typeForResource.getProfile().size() == 1) {
long t = System.nanoTime(); long t = System.nanoTime();
@ -6427,8 +6432,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (debug) { if (debug) {
System.out.println(" check " + localStack.getLiteralPath()+" against "+ei.getDefinition().getId()+" in profile "+profile.getVersionedUrl()+time()); System.out.println(" check " + localStack.getLiteralPath()+" against "+ei.getDefinition().getId()+" in profile "+profile.getVersionedUrl()+time());
} }
EnumSet<ElementValidationAction> actionSet = policyAdvisor == null ? EnumSet.allOf(ElementValidationAction.class) : EnumSet<ElementValidationAction> actionSet = policyAdvisor.policyForElement(this, valContext.getAppContext(), profile, ei.getDefinition(), localStack.getLiteralPath());
policyAdvisor.policyForElement(this, valContext.getAppContext(), profile, ei.getDefinition(), localStack.getLiteralPath());
String localStackLiteralPath = localStack.getLiteralPath(); String localStackLiteralPath = localStack.getLiteralPath();
String eiPath = ei.getPath(); String eiPath = ei.getPath();

View File

@ -181,7 +181,7 @@ public class BundleValidator extends BaseValidator {
} }
} }
// also, while we're here, check the specials, since this doesn't happen anywhere else // also, while we're here, check the specials, since this doesn't happen anywhere else
((InstanceValidator) parent).checkSpecials(hostContext, errors, res, rstack, true, pct, mode, true); ((InstanceValidator) parent).checkSpecials(hostContext, errors, res, rstack, true, pct, mode, true, ok);
} }
// todo: check specials // todo: check specials

View File

@ -38,92 +38,8 @@ public class ObservationValidator extends BaseValidator {
element.getNamedChild("effectiveTiming", false) != null || element.getNamedChild("effectiveInstant", false) != null, element.getNamedChild("effectiveTiming", false) != null || element.getNamedChild("effectiveInstant", false) != null,
I18nConstants.ALL_OBSERVATIONS_SHOULD_HAVE_AN_EFFECTIVEDATETIME_OR_AN_EFFECTIVEPERIOD, element.getProperty().typeSummary()) && ok; I18nConstants.ALL_OBSERVATIONS_SHOULD_HAVE_AN_EFFECTIVEDATETIME_OR_AN_EFFECTIVEPERIOD, element.getProperty().typeSummary()) && ok;
// hook in the vital signs // Looking for the vital signs code? It's moved to BasePolicyAdvisorForFullValidation.getImpliedProfilesForObservation
if (VersionUtilities.isR4Plus(context.getVersion())) {
Element code = element.getNamedChild("code", false);
List<String> codes = new ArrayList<>();
if (hasLoincCode(code, codes, "85353-1")) {
ok = checkObservationAgainstProfile(valContext, errors, element, stack, "http://hl7.org/fhir/StructureDefinition/vitalspanel", "Vital Signs Panel", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "9279-1", "76170-0", "76172-6", "76171-8", "19840-8", "33438-3", "76270-8", "11291-2")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/resprate", "Respiratory Rate", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "60978-4", "73795-7", "73799-9", "76476-1", "76477-9", "8867-4", "8889-8", "8890-6", "8891-4", "8892-2", "8893-0", "40443-4", "55425-3", "68999-2", "11328-2", "69000-8", "69000-8", "60978-4", "60978-4", "8890-6", "8886-4", "68999-2", "68999-2")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/heartrate", "Heart rate", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "2708-6", "19224-5", "20564-1", "2709-4", "2710-2", "2713-6", "51733-4", "59408-5", "59417-6", "89276-0", "97549-0")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/oxygensat", "Oxygen saturation", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "8310-5", "60834-9", "60835-6", "60836-4", "60838-0", "60955-2", "61009-7", "75539-7", "75987-8", "76010-8", "76011-6", "76278-1", "8309-7", "8310-5", "8328-7", "8329-5", "8330-3", "8331-1", "8332-9", "8333-7", "8334-5", "91371-5", "98657-0", "98663-8")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bodytemp", "Body temperature", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "8302-2", "3137-7", "3138-5", "8302-2", "8306-3", "8308-9")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bodyheight", "Body height", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "9843-4", "8287-5", "9843-4")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/headcircum", "Head circumference", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "29463-7", "29463-7", "3141-9", "3142-7", "75292-3", "79348-9", "8350-1", "8351-9")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bodyweight", "Body weight", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "39156-5", "39156-5", "59574-4", "89270-3")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bmi", "Body mass index", "LOINC", codes, pct, mode) && ok;
} else if (hasLoincCode(code, codes, "85354-9", "35094-2", "8459-0", "85354-9", "76534-7", "55284-4", "8480-6")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bp", "Blood pressure systolic and diastolic", "LOINC", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "46680005")) {
ok = checkObservationAgainstProfile(valContext, errors, element, stack, "http://hl7.org/fhir/StructureDefinition/vitalspanel", "Vital Signs Panel", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "86290005", "271625008", "271306003")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "Blood pressure systolic and diastolic", "Respiratory Rate", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "271306003", "249043002", "444981005", "399017001", "251670001", "429525003", "429614003")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/heartrate", "Heart rate", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "103228002", "103228002", "442349007", "442476006", "442440005", "431314004", "442734002", "713194001")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/oxygensat", "Oxygen saturation", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "386725007", "276885007", "300076005", "1222808002", "364246006", "307047009", "708499008", "708499008", "431598003", "698831002", "698832009", "415882003", "415974002", "415929009", "415945006")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bodytemp", "Body temperature", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "1153637007", "1162419008", "50373000", "1162418000", "1230278008", "1162392001", "1162417005")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bodyheight", "Body height", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "363812007", "169876006", "1269262007", "363811000")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/headcircum", "Head circumference", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "363811000", "60621009", "735395000", "425024002", "424927000", "784399000", "1162416001", "1162415002")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bodyweight", "Body weight", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "60621009")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bmi", "Body mass index", "SNOMED CT", codes, pct, mode) && ok;
} else if (hasSctCode(code, codes, "75367002", "251076008", "163033001", "163035008", "386534000", "386536003", "271649006", "271649006", "271650006", "407556006", "407554009", "716579001", "399304008")) {
ok = checkObservationAgainstProfile(valContext,errors, element, stack, "http://hl7.org/fhir/StructureDefinition/bp", "Blood pressure systolic and diastolic", "SNOMED CT", codes, pct, mode) && ok;
}
}
return ok; return ok;
} }
private boolean checkObservationAgainstProfile(ValidationContext valContext, List<ValidationMessage> errors, Element element, NodeStack stack, String url, String name, String sys, List<String> loinc, PercentageTracker pct, ValidationMode mode) {
element.addMessage(signpost(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_OBS, url, name, sys, loinc.get(0)));
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
if (sd == null) {
return false;
} else {
return ((InstanceValidator) parent).startInner(valContext, errors, element, element, sd, stack, false, pct, mode, false);
}
}
private boolean hasLoincCode(Element code, List<String> codes, String... values) {
if (code != null) {
List<Element> codings = code.getChildren("coding");
for (Element coding : codings) {
if ("http://loinc.org".equals(coding.getNamedChildValue("system", false)) && Utilities.existsInList(coding.getNamedChildValue("code", false), values)) {
codes.add(coding.getNamedChildValue("code", false));
return true;
}
}
}
return false;
}
private boolean hasSctCode(Element code, List<String> codes, String... values) {
if (code != null) {
List<Element> codings = code.getChildren("coding");
for (Element coding : codings) {
if ("http://snomed.info/sct".equals(coding.getNamedChildValue("system", false)) && Utilities.existsInList(coding.getNamedChildValue("code", false), values)) {
codes.add(coding.getNamedChildValue("code", false));
return true;
}
}
}
return false;
}
} }

View File

@ -59,6 +59,7 @@ import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.r5.utils.OperationOutcomeUtilities; import org.hl7.fhir.r5.utils.OperationOutcomeUtilities;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.validation.BundleValidationRule; import org.hl7.fhir.r5.utils.validation.BundleValidationRule;
import org.hl7.fhir.r5.utils.validation.IMessagingServices;
import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher; import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
@ -90,6 +91,7 @@ import org.hl7.fhir.validation.ValidationEngine;
import org.hl7.fhir.validation.ValidatorUtils; import org.hl7.fhir.validation.ValidatorUtils;
import org.hl7.fhir.validation.cli.model.HtmlInMarkdownCheck; import org.hl7.fhir.validation.cli.model.HtmlInMarkdownCheck;
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher; import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher;
import org.hl7.fhir.validation.instance.BasePolicyAdvisorForFullValidation;
import org.hl7.fhir.validation.instance.InstanceValidator; import org.hl7.fhir.validation.instance.InstanceValidator;
import org.hl7.fhir.validation.tests.utilities.TestUtilities; import org.hl7.fhir.validation.tests.utilities.TestUtilities;
import org.junit.AfterClass; import org.junit.AfterClass;
@ -469,7 +471,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
} }
private ValidationEngine buildVersionEngine(String ver, String txLog) throws Exception { private ValidationEngine buildVersionEngine(String ver, String txLog) throws Exception {
String server = FhirSettings.getTxFhirLocal(); String server = FhirSettings.getTxFhirDevelopment();
switch (ver) { switch (ver) {
case "1.0": return TestUtilities.getValidationEngine("hl7.fhir.r2.core#1.0.2", server, txLog, FhirPublication.DSTU2, true, "1.0.2"); case "1.0": return TestUtilities.getValidationEngine("hl7.fhir.r2.core#1.0.2", server, txLog, FhirPublication.DSTU2, true, "1.0.2");
case "1.4": return TestUtilities.getValidationEngine("hl7.fhir.r2b.core#1.4.0", server, txLog, FhirPublication.DSTU2016May, true, "1.4.0"); case "1.4": return TestUtilities.getValidationEngine("hl7.fhir.r2b.core#1.4.0", server, txLog, FhirPublication.DSTU2016May, true, "1.4.0");
@ -887,4 +889,12 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
public Set<String> fetchCanonicalResourceVersions(IResourceValidator validator, Object appContext, String url) { public Set<String> fetchCanonicalResourceVersions(IResourceValidator validator, Object appContext, String url) {
return new HashSet<>(); return new HashSet<>();
} }
@Override
public List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator, Object appContext,
String stackPath, ElementDefinition definition, StructureDefinition structure, Element resource, boolean valid,
IMessagingServices msgServices, List<ValidationMessage> messages) {
return new BasePolicyAdvisorForFullValidation().getImpliedProfilesForResource(validator, appContext, stackPath,
definition, structure, resource, valid, msgServices, messages);
}
} }

View File

@ -21,7 +21,7 @@
<commons_compress_version>1.26.0</commons_compress_version> <commons_compress_version>1.26.0</commons_compress_version>
<guava_version>32.0.1-jre</guava_version> <guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version> <hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.5.10</validator_test_case_version> <validator_test_case_version>1.5.11-SNAPSHOT</validator_test_case_version>
<jackson_version>2.17.0</jackson_version> <jackson_version>2.17.0</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version> <junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version> <junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>