improve language on constraint error message + add expression checking for SQL on FHIR project

This commit is contained in:
Grahame Grieve 2023-10-09 17:46:33 +11:00
parent af0f9bc765
commit 9da31ae8ad
4 changed files with 58 additions and 10 deletions

View File

@ -1003,6 +1003,9 @@ public class I18nConstants {
public static final String CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM = "CONCEPTMAP_VS_CONCEPT_CODE_UNKNOWN_SYSTEM";
public static final String LOGICAL_MODEL_NAME_MISMATCH = "LOGICAL_MODEL_NAME_MISMATCH";
public static final String LOGICAL_MODEL_QNAME_MISMATCH = "LOGICAL_MODEL_QNAME_MISMATCH";
public static final String FHIRPATH_CHOICE_NO_TYPE_SPECIFIER = "FHIRPATH_CHOICE_NO_TYPE_SPECIFIER";
public static final String FHIRPATH_CHOICE_SPURIOUS_TYPE_SPECIFIER = "FHIRPATH_CHOICE_SPURIOUS_TYPE_SPECIFIER";
public static final String FHIRPATH_NOT_A_COLLECTION = "FHIRPATH_NOT_A_COLLECTION";
}

View File

@ -0,0 +1,11 @@
package org.hl7.fhir.utilities.validation;
import java.io.IOException;
import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.utilities.json.model.JsonObject;
public interface IDigitalSignatureServices {
JsonObject fetchJWKS(String address) throws JsonException, IOException;
}

View File

@ -736,8 +736,8 @@ BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_MODE = This is not a matching resource t
BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_OUTCOME = This is not an OperationOutcome ({0})
BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_NO_MODE = This is not a matching resource type for the specified search (is a search mode needed?) ({0} expecting {1})
BUNDLE_SEARCH_NO_MODE = SearchSet bundles should have search modes on the entries
INV_FAILED = Rule {0} Failed
INV_FAILED_SOURCE = Rule {0} Failed (defined in {1})
INV_FAILED = Constraint failed: {0}
INV_FAILED_SOURCE = Constraint failed: {0} (defined in {1})
PATTERN_CHECK_STRING = The pattern [{0}] defined in the profile {1} not found. Issues: {2}
TYPE_SPECIFIC_CHECKS_DT_URL_EXAMPLE = Example URLs are not allowed in this context ({0})
UNICODE_BIDI_CONTROLS_CHARS_DISALLOWED = The Unicode sequence has bi-di control characters which are not allowed in this context: {0}
@ -1060,3 +1060,7 @@ TYPE_SPECIFIC_CHECKS_DT_QTY_UCUM_ANNOTATIONS_NOT_IN_UNIT = UCUM Codes that conta
TYPE_SPECIFIC_CHECKS_DT_QTY_UCUM_ANNOTATIONS = UCUM Codes that contain human readable annotations like {0} can be misleading (e.g. they are ignored when comparing units). Best Practice is not to depend on annotations in the UCUM code, so this usage should be checked
LOGICAL_MODEL_NAME_MISMATCH = The name ''{0}'' does not match the expected name ''{1}''
LOGICAL_MODEL_QNAME_MISMATCH = The QName ''{0}'' does not match the expected QName ''{1}''
FHIRPATH_CHOICE_NO_TYPE_SPECIFIER = The expression ''{0}'' refers to an element that is a choice, but doesn''t have an .ofType() so that SQL view runners can pre-determine the full element name
FHIRPATH_CHOICE_SPURIOUS_TYPE_SPECIFIER = The expression ''{0}'' refers to an element that is not a choice, but has an .ofType(). SQL view runners are likely to pre-determine an incorrect full element name
FHIRPATH_NOT_A_COLLECTION = Found a use of a collection operator on something that is not a collection at ''{0}'' - check that there's no mistakes in the expression syntax

View File

@ -185,6 +185,7 @@ import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.validation.IDigitalSignatureServices;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
@ -493,6 +494,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
public List<ValidatedFragment> validatedContent;
public boolean testMode;
private boolean example ;
private IDigitalSignatureServices signatureServices;
public InstanceValidator(@Nonnull IWorkerContext theContext, @Nonnull IEvaluationContext hostServices, @Nonnull XVerExtensionManager xverManager) {
super(theContext, xverManager, false);
@ -710,6 +712,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (parser instanceof JsonParser) {
((JsonParser) parser).setAllowComments(allowComments);
}
parser.setSignatureServices(signatureServices);
long t = System.nanoTime();
validatedContent = null;
try {
@ -5586,9 +5590,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
long t = System.nanoTime();
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, typeForResource.getProfile().get(0).asStringValue(), parentProfile);
timeTracker.sd(t);
trackUsage(profile, valContext, element);
if (rule(errors, NO_RULE_DATE, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE_EXPL, special.toHuman(), resourceName, typeForResource.getProfile().get(0).asStringValue())) {
profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE_EXPL, special == null ? "??" : special.toHuman(), resourceName, typeForResource.getProfile().get(0).asStringValue())) {
trackUsage(profile, valContext, element);
ok = validateResource(hc, errors, resource, element, profile, idstatus, stack, pct, mode) && ok;
} else {
ok = false;
@ -5841,6 +5845,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
boolean ok = true;
List<String> profiles = new ArrayList<String>();
String type = null;
String typeName = null;
ElementDefinition typeDefn = null;
checkMustSupport(profile, ei);
long s = System.currentTimeMillis();
@ -5848,21 +5853,29 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (checkDefn.getType().size() == 1 && !"*".equals(checkDefn.getType().get(0).getWorkingCode()) && !"Element".equals(checkDefn.getType().get(0).getWorkingCode())
&& !"BackboneElement".equals(checkDefn.getType().get(0).getWorkingCode())) {
type = checkDefn.getType().get(0).getWorkingCode();
typeName = type;
if (Utilities.isAbsoluteUrl(type)) {
StructureDefinition sdt = context.fetchTypeDefinition(type);
if (sdt != null) {
typeName = sdt.getTypeName();
}
}
String stype = ei.getElement().fhirType();
if (!stype.equals(type)) {
if (checkDefn.isChoice()) {
if (extensionUrl != null && !isAbsolute(extensionUrl)) {
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), false, I18nConstants.EXTENSION_PROF_TYPE, profile.getVersionedUrl(), type, stype) && ok;
} else if (!isAbstractType(type) && !"Extension".equals(profile.getType())) {
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(type), I18nConstants.EXTENSION_PROF_TYPE, profile.getVersionedUrl(), type, stype) && ok;
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(typeName), I18nConstants.EXTENSION_PROF_TYPE, profile.getVersionedUrl(), type, stype) && ok;
}
} else if (!isAbstractType(type)) {
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(type) ||
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), ei.getPath(), stype.equals(typeName) ||
(Utilities.existsInList(type, "string", "id") && Utilities.existsInList(stype, "string", "id")), // work around a r4 problem with id/string
I18nConstants.EXTENSION_PROF_TYPE, profile.getVersionedUrl(), type, stype) && ok;
} else if (!isResource(type)) {
// System.out.println("update type "+type+" to "+stype+"?");
type = stype;
typeName = type;
} else {
// this will be sorted out in contains ... System.out.println("update type "+type+" to "+stype+"?");
}
@ -5878,8 +5891,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
String prefix = tail(checkDefn.getPath());
assert prefix.endsWith("[x]");
type = ei.getName().substring(prefix.length() - 3);
if (isPrimitiveType(type))
typeName = type;
if (isPrimitiveType(type)) {
type = Utilities.uncapitalize(type);
typeName = type;
}
if (checkDefn.getType().get(0).hasProfile()) {
for (CanonicalType p : checkDefn.getType().get(0).getProfile()) {
profiles.add(p.getValue());
@ -5892,13 +5908,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (checkDefn.hasRepresentation(PropertyRepresentation.TYPEATTR)) {
type = ei.getElement().getType();
typeName = type;
} else if (ei.getElement().isResource()) {
type = ei.getElement().fhirType();
type = ei.getElement().fhirType();
typeName = type;
} else {
prefix = prefix.substring(0, prefix.length() - 3);
for (TypeRefComponent t : checkDefn.getType())
if ((prefix + Utilities.capitalize(t.getWorkingCode())).equals(ei.getName())) {
type = t.getWorkingCode();
typeName = type;
// Excluding reference is a kludge to get around versioning issues
if (t.hasProfile() && !type.equals("Reference"))
profiles.add(t.getProfile().get(0).getValue());
@ -5906,9 +5925,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
if (type == null) {
TypeRefComponent trc = checkDefn.getType().get(0);
if (trc.getWorkingCode().equals("Reference"))
if (trc.getWorkingCode().equals("Reference")) {
type = "Reference";
else
typeName = type;
} else
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_NOTYPE, ei.getName(), describeTypes(checkDefn.getType())) && ok;
}
} else if (checkDefn.getContentReference() != null) {
@ -5933,6 +5953,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ei.definition = ei.definition;
}
type = null;
typeName = type;
}
}
NodeStack localStack = stack.push(ei.getElement(), "*".equals(ei.getDefinition().getBase().getMax()) && ei.count == -1 ? 0 : ei.count, checkDefn, type == null ? typeDefn : resolveType(type, checkDefn.getType()));
@ -7115,4 +7136,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
this.example = example;
return this;
}
public IDigitalSignatureServices getSignatureServices() {
return signatureServices;
}
public void setSignatureServices(IDigitalSignatureServices signatureServices) {
this.signatureServices = signatureServices;
}
}