Improve error message from validator when invariants fail

This commit is contained in:
Grahame Grieve 2023-09-15 10:13:02 -07:00
parent 55c800e80d
commit a59a9619d9
6 changed files with 61 additions and 11 deletions

View File

@ -194,10 +194,12 @@ public class ValueSetExpander extends ValueSetProcessBase {
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
n.setSystem(system);
n.setCode(code);
if (isAbstract)
if (isAbstract) {
n.setAbstract(true);
if (inactive)
}
if (inactive) {
n.setInactive(true);
}
if (deprecated) {
ValueSetUtilities.setDeprecated(vsProp, n);
}

View File

@ -207,6 +207,7 @@ public class I18nConstants {
public static final String INTERNAL_INT_BAD_TYPE = "Internal_INT_Bad_Type";
// public static final String INTERNAL_RECURSION_DETECTION_FIND_LOOP_PATH_RECURSION____CHECK_PATHS_ARE_VALID_FOR_PATH_ = "Internal_recursion_detection_find_loop_path_recursion____check_paths_are_valid_for_path_";
public static final String INV_FAILED = "INV_FAILED";
public static final String INV_FAILED_SOURCE = "INV_FAILED_SOURCE";
public static final String INVALID_SLICING__THERE_IS_MORE_THAN_ONE_TYPE_SLICE_AT__BUT_ONE_OF_THEM__HAS_MIN__1_SO_THE_OTHER_SLICES_CANNOT_EXIST = "Invalid_slicing__there_is_more_than_one_type_slice_at__but_one_of_them__has_min__1_so_the_other_slices_cannot_exist";
public static final String LANGUAGE_XHTML_LANG_DIFFERENT1 = "Language_XHTML_Lang_Different1";
public static final String LANGUAGE_XHTML_LANG_DIFFERENT2 = "Language_XHTML_Lang_Different2";

View File

@ -523,7 +523,7 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
public static final String NO_RULE_DATE = null;
private boolean matched; // internal use counting matching filters
private boolean ignorableError;
private String invId;
/**
* Constructor
@ -903,6 +903,14 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
return loc;
}
public String getInvId() {
return invId;
}
public void setInvId(String invId) {
this.invId = invId;
}
}

View File

@ -372,7 +372,7 @@ Illegal_path__in_differential_in__illegal_character_ = Invalid path ''{0}'' in d
Illegal_path__in_differential_in__no_unicode_whitespace = Invalid path ''{0}'' in differential in {1}: no unicode whitespace
Illegal_path__in_differential_in__name_portion_exceeds_64_chars_in_length = Invalid path ''{0}'' in differential in {1}: name portion exceeds 64 chars in length
Illegal_path__in_differential_in__name_portion_mising_ = Invalid path ''{0}'' in differential in {1}: name portion missing (''..'')
Illegal_path__in_differential_in__must_start_with_ = Invalid path ''{0}'' in differential in {1}: must start with {2}.{3}
Illegal_path__in_differential_in__must_start_with_ = Invalid path ''{0}'' in input differential in {1}: must start with {2}.{3}
No_path_value_on_element_in_differential_in_ = No path value on element in differential in {0}
No_path_on_element_in_differential_in_ = No path on element in differential in {0}
Unxpected_internal_condition__no_source_on_diff_element = Unexpected internal condition - no source on diff element
@ -738,6 +738,7 @@ BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_OUTCOME = This is not an OperationOutcom
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})
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}

View File

@ -325,6 +325,21 @@ public class BaseValidator implements IValidationContextResourceLoader {
return thePass;
}
/**
* Test a rule and add a {@link IssueSeverity#INFORMATION} validation message if the validation fails
*
* @param thePass
* Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/
protected boolean hintInv(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, String invId) {
if (!thePass && doingHints()) {
String message = context.formatMessage(msg);
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, msg).setInvId(invId);
}
return thePass;
}
protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, NodeStack stack, boolean thePass, String msg, Object... theMessageArguments) {
return hint(errors, ruleDate, type, stack.line(), stack.col(), stack.getLiteralPath(), thePass, msg, theMessageArguments);
}
@ -426,6 +441,14 @@ public class BaseValidator implements IValidationContextResourceLoader {
return thePass;
}
protected boolean ruleInv(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, String invId, Object... theMessageArguments) {
if (!thePass && doingErrors()) {
String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.ERROR, theMessage).setInvId(invId);
}
return thePass;
}
protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, NodeStack stack, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) {
String message = context.formatMessage(theMessage, theMessageArguments);
@ -578,6 +601,16 @@ public class BaseValidator implements IValidationContextResourceLoader {
}
protected boolean warningInv(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, String invId, Object... theMessageArguments) {
if (!thePass && doingWarnings()) {
String nmsg = context.formatMessage(msg, theMessageArguments);
IssueSeverity severity = IssueSeverity.WARNING;
addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, msg).setInvId(invId);
}
return thePass;
}
protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, NodeStack stack, boolean thePass, String msg, Object... theMessageArguments) {
return warning(errors, ruleDate, type, stack.line(), stack.col(), stack.getLiteralPath(), thePass, msg, theMessageArguments);
}

View File

@ -6578,21 +6578,26 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (!Utilities.noString(msg)) {
msg = msg + " (log: " + msg + ")";
}
if (inv.hasSource()) {
msg = context.formatMessage(I18nConstants.INV_FAILED_SOURCE, inv.getKey() + ": '" + inv.getHuman()+"'", inv.getSource())+msg;
} else {
msg = context.formatMessage(I18nConstants.INV_FAILED, inv.getKey() + ": '" + inv.getHuman()+"'")+msg;
}
String invId = (inv.hasSource() ? inv.getSource() : profile.getUrl()) + "#"+inv.getKey();
if (inv.hasExtension(ToolingExtensions.EXT_BEST_PRACTICE) &&
ToolingExtensions.readBooleanExtension(inv, ToolingExtensions.EXT_BEST_PRACTICE)) {
msg = msg +" (Best Practice Recommendation)";
if (bpWarnings == BestPracticeWarningLevel.Hint)
hint(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg);
hintInv(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg, invId);
else if (/*bpWarnings == null || */ bpWarnings == BestPracticeWarningLevel.Warning)
warning(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg);
warningInv(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg, invId);
else if (bpWarnings == BestPracticeWarningLevel.Error)
ok = rule(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg) && ok;
ok = ruleInv(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg, invId) && ok;
} else if (inv.getSeverity() == ConstraintSeverity.ERROR) {
ok = rule(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg) && ok;
ok = ruleInv(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg, invId) && ok;
} else if (inv.getSeverity() == ConstraintSeverity.WARNING) {
warning(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg);
warningInv(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, invOK, msg, invId);
}
}
return ok;