diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java index a1bad4902..5b529d4eb 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java @@ -176,6 +176,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi protected XVerExtensionManager xverManager; protected IValidatorResourceFetcher fetcher; protected IValidationPolicyAdvisor policyAdvisor; + protected boolean noTerminologyChecks; // these two related to removing warnings on extensible bindings in structures that have derivatives that replace their bindings protected List trackedMessages = new ArrayList<>(); @@ -235,6 +236,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi this.baseOptions = parent.baseOptions; this.fetcher = parent.fetcher; this.policyAdvisor = parent.policyAdvisor; + this.noTerminologyChecks = parent.noTerminologyChecks; } private boolean doingLevel(IssueSeverity error) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/codesystem/CodeSystemChecker.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/codesystem/CodeSystemChecker.java index 3567516fb..e58b7783a 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/codesystem/CodeSystemChecker.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/codesystem/CodeSystemChecker.java @@ -8,6 +8,7 @@ import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.validation.ValidatorSession; 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.IssueType; @@ -76,8 +77,20 @@ public abstract class CodeSystemChecker extends BaseValidator { public PropertyValidationRules rulesForFilter(String property, EnumSet ops) { switch (property) { - case "concept" : return new PropertyValidationRules(PropertyFilterType.Code, CodeValidationRule.Error, addToOps(ops, PropertyOperation.Equals, PropertyOperation.In, PropertyOperation.IsA, PropertyOperation.DescendentOf, PropertyOperation.DescendentLeaf, PropertyOperation.IsNotA, PropertyOperation.NotIn)); - case "code" : return new PropertyValidationRules(PropertyFilterType.Code, CodeValidationRule.Error, addToOps(ops, PropertyOperation.Equals, PropertyOperation.RegEx)); + case "concept" : + return new PropertyValidationRules(PropertyFilterType.Code, CodeValidationRule.Error, + VersionUtilities.isR5Plus(context.getVersion()) ? + addToOps(ops, PropertyOperation.Equals, PropertyOperation.In, PropertyOperation.IsA, PropertyOperation.DescendentOf, + PropertyOperation.DescendentLeaf, PropertyOperation.IsNotA, PropertyOperation.Generalizes, PropertyOperation.ChildOf, PropertyOperation.NotIn) : + addToOps(ops, PropertyOperation.Equals, PropertyOperation.In, PropertyOperation.IsA, PropertyOperation.DescendentOf, + PropertyOperation.IsNotA, PropertyOperation.Generalizes, PropertyOperation.NotIn)); + case "code" : + return new PropertyValidationRules(PropertyFilterType.Code, CodeValidationRule.Error, + VersionUtilities.isR5Plus(context.getVersion()) ? + addToOps(ops, PropertyOperation.RegEx, PropertyOperation.Equals, PropertyOperation.In, PropertyOperation.IsA, PropertyOperation.DescendentOf, + PropertyOperation.DescendentLeaf, PropertyOperation.IsNotA, PropertyOperation.Generalizes, PropertyOperation.ChildOf, PropertyOperation.NotIn) : + addToOps(ops, PropertyOperation.RegEx, PropertyOperation.Equals, PropertyOperation.In, PropertyOperation.IsA, PropertyOperation.DescendentOf, + PropertyOperation.IsNotA, PropertyOperation.Generalizes, PropertyOperation.NotIn)); case "status" : return new PropertyValidationRules(PropertyFilterType.Code, CodeValidationRule.None, ops); case "inactive" : return new PropertyValidationRules(PropertyFilterType.Boolean,null, ops); case "effectiveDate" : return new PropertyValidationRules(PropertyFilterType.DateTime, null, ops); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 3880b7322..996071417 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -565,7 +565,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat private boolean errorForUnknownProfiles; private boolean noInvariantChecks; private boolean wantInvariantInMessage; - private boolean noTerminologyChecks; private boolean hintAboutNonMustSupport; private boolean showMessagesFromReferences; private String validationLanguage; @@ -6010,7 +6009,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } - if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wg != null || url.contains("http://hl7.org/fhir/sid"), I18nConstants.VALIDATION_HL7_WG_NEEDED, ToolingExtensions.EXT_WORKGROUP)) { + if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wg != null || url.contains("http://hl7.org/fhir/sid") || !forPublication, I18nConstants.VALIDATION_HL7_WG_NEEDED, ToolingExtensions.EXT_WORKGROUP)) { if (wg != null) { HL7WorkGroup wgd = HL7WorkGroups.find(wg); if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wgd != null, I18nConstants.VALIDATION_HL7_WG_UNKNOWN, wg)) { diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/CodeSystemValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/CodeSystemValidator.java index a686192ae..1246af2f9 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/CodeSystemValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/CodeSystemValidator.java @@ -638,7 +638,7 @@ public class CodeSystemValidator extends BaseValidator { private boolean validateSupplementConcept(List errors, Element concept, NodeStack stack, String supp, ValidationOptions options) { String code = concept.getChildValue("code"); - if (!Utilities.noString(code)) { + if (!Utilities.noString(code) && !noTerminologyChecks) { var canonical = new CanonicalPair(supp); org.hl7.fhir.r5.terminologies.utilities.ValidationResult res = context.validateCode(options, canonical.getUrl(), canonical.getVersion(), code, null); return rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), res.isOk(), I18nConstants.CODESYSTEM_CS_SUPP_INVALID_CODE, supp, code); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java index b3aeb1c4c..2cf6bfbcd 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ConceptMapValidator.java @@ -161,7 +161,7 @@ public class ConceptMapValidator extends BaseValidator { if (!batch.isEmpty()) { if (batch.size() > TOO_MANY_CODES_TO_VALIDATE) { ok = hint(errors, "2023-09-06", IssueType.BUSINESSRULE, stack.getLiteralPath(), false, I18nConstants.CONCEPTMAP_VS_TOO_MANY_CODES, batch.size()) && ok; - } else { + } else if (!noTerminologyChecks) { try { long t = System.currentTimeMillis(); context.validateCodeBatch(ValidationOptions.defaults(), batch, null); @@ -313,7 +313,7 @@ public class ConceptMapValidator extends BaseValidator { if (display != null) { warning(errors, "2023-03-05", IssueType.REQUIRED, code.line(), code.col(), cstack.getLiteralPath(), CodeSystemUtilities.checkDisplay(ctxt.source.cs, cd, display.getValue()), I18nConstants.CONCEPTMAP_GROUP_SOURCE_DISPLAY_INVALID, display.getValue(), CommaSeparatedStringBuilder.joinWrapped(", ", "'", "'", CodeSystemUtilities.getDisplays(ctxt.source.cs, cd)), ctxt.source.cs.getVersionedUrl()+"#"+cd.getCode()); } - if (ctxt.hasSourceVS() && ctxt.source != null) { + if (!noTerminologyChecks && ctxt.hasSourceVS() && ctxt.source != null) { ValidationResult vr = context.validateCode(options.withCheckValueSetOnly().withNoServer(), ctxt.source.url, ctxt.source.version, c, null, ctxt.sourceScope.vs); if (!warningOrError(ctxt.source.cs.getContent() == CodeSystemContentMode.COMPLETE, errors, "2023-09-06", IssueType.REQUIRED, code.line(), code.col(), cstack.getLiteralPath(), vr.isOk(), I18nConstants.CONCEPTMAP_GROUP_SOURCE_CODE_INVALID_VS, c, ctxt.sourceScope.vs.getVersionedUrl())) { ok = (ctxt.source.cs.getContent() != CodeSystemContentMode.COMPLETE) & ok; @@ -350,7 +350,7 @@ public class ConceptMapValidator extends BaseValidator { if (display != null) { warning(errors, "2023-03-05", IssueType.REQUIRED, code.line(), code.col(), cstack.getLiteralPath(), CodeSystemUtilities.checkDisplay(ctxt.target.cs, cd, display.getValue()), I18nConstants.CONCEPTMAP_GROUP_TARGET_DISPLAY_INVALID, display.getValue(), CommaSeparatedStringBuilder.joinWrapped(", ", "'", "'", CodeSystemUtilities.getDisplays(ctxt.target.cs, cd)), ctxt.target.cs.getVersionedUrl()+"#"+cd.getCode()); } - if (ctxt.hasTargetVS() && ctxt.target != null) { + if (!!noTerminologyChecks && ctxt.hasTargetVS() && ctxt.target != null) { ValidationResult vr = context.validateCode(options.withCheckValueSetOnly().withNoServer(), ctxt.target.url, ctxt.target.version, c, null, ctxt.targetScope.vs); if (!warningOrError(ctxt.target.cs.getContent() == CodeSystemContentMode.COMPLETE, errors, "2023-09-06", IssueType.REQUIRED, code.line(), code.col(), cstack.getLiteralPath(), vr.isOk(), I18nConstants.CONCEPTMAP_GROUP_TARGET_CODE_INVALID_VS, c, ctxt.targetScope.vs.getVersionedUrl())) { ok = (ctxt.target.cs.getContent() != CodeSystemContentMode.COMPLETE) && ok; diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java index 14b71ecc6..c6e142977 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/QuestionnaireValidator.java @@ -767,20 +767,22 @@ public class QuestionnaireValidator extends BaseValidator { } } - long t = System.nanoTime(); - ValidationContextCarrier vc = makeValidationContext(errors, qSrc); - ValidationResult res = context.validateCode(new ValidationOptions(FhirPublication.R5, stack.getWorkingLang()), c, vs, vc); - timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'"); - if (!res.isOk()) { - if (res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { - txWarning(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION_CS, c.getSystem(), c.getCode(), vs.present()); - } else { - ok = txRule(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION, c.getSystem(), c.getCode(), vs.present(), res.getMessage()) && ok; + if (!noTerminologyChecks) { + long t = System.nanoTime(); + ValidationContextCarrier vc = makeValidationContext(errors, qSrc); + ValidationResult res = context.validateCode(new ValidationOptions(FhirPublication.R5, stack.getWorkingLang()), c, vs, vc); + timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'"); + if (!res.isOk()) { + if (res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { + txWarning(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION_CS, c.getSystem(), c.getCode(), vs.present()); + } else { + ok = txRule(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION, c.getSystem(), c.getCode(), vs.present(), res.getMessage()) && ok; + } + } else if (res.getSeverity() != null) { + super.addValidationMessage(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine, null); + } else if (res.getMessage() != null) { + super.addValidationMessage(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity() == null ? IssueSeverity.INFORMATION : res.getSeverity(), Source.TerminologyEngine, null); } - } else if (res.getSeverity() != null) { - super.addValidationMessage(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine, null); - } else if (res.getMessage() != null) { - super.addValidationMessage(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity() == null ? IssueSeverity.INFORMATION : res.getSeverity(), Source.TerminologyEngine, null); } } catch (Exception e) { warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_CODING, e.getMessage()); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ValueSetValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ValueSetValidator.java index 9821cba14..ee45fc433 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ValueSetValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/ValueSetValidator.java @@ -98,9 +98,11 @@ public class ValueSetValidator extends BaseValidator { public PropertyFilterType getType() { return type; } + public EnumSet getOps() { return ops; } + public CodeValidationRule getCodeValidation() { return codeValidation; } @@ -316,34 +318,36 @@ public class ValueSetValidator extends BaseValidator { } } - boolean systemOk = true; - int cc = 0; - List batch = new ArrayList<>(); - boolean first = true; - if (concepts.size() > TOO_MANY_CODES_TO_VALIDATE) { - hint(errors, "2023-09-06", IssueType.BUSINESSRULE, stack, false, I18nConstants.VALUESET_INC_TOO_MANY_CODES, batch.size()); - } else { - if (((InstanceValidator) parent).isValidateValueSetCodesOnTxServer() && !context.isNoTerminologyServer()) { - try { - for (Element concept : concepts) { - // we treat the first differently because we want to know if the system is worth validating. if it is, then we batch the rest - if (first) { - systemOk = validateValueSetIncludeConcept(errors, concept, stack, stack.push(concept, cc, null, null), system, version, csChecker); - first = false; - } else if (systemOk) { - batch.add(prepareValidateValueSetIncludeConcept(errors, concept, stack.push(concept, cc, null, null), system, version, csChecker)); - if (batch.size() > VALIDATION_BATCH_SIZE) { - executeValidationBatch(errors, vsid, retired, system, version, batch); - batch.clear(); + if (!noTerminologyChecks) { + boolean systemOk = true; + int cc = 0; + List batch = new ArrayList<>(); + boolean first = true; + if (concepts.size() > TOO_MANY_CODES_TO_VALIDATE) { + hint(errors, "2023-09-06", IssueType.BUSINESSRULE, stack, false, I18nConstants.VALUESET_INC_TOO_MANY_CODES, batch.size()); + } else { + if (((InstanceValidator) parent).isValidateValueSetCodesOnTxServer() && !context.isNoTerminologyServer()) { + try { + for (Element concept : concepts) { + // we treat the first differently because we want to know if the system is worth validating. if it is, then we batch the rest + if (first) { + systemOk = validateValueSetIncludeConcept(errors, concept, stack, stack.push(concept, cc, null, null), system, version, csChecker); + first = false; + } else if (systemOk) { + batch.add(prepareValidateValueSetIncludeConcept(errors, concept, stack.push(concept, cc, null, null), system, version, csChecker)); + if (batch.size() > VALIDATION_BATCH_SIZE) { + executeValidationBatch(errors, vsid, retired, system, version, batch); + batch.clear(); + } } - } - cc++; - } - executeValidationBatch(errors, vsid, retired, system, version, batch); - } catch (Exception e) { - ok = false; - VSCodingValidationRequest cv = batch.get(0); - rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, cv.getStack().getLiteralPath(), false, e.getMessage()); + cc++; + } + executeValidationBatch(errors, vsid, retired, system, version, batch); + } catch (Exception e) { + ok = false; + VSCodingValidationRequest cv = batch.get(0); + rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, cv.getStack().getLiteralPath(), false, e.getMessage()); + } } } } @@ -386,36 +390,38 @@ public class ValueSetValidator extends BaseValidator { String display = concept.getChildValue("display"); slv.checkConcept(code, display); - if (version == null) { - ValidationResult vv = context.validateCode(ValidationOptions.defaults().withExampleOK(), new Coding(system, code, null), null); - if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { - if (isExampleUrl(system)) { - if (isAllowExamples()) { - hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_EXAMPLE_SYSTEM_HINT, system); + if (!!noTerminologyChecks) { + if (version == null) { + ValidationResult vv = context.validateCode(ValidationOptions.defaults().withExampleOK(), new Coding(system, code, null), null); + if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { + if (isExampleUrl(system)) { + if (isAllowExamples()) { + hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_EXAMPLE_SYSTEM_HINT, system); + } else { + rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_EXAMPLE_SYSTEM_ERROR, system); + } } else { - rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_EXAMPLE_SYSTEM_ERROR, system); + warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING, system, vv.getMessage()); } + return false; } else { - warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING, system, vv.getMessage()); + boolean ok = vv.isOk(); + warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack, ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, code, vv.getMessage()); + if (vv.getMessage() != null) { + hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack, false, vv.getMessage()); + } } - return false; } else { - boolean ok = vv.isOk(); - warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack, ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, code, vv.getMessage()); - if (vv.getMessage() != null) { - hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack, false, vv.getMessage()); - } - } - } else { - ValidationResult vv = context.validateCode(ValidationOptions.defaults().withExampleOK(), new Coding(system, code, null).setVersion(version), null); - if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { - warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING_VER, system+"#"+version, vv.getMessage()); - return false; - } else { - boolean ok = vv.isOk(); - warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack, ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, code, vv.getMessage()); - if (vv.getMessage() != null) { - hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack, false, vv.getMessage()); + ValidationResult vv = context.validateCode(ValidationOptions.defaults().withExampleOK(), new Coding(system, code, null).setVersion(version), null); + if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { + warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING_VER, system+"#"+version, vv.getMessage()); + return false; + } else { + boolean ok = vv.isOk(); + warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack, ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, code, vv.getMessage()); + if (vv.getMessage() != null) { + hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack, false, vv.getMessage()); + } } } } @@ -517,7 +523,7 @@ public class ValueSetValidator extends BaseValidator { ok = rule(errors, "2024-03-09", IssueType.INVALID, stack, value.trim().equals(value), I18nConstants.VALUESET_BAD_FILTER_VALUE_CODE, property, value) && ok; - if (rules.getCodeValidation() == CodeValidationRule.Error || rules.getCodeValidation() == CodeValidationRule.Warning) { + if (!noTerminologyChecks && (rules.getCodeValidation() == CodeValidationRule.Error || rules.getCodeValidation() == CodeValidationRule.Warning)) { ValidationResult vr = context.validateCode(baseOptions, system, version, value, null); if (rules.getCodeValidation() == CodeValidationRule.Error) { ok = rule(errors, "2024-03-09", IssueType.INVALID, stack.getLiteralPath(), vr.isOk(), rules.isChange() ? I18nConstants.VALUESET_BAD_FILTER_VALUE_VALID_CODE_CHANGE : I18nConstants.VALUESET_BAD_FILTER_VALUE_VALID_CODE, property, value, system, vr.getMessage()) && ok; @@ -557,7 +563,7 @@ public class ValueSetValidator extends BaseValidator { Coding code = Coding.fromLiteral(value); if (code == null) { ok = rule(errors, "2024-03-09", IssueType.INVALID, stack, false, I18nConstants.VALUESET_BAD_FILTER_VALUE_CODED, property, value) && ok; - } else { + } else if (!noTerminologyChecks) { ValidationResult vr = context.validateCode(baseOptions, code, null); ok = rule(errors, "2024-03-09", IssueType.INVALID, stack, vr.isOk(), I18nConstants.VALUESET_BAD_FILTER_VALUE_CODED_INVALID, property, value, vr.getMessage()) && ok; }