Add support for http://hl7.org/fhir/StructureDefinition/structuredefinition-dependencies to validator
This commit is contained in:
parent
efd8e07b9d
commit
c7ef0a3ac6
|
@ -205,6 +205,7 @@ public class ToolingExtensions {
|
|||
public static final String EXT_REND_MD = "http://hl7.org/fhir/StructureDefinition/rendering-markdown";
|
||||
public static final String EXT_CAP_STMT_EXPECT = "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation";
|
||||
public static final String EXT_ED_HEIRARCHY = "http://hl7.org/fhir/StructureDefinition/elementdefinition-heirarchy";
|
||||
public static final String EXT_SD_DEPENDENCY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-dependencies";
|
||||
|
||||
// in the tooling IG
|
||||
public static final String EXT_BINDING_ADDITIONAL = "http://hl7.org/fhir/tools/StructureDefinition/additional-binding";
|
||||
|
|
|
@ -611,6 +611,7 @@ public class I18nConstants {
|
|||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST = "VALIDATION_VAL_PROFILE_SIGNPOST";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL = "VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_META = "VALIDATION_VAL_PROFILE_SIGNPOST_META";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_DEP = "VALIDATION_VAL_PROFILE_SIGNPOST_DEP";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM = "VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM";
|
||||
public static final String VALIDATION_VAL_PROFILE_SLICEORDER = "Validation_VAL_Profile_SliceOrder";
|
||||
public static final String VALIDATION_VAL_PROFILE_OTHER_VERSION = "VALIDATION_VAL_PROFILE_OTHER_VERSION";
|
||||
|
@ -622,6 +623,7 @@ public class I18nConstants {
|
|||
public static final String VALIDATION_VAL_PROFILE_WRONGTYPE = "Validation_VAL_Profile_WrongType";
|
||||
public static final String VALIDATION_VAL_PROFILE_WRONGTYPE2 = "Validation_VAL_Profile_WrongType2";
|
||||
public static final String VALIDATION_VAL_UNKNOWN_PROFILE = "Validation_VAL_Unknown_Profile";
|
||||
public static final String VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED = "VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED";
|
||||
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE";
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER";
|
||||
|
|
|
@ -236,6 +236,7 @@ Validation_VAL_Profile_Unknown = Profile reference ''{0}'' has not been checked
|
|||
VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY = Profile reference ''{0}'' has not been checked because it is unknown, and the validator is set to not fetch unknown profiles
|
||||
VALIDATION_VAL_PROFILE_UNKNOWN_ERROR = Profile reference ''{0}'' has not been checked because it is unknown, and fetching it resulted in the error {1}
|
||||
Validation_VAL_Unknown_Profile = Unknown profile {0}
|
||||
VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED = Profile {1} identifies {2} as a dependency (using the extension http://hl7.org/fhir/StructureDefinition/structuredefinition-dependencies), but this profile could not be found
|
||||
XHTML_XHTML_Attribute_Illegal = Illegal attribute name in the XHTML (''{0}'' on ''{1}'')
|
||||
XHTML_XHTML_Element_Illegal = Illegal element name in the XHTML (''{0}'')
|
||||
XHTML_XHTML_NS_InValid = Wrong namespace on the XHTML (''{0}'', should be ''{1}'')
|
||||
|
@ -536,6 +537,7 @@ VALIDATION_VAL_GLOBAL_PROFILE_UNKNOWN = Global Profile reference ''{0}'' from IG
|
|||
VALIDATION_VAL_PROFILE_SIGNPOST_BASE = Validate resource against profile
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST = Validate resource against profile {0}
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_META = Validate resource against profile {0} (per meta)
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_DEP = Validate resource against profile {0} (per http://hl7.org/fhir/StructureDefinition/structuredefinition-dependencies in {1})
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM = Validate resource against profile {0} - provided as bundle param
|
||||
VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL = Validate resource against profile {0} - a global profile in {1}
|
||||
ERROR_GENERATING_SNAPSHOT = Error generating Snapshot: {0} (this usually arises from a problem in the differential)
|
||||
|
|
|
@ -818,15 +818,31 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
setParents(element);
|
||||
|
||||
long t = System.nanoTime();
|
||||
NodeStack stack = new NodeStack(context, path, element, validationLanguage);
|
||||
if (profiles == null || profiles.isEmpty()) {
|
||||
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, null, resourceIdRule, new NodeStack(context, path, element, validationLanguage).resetIds(), null);
|
||||
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, null, resourceIdRule, stack.resetIds(), null);
|
||||
} else {
|
||||
int i = 0;
|
||||
while (i < profiles.size()) {
|
||||
StructureDefinition sd = profiles.get(i);
|
||||
if (sd.hasExtension(ToolingExtensions.EXT_SD_DEPENDENCY)) {
|
||||
for (Extension ext : sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_DEPENDENCY)) {
|
||||
StructureDefinition dep = context.fetchResource( StructureDefinition.class, ext.getValue().primitiveValue());
|
||||
if (dep == null) {
|
||||
warning(errors, IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED, ext.getValue().primitiveValue(), sd.getUrl());
|
||||
} else if (!profiles.contains(dep)) {
|
||||
profiles.add(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
for (StructureDefinition defn : profiles) {
|
||||
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, defn, resourceIdRule, new NodeStack(context, path, element, validationLanguage).resetIds(), null);
|
||||
validateResource(new ValidatorHostContext(appContext, element), errors, element, element, defn, resourceIdRule, stack.resetIds(), null);
|
||||
}
|
||||
}
|
||||
if (hintAboutNonMustSupport) {
|
||||
checkElementUsage(errors, element, new NodeStack(context, path, element, validationLanguage));
|
||||
checkElementUsage(errors, element, stack);
|
||||
}
|
||||
errors.removeAll(messagesToRemove);
|
||||
timeTracker.overall(t);
|
||||
|
@ -1217,7 +1233,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
checkBindings(errors, path, element, stack, valueset, nextCoding);
|
||||
}
|
||||
}
|
||||
timeTracker.tx(t, "vc "+DataRenderer.display(context, cc));
|
||||
timeTracker.tx(t, "vc "+cc.toString());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -1692,6 +1708,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txHint(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_14, describeReference(binding.getValueSet(), valueset), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode);
|
||||
}
|
||||
}
|
||||
} else if (vr != null && vr.getMessage() != null) {
|
||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) e.printStackTrace();
|
||||
|
@ -3713,7 +3731,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
private String getErrorMessage(String message) {
|
||||
return message != null ? " (error message = " + message + ")" : "";
|
||||
return message != null ? " (error message = " + message + ")" : "";
|
||||
}
|
||||
|
||||
public boolean isSuppressLoincSnomedMessages() {
|
||||
|
@ -4517,28 +4535,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else if (!fetcher.fetchesCanonicalResource(this, profile.primitiveValue())) {
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_NOT_POLICY, profile.primitiveValue());
|
||||
} else {
|
||||
sd = null;
|
||||
String url = profile.primitiveValue();
|
||||
CanonicalResourceLookupResult cr = crLookups.get(url);
|
||||
if (cr != null) {
|
||||
if (cr.error != null) {
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, url, cr.error);
|
||||
} else {
|
||||
sd = (StructureDefinition) cr.resource;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
sd = (StructureDefinition) fetcher.fetchCanonicalResource(this, url);
|
||||
crLookups.put(url, new CanonicalResourceLookupResult(sd));
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) { e.printStackTrace(); }
|
||||
crLookups.put(url, new CanonicalResourceLookupResult(e.getMessage()));
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, profile.primitiveValue(), e.getMessage());
|
||||
}
|
||||
if (sd != null) {
|
||||
context.cacheResource(sd);
|
||||
}
|
||||
}
|
||||
sd = lookupProfileReference(errors, element, stack, i, profile, sd);
|
||||
}
|
||||
}
|
||||
if (sd != null) {
|
||||
|
@ -4553,6 +4550,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (pctOwned) {
|
||||
pct.done();
|
||||
}
|
||||
if (sd.hasExtension(ToolingExtensions.EXT_SD_DEPENDENCY)) {
|
||||
for (Extension ext : sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_DEPENDENCY)) {
|
||||
StructureDefinition sdi = context.fetchResource(StructureDefinition.class, ext.getValue().primitiveValue());
|
||||
if (sdi == null) {
|
||||
warning(errors, IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED, ext.getValue().primitiveValue(), sd.getUrl());
|
||||
} else {
|
||||
if (crumbTrails) {
|
||||
element.addMessage(signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_DEP, sdi.getUrl(), sd.getUrl()));
|
||||
}
|
||||
stack.resetIds();
|
||||
if (pctOwned) {
|
||||
pct = new PercentageTracker(resource.countDescendents(), resource.fhirType(), sdi.getUrl(), logProgress);
|
||||
}
|
||||
startInner(hostContext, errors, resource, element, sdi, stack, false, pct);
|
||||
if (pctOwned) {
|
||||
pct.done();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4583,6 +4601,32 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// System.out.println("start: "+(System.currentTimeMillis()-st)+" ("+resource.fhirType()+")");
|
||||
}
|
||||
|
||||
private StructureDefinition lookupProfileReference(List<ValidationMessage> errors, Element element, NodeStack stack,
|
||||
int i, Element profile, StructureDefinition sd) {
|
||||
String url = profile.primitiveValue();
|
||||
CanonicalResourceLookupResult cr = crLookups.get(url);
|
||||
if (cr != null) {
|
||||
if (cr.error != null) {
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, url, cr.error);
|
||||
} else {
|
||||
sd = (StructureDefinition) cr.resource;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
sd = (StructureDefinition) fetcher.fetchCanonicalResource(this, url);
|
||||
crLookups.put(url, new CanonicalResourceLookupResult(sd));
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) { e.printStackTrace(); }
|
||||
crLookups.put(url, new CanonicalResourceLookupResult(e.getMessage()));
|
||||
warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN_ERROR, profile.primitiveValue(), e.getMessage());
|
||||
}
|
||||
if (sd != null) {
|
||||
context.cacheResource(sd);
|
||||
}
|
||||
}
|
||||
return sd;
|
||||
}
|
||||
|
||||
// private void plog(String msg) {
|
||||
// long n = System.currentTimeMillis();
|
||||
// String elapsed = Utilities.padLeft(Long.toString(n-start), ' ', 5);
|
||||
|
@ -5720,7 +5764,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
boolean ok;
|
||||
try {
|
||||
long t = System.nanoTime();
|
||||
ok = fpe.evaluateToBoolean(hostContext, resource, hostContext.getRootResource(), element, n);
|
||||
ok = fpe.evaluateToBoolean(hostContext, resource, hostContext.getRootResource(), element, n);
|
||||
timeTracker.fpe(t);
|
||||
msg = fpe.forLog();
|
||||
} catch (Exception ex) {
|
||||
|
|
|
@ -419,7 +419,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
|
||||
private void checkOutcomes(List<ValidationMessage> errors, JsonObject focus, String profile, String name) throws IOException {
|
||||
JsonObject java = focus.getAsJsonObject("java");
|
||||
OperationOutcome goal = (OperationOutcome) new JsonParser().parse(java.getAsJsonObject("outcome"));
|
||||
OperationOutcome goal = java.has("outcome") ? (OperationOutcome) new JsonParser().parse(java.getAsJsonObject("outcome")) : new OperationOutcome();
|
||||
OperationOutcome actual = OperationOutcomeUtilities.createOutcomeSimple(errors);
|
||||
actual.setText(null);
|
||||
String json = new JsonParser().setOutputStyle(OutputStyle.PRETTY).composeString(actual);
|
||||
|
@ -521,8 +521,10 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
if (java.has("outcome")) {
|
||||
java.remove("outcome");
|
||||
}
|
||||
JsonObject oj = JsonTrackingParser.parse(json, null);
|
||||
java.add("outcome", oj);
|
||||
if (actual.hasIssue()) {
|
||||
JsonObject oj = JsonTrackingParser.parse(json, null);
|
||||
java.add("outcome", oj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue