Merge pull request #1241 from hapifhir/gg-202304-extension-validation

Gg 202304 extension validation
This commit is contained in:
Grahame Grieve 2023-04-28 17:47:19 +10:00 committed by GitHub
commit bef3f68314
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 3 deletions

View File

@ -63,6 +63,7 @@ public class TerminologyClientR4 implements TerminologyClient {
public TerminologyClientR4(String id, String address, String userAgent) throws URISyntaxException { public TerminologyClientR4(String id, String address, String userAgent) throws URISyntaxException {
this.client = new FHIRToolingClient(address, userAgent); this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(new ClientHeaders()); setClientHeaders(new ClientHeaders());
this.id = id;
} }
public TerminologyClientR4(String id, String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException { public TerminologyClientR4(String id, String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException {

View File

@ -859,6 +859,9 @@ public class I18nConstants {
public static final String UNKNOWN_CODESYSTEM_VERSION = "UNKNOWN_CODESYSTEM_VERSION"; public static final String UNKNOWN_CODESYSTEM_VERSION = "UNKNOWN_CODESYSTEM_VERSION";
public static final String VALUESET_TOO_COSTLY = "VALUESET_TOO_COSTLY"; public static final String VALUESET_TOO_COSTLY = "VALUESET_TOO_COSTLY";
public static final String NO_VALID_DISPLAY_FOUND = "NO_VALID_DISPLAY_FOUND"; public static final String NO_VALID_DISPLAY_FOUND = "NO_VALID_DISPLAY_FOUND";
public static final String SD_NO_CONTEXT_WHEN_NOT_EXTENSION = "SD_NO_CONTEXT_WHEN_NOT_EXTENSION";
public static final String SD_CONTEXT_SHOULD_NOT_BE_ELEMENT = "SD_CONTEXT_SHOULD_NOT_BE_ELEMENT";
public static final String SD_NO_CONTEXT_INV_WHEN_NOT_EXTENSION = "SD_NO_CONTEXT_INV_WHEN_NOT_EXTENSION";
} }

View File

@ -72,7 +72,7 @@ Profile_VAL_MissingElement = Missing element ''{0}'' - required by fixed value a
Profile_VAL_NotAllowed = The element {0} is present in the instance but not allowed in the applicable {1} specified in profile Profile_VAL_NotAllowed = The element {0} is present in the instance but not allowed in the applicable {1} specified in profile
Measure_MR_M_None = No Measure is identified, so no validation can be performed against the Measure Measure_MR_M_None = No Measure is identified, so no validation can be performed against the Measure
Measure_MR_M_NotFound = The Measure ''{0}'' could not be resolved, so no validation can be performed against the Measure Measure_MR_M_NotFound = The Measure ''{0}'' could not be resolved, so no validation can be performed against the Measure
Questionnaire_QR_Item_BadOption = The code provided {1} in the system {0}) is not in the options value set ({2}) in the questionnaire Questionnaire_QR_Item_BadOption = The code provided {1} in the system {0}) is not in the options value set ({2}) in the questionnaire: {3}
QUESTIONNAIRE_QR_ITEM_BADOPTION_CS = The code provided {1} cannot be validated in the options value set ({2}) in the questionnaire because the system {0} is unknown QUESTIONNAIRE_QR_ITEM_BADOPTION_CS = The code provided {1} cannot be validated in the options value set ({2}) in the questionnaire because the system {0} is unknown
Questionnaire_QR_Item_Coding = Error {0} validating Coding against Questionnaire Options Questionnaire_QR_Item_Coding = Error {0} validating Coding against Questionnaire Options
Questionnaire_QR_Item_CodingNoOptions = Cannot validate Coding option because no option list is provided Questionnaire_QR_Item_CodingNoOptions = Cannot validate Coding option because no option list is provided
@ -481,7 +481,6 @@ Unable_to_resolve_system__value_set_has_multiple_matches = Unable to resolve sys
Unable_to_resolve_system__value_set_has_no_includes_or_expansion = Unable to resolve system - value set {0} has no includes or expansion Unable_to_resolve_system__value_set_has_no_includes_or_expansion = Unable to resolve system - value set {0} has no includes or expansion
Unable_to_resolve_system__no_value_set = Unable to resolve system - no value set Unable_to_resolve_system__no_value_set = Unable to resolve system - no value set
This_base_property_must_be_an_Array_not_ = This base property must be an Array, not {0} This_base_property_must_be_an_Array_not_ = This base property must be an Array, not {0}
This_property_must_be_an_Array_not_ = This property must be an Array, not {0}
documentmsg = (document) documentmsg = (document)
xml_attr_value_invalid = The XML Attribute {0} has an invalid character xml_attr_value_invalid = The XML Attribute {0} has an invalid character
xml_encoding_invalid = The XML encoding is invalid (must be UTF-8) xml_encoding_invalid = The XML encoding is invalid (must be UTF-8)
@ -912,6 +911,9 @@ UNABLE_TO_INFER_CODESYSTEM = The System URI could not be determined for the code
VALUESET_TOO_COSTLY = The value set {0} has too many codes to display ({1}) VALUESET_TOO_COSTLY = The value set {0} has too many codes to display ({1})
NO_VALID_DISPLAY_FOUND_one = No valid Display Names found for {1}#{2} in the language {3} NO_VALID_DISPLAY_FOUND_one = No valid Display Names found for {1}#{2} in the language {3}
NO_VALID_DISPLAY_FOUND_other = No valid Display Names found for {1}#{2} in the languages {3} NO_VALID_DISPLAY_FOUND_other = No valid Display Names found for {1}#{2} in the languages {3}
SD_NO_CONTEXT_WHEN_NOT_EXTENSION = The type is {0} so an extension context should not be specified
SD_NO_CONTEXT_INV_WHEN_NOT_EXTENSION = The type is {0} so an extension context invariants should not be specified
SD_CONTEXT_SHOULD_NOT_BE_ELEMENT = Review the extension type: extensions should not have a context of {0} unless it''s really intended that they can be used anywhere

View File

@ -566,7 +566,7 @@ public class QuestionnaireValidator extends BaseValidator {
if (res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { if (res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
txWarning(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION_CS, c.getSystem(), c.getCode(), vs.present()); txWarning(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION_CS, c.getSystem(), c.getCode(), vs.present());
} else { } else {
ok = txRule(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION, c.getSystem(), c.getCode(), vs.present()) && ok; ok = txRule(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION, c.getSystem(), c.getCode(), vs.present(), res.getMessage()) && ok;
} }
} else if (res.getSeverity() != null) { } else if (res.getSeverity() != null) {
super.addValidationMessage(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine, null); super.addValidationMessage(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine, null);

View File

@ -73,6 +73,8 @@ public class StructureDefinitionValidator extends BaseValidator {
String typeName = null; String typeName = null;
try { try {
sd = loadAsSD(src); sd = loadAsSD(src);
checkExtensionContext(errors, src, stack);
List<ElementDefinition> snapshot = sd.getSnapshot().getElement(); List<ElementDefinition> snapshot = sd.getSnapshot().getElement();
sd.setSnapshot(null); sd.setSnapshot(null);
typeName = sd.getTypeName(); typeName = sd.getTypeName();
@ -132,6 +134,41 @@ public class StructureDefinitionValidator extends BaseValidator {
return ok; return ok;
} }
private void checkExtensionContext(List<ValidationMessage> errors, Element src, NodeStack stack) {
String type = src.getNamedChildValue("type");
List<Element> eclist = src.getChildren("context");
List<Element> cilist = src.getChildren("contextInvariant");
int i = 0;
for (Element ec : eclist) {
NodeStack n = stack.push(ec, i, null, null);
if ("Extension".equals(type)) {
String ct = null;
String cv = null;
if (VersionUtilities.isR4Plus(context.getVersion())) {
ct = ec.getNamedChildValue("type");
cv = ec.getNamedChildValue("expression");
} else {
ct = src.getNamedChildValue("contextType"); /// todo - this doesn't have the right value
cv = ec.primitiveValue();
}
if ("element".equals(ct) && "Element".equals(cv)) {
warning(errors, "2023-04-23", IssueType.BUSINESSRULE, n.getLiteralPath(), false, I18nConstants.SD_CONTEXT_SHOULD_NOT_BE_ELEMENT, cv);
}
} else {
rule(errors, "2023-04-23", IssueType.INVALID, n.getLiteralPath(), false, I18nConstants.SD_NO_CONTEXT_WHEN_NOT_EXTENSION, type);
}
}
i = 0;
for (Element ci : cilist) {
NodeStack n = stack.push(ci, i, null, null);
if ("Extension".equals(type)) {
} else {
rule(errors, "2023-04-23", IssueType.INVALID, n.getLiteralPath(), false, I18nConstants.SD_NO_CONTEXT_INV_WHEN_NOT_EXTENSION, type);
}
}
}
private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName) { private boolean validateElementList(List<ValidationMessage> errors, Element elementList, NodeStack stack, boolean snapshot, boolean hasSnapshot, StructureDefinition sd, String typeName) {
boolean ok = true; boolean ok = true;
List<Element> elements = elementList.getChildrenByName("element"); List<Element> elements = elementList.getChildrenByName("element");