CodeSystem property validation improvements
This commit is contained in:
parent
413c047b56
commit
30545d31c1
|
@ -234,6 +234,15 @@ public class CodeSystemUtilities extends TerminologyUtilities {
|
|||
concept.addProperty().setCode(code).setValue(value);
|
||||
}
|
||||
|
||||
public static void setProperty(CodeSystem cs, ConceptDefinitionComponent concept, String url, String code, DataType value) throws FHIRFormatError {
|
||||
defineProperty(cs, code, propertyTypeForValue(value), url);
|
||||
ConceptPropertyComponent p = getProperty(concept, code);
|
||||
if (p != null)
|
||||
p.setValue(value);
|
||||
else
|
||||
concept.addProperty().setCode(code).setValue(value);
|
||||
}
|
||||
|
||||
|
||||
private static PropertyType propertyTypeForValue(DataType value) {
|
||||
if (value instanceof BooleanType) {
|
||||
|
@ -262,6 +271,9 @@ public class CodeSystemUtilities extends TerminologyUtilities {
|
|||
|
||||
private static String defineProperty(CodeSystem cs, String code, PropertyType pt) {
|
||||
String url = "http://hl7.org/fhir/concept-properties#"+code;
|
||||
return defineProperty(cs, code, pt, url);
|
||||
}
|
||||
private static String defineProperty(CodeSystem cs, String code, PropertyType pt, String url) {
|
||||
for (PropertyComponent p : cs.getProperty()) {
|
||||
if (p.hasCode() && p.getCode().equals(code)) {
|
||||
if (!p.getUri().equals(url)) {
|
||||
|
|
|
@ -2235,4 +2235,11 @@ public class Utilities {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static String stripEoln(String text) {
|
||||
if (text == null) {
|
||||
return "";
|
||||
}
|
||||
return text.replace("\r\n", " ").replace("\n", " ").replace("\r", " ");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1101,6 +1101,7 @@ public class I18nConstants {
|
|||
public static final String VALUESET_BAD_FILTER_VALUE_HAS_COMMA = "VALUESET_BAD_FILTER_VALUE_HAS_COMMA";
|
||||
public static final String VALUESET_BAD_FILTER_VALUE_VALID_REGEX = "VALUESET_BAD_FILTER_VALUE_VALID_REGEX";
|
||||
public static final String VALUESET_BAD_PROPERTY_NO_REGEX = "VALUESET_BAD_PROPERTY_NO_REGEX";
|
||||
public static final String CODESYSTEM_PROPERTY_CODE_WARNING = "CODESYSTEM_PROPERTY_CODE_WARNING";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1159,4 +1159,5 @@ VALUESET_BAD_FILTER_OP = The operation ''{0}'' is not allowed for property ''{1}
|
|||
VALUESET_BAD_FILTER_VALUE_HAS_COMMA = The filter value has a comma, but the operation is different to 'in' and 'not-in', so the comma will be interpreted as part of the {0} value
|
||||
VALUESET_BAD_FILTER_VALUE_VALID_REGEX = The value for a filter based on property ''{0}'' should be a valid regex, not ''{1}'' (err = ''{2}'')
|
||||
VALUESET_BAD_PROPERTY_NO_REGEX = Cannot apply a regex filter to the property ''{0}'' (usually regex filters are applied to the codes, or a named property of the code system)
|
||||
CODESYSTEM_PROPERTY_CODE_WARNING = If the type is ''code'', then the valueSet property should be provided to clarify what kind of code will be found in the element
|
||||
|
||||
|
|
|
@ -3344,7 +3344,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
Set<String> refs = new HashSet<>();
|
||||
int count = countTargetMatches(resource, ref, true, "$", refs);
|
||||
if (count == 0) {
|
||||
rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_XHTML_RESOLVE, href, xpath, node.allText());
|
||||
rule(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_XHTML_RESOLVE, href, xpath, Utilities.stripEoln(node.allText()));
|
||||
} else if (count > 1) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_XHTML_MULTIPLE_MATCHES, href, xpath, node.allText(), CommaSeparatedStringBuilder.join(", ", refs));
|
||||
}
|
||||
|
@ -5760,7 +5760,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
|
||||
if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wg != null && !url.contains("http://hl7.org/fhir/sid"), I18nConstants.VALIDATION_HL7_WG_NEEDED, ToolingExtensions.EXT_WORKGROUP)) {
|
||||
if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wg != null || url.contains("http://hl7.org/fhir/sid"), I18nConstants.VALIDATION_HL7_WG_NEEDED, ToolingExtensions.EXT_WORKGROUP)) {
|
||||
HL7WorkGroup wgd = HL7WorkGroups.find(wg);
|
||||
if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wgd != null, I18nConstants.VALIDATION_HL7_WG_UNKNOWN, wg)) {
|
||||
String rpub = "HL7 International / "+wgd.getName();
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
|
@ -57,16 +58,30 @@ public class CodeSystemValidator extends BaseValidator {
|
|||
|
||||
}
|
||||
|
||||
public enum CodeValidationRule {
|
||||
NO_VALIDATION, INTERNAL_CODE, VS_ERROR, VS_WARNING
|
||||
}
|
||||
|
||||
public class PropertyDef {
|
||||
private String uri;
|
||||
private String code;
|
||||
private String type;
|
||||
|
||||
private CodeValidationRule rule;
|
||||
private String valueset;
|
||||
|
||||
protected PropertyDef(String uri, String code, String type) {
|
||||
super();
|
||||
this.uri = uri;
|
||||
this.code = code;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setCodeValidationRules(CodeValidationRule rule, String valueset) {
|
||||
this.rule = rule;
|
||||
this.valueset = valueset;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
@ -76,9 +91,14 @@ public class CodeSystemValidator extends BaseValidator {
|
|||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
public String getValueset() {
|
||||
return valueset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final String VS_PROP_STATUS = null;
|
||||
|
||||
public CodeSystemValidator(BaseValidator parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
@ -252,8 +272,7 @@ public class CodeSystemValidator extends BaseValidator {
|
|||
ukp = KnownProperty.ItemWeight;
|
||||
break;
|
||||
default:
|
||||
ok = false;
|
||||
rule(errors, "2024-03-06", IssueType.BUSINESSRULE, cs.line(), cs.col(), stack.getLiteralPath(), false, I18nConstants.CODESYSTEM_PROPERTY_BAD_HL7_URI, uri);
|
||||
ok = rule(errors, "2024-03-06", IssueType.BUSINESSRULE, cs.line(), cs.col(), stack.getLiteralPath(), isBaseSpec(cs.getNamedChildValue("url")), I18nConstants.CODESYSTEM_PROPERTY_BAD_HL7_URI, uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +328,31 @@ public class CodeSystemValidator extends BaseValidator {
|
|||
if (type != null) {
|
||||
ok = rule(errors, "2024-03-06", IssueType.BUSINESSRULE, cs.line(), cs.col(), stack.getLiteralPath(), type.equals(ukp.getType()), I18nConstants.CODESYSTEM_PROPERTY_URI_TYPE_MISMATCH, uri, ukp.getType(),type) && ok;
|
||||
}
|
||||
switch (ukp) {
|
||||
case Child:
|
||||
case Parent:
|
||||
case PartOf:
|
||||
case Synonym:
|
||||
pd.setCodeValidationRules(CodeValidationRule.INTERNAL_CODE, null);
|
||||
break;
|
||||
case Status:
|
||||
pd.setCodeValidationRules(CodeValidationRule.VS_WARNING, VS_PROP_STATUS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if ("code".equals(pd.getType())) {
|
||||
if (property.hasExtension("http://hl7.org/fhir/6.0/StructureDefinition/extension-CodeSystem.property.valueSet")) {
|
||||
pd.setCodeValidationRules(CodeValidationRule.VS_ERROR, property.getExtensionValue("http://hl7.org/fhir/6.0/StructureDefinition/extension-CodeSystem.property.valueSet").primitiveValue());
|
||||
} else if (VersionUtilities.isR6Plus(context.getVersion())) {
|
||||
hint(errors, "2024-03-18", IssueType.BUSINESSRULE, cs.line(), cs.col(), stack.getLiteralPath(), ukp != null && type.equals(ukp.getType()), I18nConstants.CODESYSTEM_PROPERTY_CODE_WARNING);
|
||||
} else {
|
||||
|
||||
}
|
||||
} else if ("Coding".equals(pd.getType()) && property.hasExtension("http://hl7.org/fhir/6.0/StructureDefinition/extension-CodeSystem.property.valueSet")) {
|
||||
pd.setCodeValidationRules(CodeValidationRule.VS_ERROR, property.getExtensionValue("http://hl7.org/fhir/6.0/StructureDefinition/extension-CodeSystem.property.valueSet").primitiveValue());
|
||||
}
|
||||
|
||||
if (uri == null) {
|
||||
if (ckp == null) {
|
||||
hint(errors, "2024-03-06", IssueType.BUSINESSRULE, cs.line(), cs.col(), stack.getLiteralPath(), false, I18nConstants.CODESYSTEM_PROPERTY_UNKNOWN_CODE, code);
|
||||
|
@ -323,6 +366,10 @@ public class CodeSystemValidator extends BaseValidator {
|
|||
return ok;
|
||||
}
|
||||
|
||||
private boolean isBaseSpec(String url) {
|
||||
return url.startsWith("http://hl7.org/fhir/") && !url.substring(20).contains("/");
|
||||
}
|
||||
|
||||
private boolean checkConcept(List<ValidationMessage> errors, Element cs, NodeStack stack, boolean caseSensitive, String hierarchyMeaning, CodeSystem csB, Element concept, Set<String> codes, Map<String, PropertyDef> properties) {
|
||||
boolean ok = true;
|
||||
String code = concept.getNamedChildValue("code");
|
||||
|
|
Loading…
Reference in New Issue