alter processing of unknown code systems per discussion at ,https://chat.fhir.org/#narrow/stream/179252-IG-creation/topic/Don't.20error.20when.20you.20can't.20find.20code.20system and implement unknown-codesystems-cause-errors

This commit is contained in:
Grahame Grieve 2024-09-06 22:18:01 +08:00
parent 4603b3ac3c
commit 7fc34e509a
9 changed files with 163 additions and 77 deletions

View File

@ -124,11 +124,9 @@ public class ValueSetValidator extends ValueSetProcessBase {
}
public String getMessage() {
return message;
}
}
}
private ValueSet valueset;
private Map<String, ValueSetValidator> inner = new HashMap<>();
private ValidationOptions options;

View File

@ -1491,7 +1491,7 @@ public class Utilities {
}
public static boolean startsWithInList(String s, Collection<String> list) {
if (s == null) {
if (s == null || list == null) {
return false;
}
for (String l : list) {
@ -2304,4 +2304,16 @@ public class Utilities {
}
}
public static boolean listValueStartsWith(String s, Set<String> list) {
if (s == null || list == null) {
return false;
}
for (String l : list) {
if (l.startsWith(s)) {
return true;
}
}
return false;
}
}

View File

@ -31,18 +31,19 @@ public class PackageHacker {
public static void main(String[] args) throws FileNotFoundException, IOException {
// new PackageHacker().massEdit(new File("/Users/grahamegrieve/web/hl7.org/fhir"));
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.core.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.corexml.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.examples.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.expansions.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.search.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.core.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.corexml.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.examples.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.expansions.tgz");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.core.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.corexml.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.examples.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.expansions.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot1/hl7.fhir.r6.search.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.core.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.corexml.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.examples.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.expansions.tgz");
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz");
// new PackageHacker().edit(args[0]);
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v311/package.tgz", "http://hl7.org/fhir/us/core/STU3.1.1");
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v700/package.tgz", "http://hl7.org/fhir/us/core/STU7");
}
// private void massEdit(File dir) throws IOException {
@ -91,7 +92,7 @@ public class PackageHacker {
// }
// }
private void edit(String name) throws FileNotFoundException, IOException {
private void edit(String name, String path) throws FileNotFoundException, IOException {
File f = ManagedFileAccess.file(name);
if (!f.exists())
throw new Error("Unable to find "+f.getAbsolutePath());
@ -107,15 +108,15 @@ public class PackageHacker {
System.out.println("Altering Package "+f.getAbsolutePath());
System.out.println(nice(pck.getNpm()));
if (change(pck.getNpm())) {
if (change(pck.getNpm(), path)) {
System.out.println("Revised Package");
System.out.println("=======================");
System.out.println(nice(pck.getNpm()));
System.out.println("=======================");
// System.out.print("save? y/n: ");
// int r = System.in.read();
// if (r == 'y') {
System.out.print("save? y/n: ");
int r = System.in.read();
if (r == 'y') {
f.renameTo(ManagedFileAccess.file(Utilities.changeFileExt(name, ".tgz.bak")));
FileOutputStream fso = ManagedFileAccess.outStream(f);
try {
@ -123,7 +124,7 @@ public class PackageHacker {
} finally {
fso.close();
}
// }
}
}
}
@ -142,13 +143,15 @@ public class PackageHacker {
return JsonParser.compose(json, true);
}
private boolean change(JsonObject npm) throws FileNotFoundException, IOException {
// fixVersions(npm, ver);
if (npm.has("notForPublication")) {
npm.remove("notForPublication");
return true;
}
return false;
private boolean change(JsonObject npm, String path) throws FileNotFoundException, IOException {
npm.remove("url");
npm.add("url", path);
return true;
// if (npm.has("notForPublication")) {
// npm.remove("notForPublication");
// return true;
// }
// return false;
}
private void fixVersionInContent(Map<String, byte[]> content) {

View File

@ -226,6 +226,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
@Getter @Setter private boolean allowDoubleQuotesInFHIRPath;
@Getter @Setter private boolean checkIPSCodes;
@Getter @Setter private BestPracticeWarningLevel bestPracticeLevel;
@Getter @Setter private boolean unknownCodeSystemsCauseErrors;
@Getter @Setter private Locale locale;
@Getter @Setter private List<ImplementationGuide> igs = new ArrayList<>();
@Getter @Setter private List<String> extensionDomains = new ArrayList<>();
@ -289,6 +290,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
fhirPathEngine = other.fhirPathEngine;
igLoader = other.igLoader;
jurisdiction = other.jurisdiction;
unknownCodeSystemsCauseErrors = other.unknownCodeSystemsCauseErrors;
}
/**
@ -906,6 +908,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
if (policyAdvisor != null) {
validator.setPolicyAdvisor(policyAdvisor);
}
validator.setUnknownCodeSystemsCauseErrors(unknownCodeSystemsCauseErrors);
return validator;
}

View File

@ -163,6 +163,9 @@ public class CliContext {
@JsonProperty("bestPracticeLevel")
private BestPracticeWarningLevel bestPracticeLevel = BestPracticeWarningLevel.Warning;
@JsonProperty("unknownCodeSystemsCauseErrors")
private boolean unknownCodeSystemsCauseErrors;
@JsonProperty("baseEngine")
public String getBaseEngine() {
return baseEngine;
@ -832,6 +835,7 @@ public class CliContext {
Objects.equals(watchMode, that.watchMode) &&
Objects.equals(bestPracticeLevel, that.bestPracticeLevel) &&
Objects.equals(watchScanDelay, that.watchScanDelay) &&
Objects.equals(unknownCodeSystemsCauseErrors, that.unknownCodeSystemsCauseErrors) &&
Objects.equals(watchSettleTime, that.watchSettleTime) ;
}
@ -839,8 +843,8 @@ public class CliContext {
public int hashCode() {
return Objects.hash(baseEngine, doNative, extensions, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching,
noExtensibleBindingMessages, noInvariants, displayWarnings, wantInvariantsInMessages, map, output, outputSuffix, htmlOutput, txServer, sv, txLog, txCache, mapLog, lang, srcLang, tgtLang, fhirpath, snomedCT,
targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars, watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel,
htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars,
watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
}
@Override
@ -899,6 +903,7 @@ public class CliContext {
", bestPracticeLevel=" + bestPracticeLevel +
", watchSettleTime=" + watchSettleTime +
", watchScanDelay=" + watchScanDelay +
", unknownCodeSystemsCauseErrors=" + unknownCodeSystemsCauseErrors +
'}';
}
@ -956,4 +961,17 @@ public class CliContext {
return this;
}
@JsonProperty("unknownCodeSystemsCauseErrors")
public boolean isUnknownCodeSystemsCauseErrors() {
return unknownCodeSystemsCauseErrors;
}
@JsonProperty("unknownCodeSystemsCauseErrors")
public void setUnknownCodeSystemsCauseErrors(boolean unknownCodeSystemsCauseErrors) {
this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors;
}
}

View File

@ -581,6 +581,7 @@ public class ValidationService {
}
validationEngine.getBundleValidationRules().addAll(cliContext.getBundleValidationRules());
validationEngine.setJurisdiction(CodeSystemUtilities.readCoding(cliContext.getJurisdiction()));
validationEngine.setUnknownCodeSystemsCauseErrors(cliContext.isUnknownCodeSystemsCauseErrors());
TerminologyCache.setNoCaching(cliContext.isNoInternalCaching());
validationEngine.prepare(); // generate any missing snapshots
System.out.println(" go (" + timeTracker.milestone() + ")");

View File

@ -94,8 +94,7 @@ public class Params {
public static final String DISABLE_DEFAULT_RESOURCE_FETCHER = "-disable-default-resource-fetcher";
public static final String CHECK_IPS_CODES = "-check-ips-codes";
public static final String BEST_PRACTICE = "-best-practice";
public static final String UNKNOWN_CODESYSTEMS_CAUSE_ERROR = "-unknown-codesystems-cause-errors";
public static final String RUN_TESTS = "-run-tests";
@ -320,6 +319,8 @@ public class Params {
cliContext.setCrumbTrails(true);
} else if (args[i].equals(FOR_PUBLICATION)) {
cliContext.setForPublication(true);
} else if (args[i].equals(UNKNOWN_CODESYSTEMS_CAUSE_ERROR)) {
cliContext.setUnknownCodeSystemsCauseErrors(true);
} else if (args[i].equals(VERBOSE)) {
cliContext.setCrumbTrails(true);
} else if (args[i].equals(ALLOW_EXAMPLE_URLS)) {

View File

@ -598,6 +598,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean example ;
private IDigitalSignatureServices signatureServices;
private ContextUtilities cu;
private boolean unknownCodeSystemsCauseErrors;
public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) {
super(theContext, xverManager, false);
@ -1125,7 +1126,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
if (s == null)
return true;
ok = processTxIssues(errors, s, element, path, null, "no binding on code", false, null) & ok;
ok = processTxIssues(errors, s, element, path, false, null, null) & ok;
if (s.isOk()) {
if (s.getMessage() != null && !s.messageIsInIssues()) {
@ -1381,7 +1382,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (cc.hasCoding()) {
long t = System.nanoTime();
ValidationResult vr = checkCodeOnServer(stack, null, cc);
bh.see(processTxIssues(errors, vr, element, path, org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION, null, false, null));
bh.see(processTxIssues(errors, vr, element, path, false, null, null));
timeTracker.tx(t, "vc " + cc.toString());
}
} catch (CheckCodeOnServerException e) {
@ -1465,7 +1466,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else {
checked.set(true);
ValidationResult vr = checkCodeOnServer(stack, valueset, cc);
bh.see(processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), false, vsRef));
bh.see(processTxIssues(errors, vr, element, path, false, vsRef, strength));
if (!vr.isOk()) {
bindingsOk = false;
if (vr.getErrorClass() != null && vr.getErrorClass() == TerminologyServiceErrorClass.NOSERVICE) {
@ -1533,33 +1534,34 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return checkDisp;
}
private String notFoundSeverityNoteForBinding(BindingStrength strength) {
if (strength == BindingStrength.REQUIRED) {
return "error because this is a required binding";
} else {
return null;
}
}
// private String notFoundSeverityNoteForBinding(BindingStrength strength, Set<String> systems) {
// if (strength == BindingStrength.REQUIRED &&
// (Utilities.listValueStartsWith("http://hl7.org/fhir", systems) || Utilities.listValueStartsWith("http://terminology.hl7.org", systems))) {
// return "error because this is a required binding to an HL7 code system";
// } else {
// return null;
// }
// }
//
// /**
// * The terminology server will report an error for an unknown code system or version, or a dependent valueset
// *
// * but we only care for validation if the binding strength is strong enough.
// * @param binding
// * @return
// */
// private org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundSeverityForBinding(BindingStrength strength, String systems) {
// if (strength == BindingStrength.REQUIRED &&
// (Utilities.listValueStartsWith("http://hl7.org/fhir", systems) || Utilities.listValueStartsWith("http://terminology.hl7.org", systems))) {
// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR;
// } else if (strength == BindingStrength.REQUIRED || strength == BindingStrength.EXTENSIBLE) {
// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
// } else {
// return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION;
// }
// }
/**
* The terminology server will report an error for an unknown code system or version, or a dependent valueset
*
* but we only care for validation if the binding strength is strong enough.
* @param binding
* @return
*/
private org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundSeverityForBinding(BindingStrength strength) {
if (strength == BindingStrength.REQUIRED) {
return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR;
} else if (strength == BindingStrength.EXTENSIBLE) {
return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
} else {
return org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.INFORMATION;
}
}
private boolean processTxIssues(List<ValidationMessage> errors, ValidationResult vr, Element element, String path,
org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundLevel, String notFoundNote, boolean ignoreCantInfer, String vsurl) {
private boolean processTxIssues(List<ValidationMessage> errors, ValidationResult vr, Element element, String path, boolean ignoreCantInfer, String vsurl, BindingStrength bs) {
boolean ok = true;
if (vr != null) {
for (OperationOutcomeIssueComponent iss : vr.getIssues()) {
@ -1567,12 +1569,35 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
&& !iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "this-code-not-in-vs")
&& !(ignoreCantInfer || iss.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "cannot-infer"))) {
OperationOutcomeIssueComponent i = iss.copy();
if (i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) {
if (notFoundLevel != null && i.getSeverity().isHigherThan(notFoundLevel) || (vsurl != null && i.getDetails().getText().contains(vsurl))) {
i.setSeverity(notFoundLevel);
if (i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "not-found")) {
String msg = iss.getDetails().getText();
boolean isHL7 = msg == null ? false : msg.contains("http://hl7.org/fhir") || msg.contains("http://terminology.hl7.org");
org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity notFoundLevel = null;
String notFoundNote = null;
if (bs == null) {
notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
notFoundNote = null; // "binding=null";
} else if (bs == BindingStrength.REQUIRED && isHL7) {
notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR;
notFoundNote = "error because this is a required binding to an HL7 code system";
} else if (bs == BindingStrength.REQUIRED && unknownCodeSystemsCauseErrors) {
notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR;
notFoundNote = "error because this is a required binding";
} else if (bs == BindingStrength.REQUIRED) {
notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
notFoundNote = null; // "binding=required";
} else if (bs == BindingStrength.EXTENSIBLE) {
notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
notFoundNote = null; // "binding=extensible";
} else {
notFoundLevel = org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.WARNING;
notFoundNote = null; // "binding="+bs.toCode();
}
if (notFoundNote != null) {
i.getDetails().setText(i.getDetails().getText()+" ("+notFoundNote+")");
if (notFoundLevel != null && i.getSeverity().isHigherThan(notFoundLevel)) { // && (vsurl != null && i.getDetails().getText().contains(vsurl))) {
i.setSeverity(notFoundLevel);
if (notFoundNote != null) {
i.getDetails().setText(i.getDetails().getText()+" ("+notFoundNote+")");
}
}
}
if (baseOptions.isDisplayWarningMode() && i.getSeverity() == org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity.ERROR && i.getDetails().hasCoding("http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", "invalid-display")) {
@ -1592,7 +1617,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
boolean ok = true;
if (isNotBlank(nextCoding.getCode()) && isNotBlank(nextCoding.getSystem()) && context.supportsSystem(nextCoding.getSystem(), baseOptions.getFhirVersion())) {
ValidationResult vr = checkCodeOnServer(stack, valueset, nextCoding);
ok = processTxIssues(errors, vr, element, path, null, "ex-checkBindings", false, null) && ok;
ok = processTxIssues(errors, vr, element, path, false, null, null) && ok;
if (vr.getSeverity() != null && !vr.messageIsInIssues()) {
if (vr.getSeverity() == IssueSeverity.INFORMATION) {
@ -1721,7 +1746,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (strength == BindingStrength.REQUIRED) {
removeTrackedMessagesForLocation(errors, element, path);
}
ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), false, vsRef) && ok;
ok = processTxIssues(errors, vr, element, path, false, vsRef, strength) && ok;
timeTracker.tx(t, "vc "+system+"#"+code+" '"+display+"'");
if (vr != null && !vr.isOk()) {
if (vr.IsNoService())
@ -1766,6 +1791,21 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return ok;
}
private Set<String> getUnknownSystems(ValidationResult vr) {
if (vr == null) {
return null;
}
if (vr.getUnknownSystems() != null && !vr.getUnknownSystems().isEmpty()) {
return vr.getUnknownSystems();
}
if (vr.getSystem() != null) {
Set<String> set = new HashSet<String>();
set.add(vr.getSystem());
return set;
}
return null;
}
private boolean convertCDACodeToCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition logical, CodeableConcept cc) {
boolean ok = true;
cc.setText(element.getNamedChildValue("originalText", false));
@ -1851,7 +1891,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
try {
long t = System.nanoTime();
ValidationResult vr = checkCodeOnServer(stack, valueset, cc);
ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet", false, maxVSUrl) && ok;
ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok;
timeTracker.tx(t, "vc "+cc.toString());
if (!vr.isOk()) {
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
@ -1890,7 +1930,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
try {
long t = System.nanoTime();
ValidationResult vr = checkCodeOnServer(stack, valueset, c);
ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet-2", false, maxVSUrl) && ok;
ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok;
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
if (!vr.isOk()) {
@ -1921,7 +1961,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
try {
long t = System.nanoTime();
ValidationResult vr = checkCodeOnServer(stack, valueset, value, baseOptions);
ok = processTxIssues(errors, vr, element, path, null, "ex-checkMaxValueSet-3", false, maxVSUrl) && ok;
ok = processTxIssues(errors, vr, element, path, false, maxVSUrl, null) && ok;
timeTracker.tx(t, "vc "+value);
if (!vr.isOk()) {
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
@ -2045,7 +2085,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checked.set(true);
vr = checkCodeOnServer(stack, valueset, c);
}
ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(strength), notFoundSeverityNoteForBinding(strength), strength == BindingStrength.EXTENSIBLE, vsRef) && ok;
ok = processTxIssues(errors, vr, element, path, strength == BindingStrength.EXTENSIBLE, vsRef, strength) && ok;
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
if (strength == BindingStrength.REQUIRED) {
@ -3510,7 +3550,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
vr = checkCodeOnServer(stack, vs, value, options);
}
ok = processTxIssues(errors, vr, element, path, notFoundSeverityForBinding(binding.getStrength()), notFoundSeverityNoteForBinding(binding.getStrength()), binding.getStrength() != BindingStrength.REQUIRED, binding.getValueSet()) && ok;
ok = processTxIssues(errors, vr, element, path, binding.getStrength() != BindingStrength.REQUIRED, binding.getValueSet(), binding.getStrength()) && ok;
timeTracker.tx(t, "vc "+value+"");
if (binding.getStrength() == BindingStrength.REQUIRED) {
@ -7791,4 +7831,14 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
this.fetcher = value;
return this;
}
public boolean isUnknownCodeSystemsCauseErrors() {
return unknownCodeSystemsCauseErrors;
}
public void setUnknownCodeSystemsCauseErrors(boolean unknownCodeSystemsCauseErrors) {
this.unknownCodeSystemsCauseErrors = unknownCodeSystemsCauseErrors;
}
}

View File

@ -247,9 +247,9 @@ public class ValidationEngineTests {
Assertions.assertTrue(checkOutcomes("testObs102", op,
"Observation.text.div null error/invalid: Wrong namespace on the XHTML ('null', should be 'http://www.w3.org/1999/xhtml')\n"+
"Observation.category null information/business-rule: Reference to experimental CodeSystem http://hl7.org/fhir/observation-category\n"+
"Observation.code.coding[2].system null information/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated\n"+
"Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer\n"+
"Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have an effective[x] ()"));
"Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have an effective[x] ()\n"+
"Observation.code.coding[2].system null warning/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated"));
verifyNoTerminologyRequests(logger);
}
@ -265,8 +265,8 @@ public class ValidationEngineTests {
System.out.println(" .. load USCore");
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "observation301.xml"), null);
Assertions.assertTrue(checkOutcomes("test301", op,
"Observation.code.coding[3].system null information/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated\n"+
"Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer"));
"Observation null warning/invalid: Best Practice Recommendation: In general, all observations should have a performer\n"+
"Observation.code.coding[3].system null warning/not-found: A definition for CodeSystem 'http://acme.org/devices/clinical-codes' could not be found, so the code cannot be validated"));
verifyNoTerminologyRequests(logger);
}