test primitive regexes if other tests pass

This commit is contained in:
Grahame Grieve 2023-03-05 06:14:07 +11:00
parent 472fb19542
commit 52c97f3c70
4 changed files with 55 additions and 2 deletions

View File

@ -527,6 +527,8 @@ public class I18nConstants {
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_LENGTH = "Type_Specific_Checks_DT_Primitive_Length";
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_NOTEMPTY = "Type_Specific_Checks_DT_Primitive_NotEmpty";
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX = "Type_Specific_Checks_DT_Primitive_Regex";
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX_TYPE = "Type_Specific_Checks_DT_Primitive_Regex_Type";
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX_EXCEPTION = "TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX_EXCEPTION";
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_VALUEEXT = "Type_Specific_Checks_DT_Primitive_ValueExt";
public static final String TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_WS = "Type_Specific_Checks_DT_Primitive_WS";
public static final String TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = "TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS";

View File

@ -212,6 +212,8 @@ Type_Specific_Checks_DT_OID_Valid = OIDs must be valid ({0})
Type_Specific_Checks_DT_Primitive_Length = value is longer than permitted maximum length of {0}
Type_Specific_Checks_DT_Primitive_NotEmpty = value cannot be empty
Type_Specific_Checks_DT_Primitive_Regex = Element value ''{0}'' does not meet regex ''{1}''
TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX_EXCEPTION = "Exception evaluating regex ''{0}'' on type {1}: {2}
Type_Specific_Checks_DT_Primitive_Regex_Type = Element value ''{0}'' does not meet {1} regex ''{2}''
Type_Specific_Checks_DT_Primitive_ValueExt = Primitive types must have a value or must have child extensions
Type_Specific_Checks_DT_Primitive_WS = Primitive types should not only be whitespace
Type_Specific_Checks_DT_String_Length = value is longer than permitted maximum length of 1 MB (1048576 bytes)

View File

@ -2288,6 +2288,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (regex != null) {
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, e.primitiveValue().matches(regex), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX, e.primitiveValue(), regex) && ok;
}
if (!"xhtml".equals(type)) {
if (securityChecks) {
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, !containsHtmlTags(e.primitiveValue()), I18nConstants.SECURITY_STRING_CONTENT_ERROR) && ok;
@ -2304,9 +2305,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
String url = e.primitiveValue();
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, !url.startsWith("oid:"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URI_OID) && ok;
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, !url.startsWith("uuid:"), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URI_UUID) && ok;
rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, url.equals(url.trim().replace(" ", ""))
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, url.equals(url.trim().replace(" ", ""))
// work around an old invalid example in a core package
|| "http://www.acme.com/identifiers/patient or urn:ietf:rfc:3986 if the Identifier.value itself is a full uri".equals(url), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URI_WS, url);
|| "http://www.acme.com/identifiers/patient or urn:ietf:rfc:3986 if the Identifier.value itself is a full uri".equals(url), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URI_WS, url) && ok;
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, !context.hasMaxLength() || context.getMaxLength() == 0 || url.length() <= context.getMaxLength(), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_LENGTH, context.getMaxLength()) && ok;
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, !context.hasMaxLength() || context.getMaxLength() == 0 || e.primitiveValue().length() <= context.getMaxLength(), I18nConstants.TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_LENGTH, context.getMaxLength()) && ok;
@ -2429,6 +2430,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, v >= 0, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_INTEGER_LT0) && ok;
if (type.equals("positiveInt"))
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, v > 0, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_INTEGER_LT1) && ok;
} else {
ok = false;
}
}
if (type.equals("integer64")) {
@ -2540,11 +2543,47 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (context.hasPattern()) {
ok = checkFixedValue(errors, path, e, context.getPattern(), profile.getVersionedUrl(), context.getSliceName(), null, true) && ok;
}
if (ok && !Utilities.existsInList(e.fhirType(), "id", "base64Binary", "markdown")) { // ids get checked elsewhere
String regext = FHIRPathExpressionFixer.fixRegex(getRegexFromType(e.fhirType()));
if (regext != null) {
try {
boolean matches = e.primitiveValue().matches(regext);
if (!matches) {
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, matches, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX_TYPE, e.primitiveValue(), e.fhirType(), regext) && ok;
}
} catch (Throwable ex) {
ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_PRIMITIVE_REGEX_EXCEPTION, regext, e.fhirType(), ex.getMessage()) && ok;
}
}
}
// for nothing to check
return ok;
}
private String getRegexFromType(String fhirType) {
StructureDefinition sd = context.fetchTypeDefinition(fhirType);
if (sd != null) {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.getPath().endsWith(".value")) {
String regex = ed.getExtensionString(ToolingExtensions.EXT_REGEX);
if (regex != null) {
return regex;
}
for (TypeRefComponent td : ed.getType()) {
regex = td.getExtensionString(ToolingExtensions.EXT_REGEX);
if (regex != null) {
return regex;
}
}
}
}
}
return null;
}
private boolean checkTypeValue(List<ValidationMessage> errors, String path, Element e, Element sd) {
String v = e.primitiveValue();
if (v == null) {

View File

@ -126,5 +126,15 @@ public class FHIRPathExpressionFixer {
}
return expr;
}
public static String fixRegex(String regex) {
if (regex == null) {
return null;
}
if (regex.equals("-?(0|[1-9][0-9]{0,17})(\\.[0-9]{1,17})?([eE][+-]?[0-9]{1,9}})?")) {
return "-?(0|[1-9][0-9]{0,17})(\\.[0-9]{1,17})?([eE](0|[+\\-]?[1-9][0-9]{0,9}))?";
}
return regex;
}
}