fix bugs in FHIRPath checking and track special time when validating resources

This commit is contained in:
Grahame Grieve 2023-08-31 06:30:29 +02:00
parent 2deb88cdc9
commit 4bba1c2cde
7 changed files with 74 additions and 44 deletions

View File

@ -263,10 +263,7 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
public void see(CachedCanonicalResource<T> cr) {
// -- 1. exit conditions -----------------------------------------------------------------------------
if ("http://hl7.org/fhir/StructureDefinition/Address".equals(cr.getUrl())) {
System.out.println("!"); // #FIXME
}
// ignore UTG NUCC erroneous code system
if (cr.getPackageInfo() != null
&& cr.getPackageInfo().getId() != null

View File

@ -444,7 +444,7 @@ public class FHIRPathEngine {
if (context == null) {
types = null; // this is a special case; the first path reference will have to resolve to something in the context
} else if (!context.contains(".")) {
StructureDefinition sd = worker.fetchTypeDefinition(resourceType);
StructureDefinition sd = worker.fetchTypeDefinition(context);
if (sd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT, context);
}

View File

@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@ -65,6 +66,7 @@ import javax.annotation.Nullable;
import org.apache.commons.io.FileUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.FileNotifier.FileNotifier2;
import org.hl7.fhir.utilities.Utilities.CaseInsensitiveSorter;
import org.hl7.fhir.utilities.settings.FhirSettings;
public class Utilities {
@ -1306,6 +1308,21 @@ public class Utilities {
return id.matches("[A-Za-z0-9\\-\\.]{1,64}");
}
public static class CaseInsensitiveSorter implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);
}
}
public static List<String> sortedCaseInsensitive(Collection<String> set) {
List<String> list = new ArrayList<>();
list.addAll(set);
Collections.sort(list, new CaseInsensitiveSorter());
return list;
}
public static List<String> sorted(Collection<String> set) {
List<String> list = new ArrayList<>();
list.addAll(set);

View File

@ -6,6 +6,7 @@ public class TimeTracker {
private long sdTime = 0;
private long loadTime = 0;
private long fpeTime = 0;
private long specTime = 0;
public long getOverall() {
return overall;
@ -22,6 +23,10 @@ public class TimeTracker {
public long getFpeTime() {
return fpeTime;
}
public long getSpecTime() {
return specTime;
}
public void load(long start) {
loadTime = loadTime + (System.nanoTime() - start);
@ -45,11 +50,16 @@ public class TimeTracker {
fpeTime = fpeTime + (System.nanoTime() - start);
}
public void spec(long start) {
specTime = specTime + (System.nanoTime() - start);
}
public void reset() {
overall = 0;
txTime = 0;
sdTime = 0;
loadTime = 0;
fpeTime = 0;
specTime = 0;
}
}

View File

@ -5202,44 +5202,50 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
public boolean checkSpecials(ValidatorHostContext hostContext, List<ValidationMessage> errors, Element element, NodeStack stack, boolean checkSpecials, PercentageTracker pct, ValidationMode mode) {
if (VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(element.getType())) {
Base base = element.getExtensionValue(ToolingExtensions.EXT_STANDARDS_STATUS);
String standardsStatus = base != null && base.isPrimitive() ? base.primitiveValue() : null;
String status = element.getNamedChildValue("status");
if (!Utilities.noString(status) && !Utilities.noString(standardsStatus)) {
if (warning(errors, "2023-08-14", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), statusCodesConsistent(status, standardsStatus), I18nConstants.VALIDATION_VAL_STATUS_INCONSISTENT, status, standardsStatus)) {
hint(errors, "2023-08-14", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), statusCodesDeeplyConsistent(status, standardsStatus), I18nConstants.VALIDATION_VAL_STATUS_INCONSISTENT_HINT, status, standardsStatus);
long t = System.nanoTime();
try {
if (VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(element.getType())) {
Base base = element.getExtensionValue(ToolingExtensions.EXT_STANDARDS_STATUS);
String standardsStatus = base != null && base.isPrimitive() ? base.primitiveValue() : null;
String status = element.getNamedChildValue("status");
if (!Utilities.noString(status) && !Utilities.noString(standardsStatus)) {
if (warning(errors, "2023-08-14", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), statusCodesConsistent(status, standardsStatus), I18nConstants.VALIDATION_VAL_STATUS_INCONSISTENT, status, standardsStatus)) {
hint(errors, "2023-08-14", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), statusCodesDeeplyConsistent(status, standardsStatus), I18nConstants.VALIDATION_VAL_STATUS_INCONSISTENT_HINT, status, standardsStatus);
}
}
}
}
if (element.getType().equals(BUNDLE)) {
return new BundleValidator(this, serverBase).validateBundle(errors, element, stack, checkSpecials, hostContext, pct, mode);
} else if (element.getType().equals("Observation")) {
return validateObservation(errors, element, stack);
} else if (element.getType().equals("Questionnaire")) {
return new QuestionnaireValidator(this, myEnableWhenEvaluator, fpe, questionnaireMode).validateQuestionannaire(errors, element, element, stack);
} else if (element.getType().equals("QuestionnaireResponse")) {
return new QuestionnaireValidator(this, myEnableWhenEvaluator, fpe, questionnaireMode).validateQuestionannaireResponse(hostContext, errors, element, stack);
} else if (element.getType().equals("Measure")) {
return new MeasureValidator(this).validateMeasure(hostContext, errors, element, stack);
} else if (element.getType().equals("MeasureReport")) {
return new MeasureValidator(this).validateMeasureReport(hostContext, errors, element, stack);
} else if (element.getType().equals("CapabilityStatement")) {
return validateCapabilityStatement(errors, element, stack);
} else if (element.getType().equals("CodeSystem")) {
return new CodeSystemValidator(this).validateCodeSystem(errors, element, stack, baseOptions.withLanguage(stack.getWorkingLang()));
} else if (element.getType().equals("ConceptMap")) {
return new ConceptMapValidator(this).validateConceptMap(errors, element, stack, baseOptions.withLanguage(stack.getWorkingLang()));
} else if (element.getType().equals("SearchParameter")) {
return new SearchParameterValidator(this, fpe).validateSearchParameter(errors, element, stack);
} else if (element.getType().equals("StructureDefinition")) {
return new StructureDefinitionValidator(this, fpe, wantCheckSnapshotUnchanged).validateStructureDefinition(errors, element, stack);
} else if (element.getType().equals("StructureMap")) {
return new StructureMapValidator(this, fpe, profileUtilities).validateStructureMap(errors, element, stack);
} else if (element.getType().equals("ValueSet")) {
return new ValueSetValidator(this).validateValueSet(errors, element, stack);
} else {
return true;
if (element.getType().equals(BUNDLE)) {
return new BundleValidator(this, serverBase).validateBundle(errors, element, stack, checkSpecials, hostContext, pct, mode);
} else if (element.getType().equals("Observation")) {
return validateObservation(errors, element, stack);
} else if (element.getType().equals("Questionnaire")) {
return new QuestionnaireValidator(this, myEnableWhenEvaluator, fpe, questionnaireMode).validateQuestionannaire(errors, element, element, stack);
} else if (element.getType().equals("QuestionnaireResponse")) {
return new QuestionnaireValidator(this, myEnableWhenEvaluator, fpe, questionnaireMode).validateQuestionannaireResponse(hostContext, errors, element, stack);
} else if (element.getType().equals("Measure")) {
return new MeasureValidator(this).validateMeasure(hostContext, errors, element, stack);
} else if (element.getType().equals("MeasureReport")) {
return new MeasureValidator(this).validateMeasureReport(hostContext, errors, element, stack);
} else if (element.getType().equals("CapabilityStatement")) {
return validateCapabilityStatement(errors, element, stack);
} else if (element.getType().equals("CodeSystem")) {
return new CodeSystemValidator(this).validateCodeSystem(errors, element, stack, baseOptions.withLanguage(stack.getWorkingLang()));
} else if (element.getType().equals("ConceptMap")) {
return new ConceptMapValidator(this).validateConceptMap(errors, element, stack, baseOptions.withLanguage(stack.getWorkingLang()));
} else if (element.getType().equals("SearchParameter")) {
return new SearchParameterValidator(this, fpe).validateSearchParameter(errors, element, stack);
} else if (element.getType().equals("StructureDefinition")) {
return new StructureDefinitionValidator(this, fpe, wantCheckSnapshotUnchanged).validateStructureDefinition(errors, element, stack);
} else if (element.getType().equals("StructureMap")) {
return new StructureMapValidator(this, fpe, profileUtilities).validateStructureMap(errors, element, stack);
} else if (element.getType().equals("ValueSet")) {
return new ValueSetValidator(this).validateValueSet(errors, element, stack);
} else {
return true;
}
} finally {
timeTracker.spec(t);
}
}
@ -6535,7 +6541,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
public String reportTimes() {
String s = String.format("Times (ms): overall = %d, tx = %d, sd = %d, load = %d, fpe = %d", timeTracker.getOverall() / 1000000, timeTracker.getTxTime() / 1000000, timeTracker.getSdTime() / 1000000, timeTracker.getLoadTime() / 1000000, timeTracker.getFpeTime() / 1000000);
String s = String.format("Times (ms): overall = %d, tx = %d, sd = %d, load = %d, fpe = %d, spec = %d", timeTracker.getOverall() / 1000000, timeTracker.getTxTime() / 1000000, timeTracker.getSdTime() / 1000000, timeTracker.getLoadTime() / 1000000, timeTracker.getFpeTime() / 1000000, timeTracker.getSpecTime() / 1000000);
timeTracker.reset();
return s;
}

View File

@ -536,7 +536,7 @@ public class StructureDefinitionValidator extends BaseValidator {
types.add(elements.get(0).getNamedChildValue("path"));
}
List<String> warnings = new ArrayList<>();
fpe.checkOnTypes(invariant, rootPath, types, fpe.parse(exp), warnings);
fpe.checkOnTypes(invariant, "DomainResource", types, fpe.parse(exp), warnings);
for (String s : warnings) {
warning(errors, "2023-07-27", IssueType.BUSINESSRULE, stack, false, key+": "+s);
}

View File

@ -20,7 +20,7 @@
<properties>
<guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.4.1</validator_test_case_version>
<validator_test_case_version>1.4.2-SNAPSHOT</validator_test_case_version>
<jackson_version>2.15.2</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>