CodeSystem validation around count and content
This commit is contained in:
parent
cc5069ccb3
commit
ea4e592910
|
@ -966,6 +966,11 @@ public class I18nConstants {
|
||||||
public static final String MSG_DEPENDS_ON_EXTENSION = "MSG_DEPENDS_ON_EXTENSION";
|
public static final String MSG_DEPENDS_ON_EXTENSION = "MSG_DEPENDS_ON_EXTENSION";
|
||||||
public static final String MSG_DEPENDS_ON_PROFILE = "MSG_DEPENDS_ON_PROFILE";
|
public static final String MSG_DEPENDS_ON_PROFILE = "MSG_DEPENDS_ON_PROFILE";
|
||||||
public static final String VALIDATION_VAL_STATUS_INCONSISTENT = "VALIDATION_VAL_STATUS_INCONSISTENT";
|
public static final String VALIDATION_VAL_STATUS_INCONSISTENT = "VALIDATION_VAL_STATUS_INCONSISTENT";
|
||||||
|
public static final String CODESYSTEM_CS_COUNT_COMPLETE_WRONG = "CODESYSTEM_CS_COUNT_COMPLETE_WRONG";
|
||||||
|
public static final String CODESYSTEM_CS_COUNT_FRAGMENT_WRONG = "CODESYSTEM_CS_COUNT_FRAGMENT_WRONG";
|
||||||
|
public static final String CODESYSTEM_CS_COUNT_NOTPRESENT_ZERO = "CODESYSTEM_CS_COUNT_NOTPRESENT_ZERO";
|
||||||
|
public static final String CODESYSTEM_CS_COUNT_SUPPLEMENT_WRONG = "CODESYSTEM_CS_COUNT_SUPPLEMENT_WRONG";
|
||||||
|
public static final String CODESYSTEM_CS_COUNT_NO_CONTENT_ALLOWED = "CODESYSTEM_CS_COUNT_NO_CONTENT_ALLOWED";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1024,5 +1024,11 @@ MSG_DEPENDS_ON_EXPERIMENTAL = The {0} {1} is an experimental resource
|
||||||
MSG_DEPENDS_ON_DRAFT = The {0} {1} is a draft resource
|
MSG_DEPENDS_ON_DRAFT = The {0} {1} is a draft resource
|
||||||
MSG_DEPENDS_ON_EXTENSION = extension
|
MSG_DEPENDS_ON_EXTENSION = extension
|
||||||
MSG_DEPENDS_ON_PROFILE = profile
|
MSG_DEPENDS_ON_PROFILE = profile
|
||||||
VALIDATION_VAL_STATUS_INCONSISTENT = The resource status ''{0}'' amd the standards status ''{1}'' are not consistent
|
VALIDATION_VAL_STATUS_INCONSISTENT = The resource status ''{0}'' and the standards status ''{1}'' are not consistent
|
||||||
|
CODESYSTEM_CS_COUNT_COMPLETE_WRONG = The code system is complete, but the number of concepts ({0}) does not match the stated total number ({1})
|
||||||
|
CODESYSTEM_CS_COUNT_FRAGMENT_WRONG = The code system is a fragment/example, but the number of concepts ({0}) exceeds or matches the stated total number ({1})
|
||||||
|
CODESYSTEM_CS_COUNT_NOTPRESENT_ZERO = The code system has no content, but the exceeds the stated total number is 0 concepts - check that this isn't a complete code system that has no concepts, or update/remove the stated count
|
||||||
|
CODESYSTEM_CS_COUNT_SUPPLEMENT_WRONG = The code system supplement states the total number of concepts as {1}, but this is different to the underlying code system that states a value of {0}
|
||||||
|
CODESYSTEM_CS_COUNT_NO_CONTENT_ALLOWED = The code system says it has no content present, but concepts are found
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.elementmodel.Element;
|
import org.hl7.fhir.r5.elementmodel.Element;
|
||||||
import org.hl7.fhir.r5.model.Coding;
|
import org.hl7.fhir.r5.model.Coding;
|
||||||
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
@ -32,8 +33,9 @@ public class CodeSystemValidator extends BaseValidator {
|
||||||
String caseSensitive = cs.getNamedChildValue("caseSensitive");
|
String caseSensitive = cs.getNamedChildValue("caseSensitive");
|
||||||
String hierarchyMeaning = cs.getNamedChildValue("hierarchyMeaning");
|
String hierarchyMeaning = cs.getNamedChildValue("hierarchyMeaning");
|
||||||
String supp = cs.getNamedChildValue("supplements");
|
String supp = cs.getNamedChildValue("supplements");
|
||||||
|
int count = countConcepts(cs);
|
||||||
metaChecks(errors, cs, stack, url, content, caseSensitive, hierarchyMeaning, !Utilities.noString(supp));
|
|
||||||
|
metaChecks(errors, cs, stack, url, content, caseSensitive, hierarchyMeaning, !Utilities.noString(supp), count, supp);
|
||||||
|
|
||||||
String vsu = cs.getNamedChildValue("valueSet");
|
String vsu = cs.getNamedChildValue("valueSet");
|
||||||
if (!Utilities.noString(vsu)) {
|
if (!Utilities.noString(vsu)) {
|
||||||
|
@ -51,7 +53,6 @@ public class CodeSystemValidator extends BaseValidator {
|
||||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !vs.getCompose().getInclude().get(0).hasValueSet()
|
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !vs.getCompose().getInclude().get(0).hasValueSet()
|
||||||
&& !vs.getCompose().getInclude().get(0).hasConcept() && !vs.getCompose().getInclude().get(0).hasFilter(), I18nConstants.CODESYSTEM_CS_VS_INCLUDEDETAILS, url, vsu) && ok;
|
&& !vs.getCompose().getInclude().get(0).hasConcept() && !vs.getCompose().getInclude().get(0).hasFilter(), I18nConstants.CODESYSTEM_CS_VS_INCLUDEDETAILS, url, vsu) && ok;
|
||||||
if (vs.hasExpansion()) {
|
if (vs.hasExpansion()) {
|
||||||
int count = countConcepts(cs);
|
|
||||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.getExpansion().getContains().size() == count, I18nConstants.CODESYSTEM_CS_VS_EXP_MISMATCH, url, vsu, count, vs.getExpansion().getContains().size()) && ok;
|
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.getExpansion().getContains().size() == count, I18nConstants.CODESYSTEM_CS_VS_EXP_MISMATCH, url, vsu, count, vs.getExpansion().getContains().size()) && ok;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -71,7 +72,11 @@ public class CodeSystemValidator extends BaseValidator {
|
||||||
List<Element> concepts = cs.getChildrenByName("concept");
|
List<Element> concepts = cs.getChildrenByName("concept");
|
||||||
int ce = 0;
|
int ce = 0;
|
||||||
for (Element concept : concepts) {
|
for (Element concept : concepts) {
|
||||||
ok = validateSupplementConcept(errors, concept, stack.push(concept, ce, null, null), supp, options) && ok;
|
NodeStack nstack = stack.push(concept, ce, null, null);
|
||||||
|
if (ce == 0) {
|
||||||
|
rule(errors, "2023-08-15", IssueType.INVALID, nstack, !"not-present".equals(content), I18nConstants.CODESYSTEM_CS_COUNT_NO_CONTENT_ALLOWED);
|
||||||
|
}
|
||||||
|
ok = validateSupplementConcept(errors, concept, nstack, supp, options) && ok;
|
||||||
ce++;
|
ce++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -121,7 +126,7 @@ public class CodeSystemValidator extends BaseValidator {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void metaChecks(List<ValidationMessage> errors, Element cs, NodeStack stack, String url, String content, String caseSensitive, String hierarchyMeaning, boolean isSupplement) {
|
private void metaChecks(List<ValidationMessage> errors, Element cs, NodeStack stack, String url, String content, String caseSensitive, String hierarchyMeaning, boolean isSupplement, int count, String supp) {
|
||||||
if (isSupplement) {
|
if (isSupplement) {
|
||||||
if (!"supplement".equals(content)) {
|
if (!"supplement".equals(content)) {
|
||||||
NodeStack s = stack.push(cs.getNamedChild("content"), -1, null, null);
|
NodeStack s = stack.push(cs.getNamedChild("content"), -1, null, null);
|
||||||
|
@ -178,6 +183,40 @@ public class CodeSystemValidator extends BaseValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cs.hasChild("count")) {
|
||||||
|
int statedCount = Utilities.parseInt(cs.getNamedChildValue("count"), -1);
|
||||||
|
if (statedCount > -1 && content != null) { // error elsewhere
|
||||||
|
var nstack = stack.push(cs.getNamedChild("count"), -1, null, null);
|
||||||
|
switch (content) {
|
||||||
|
case "complete":
|
||||||
|
rule(errors, "2023-08-15", IssueType.INVALID, nstack, count == statedCount, I18nConstants.CODESYSTEM_CS_COUNT_COMPLETE_WRONG, count, statedCount);
|
||||||
|
break;
|
||||||
|
case "example":
|
||||||
|
case "fragment":
|
||||||
|
warning(errors, "2023-08-15", IssueType.INVALID, nstack, count < statedCount, I18nConstants.CODESYSTEM_CS_COUNT_FRAGMENT_WRONG, count, statedCount);
|
||||||
|
break;
|
||||||
|
case "not-present":
|
||||||
|
hint(errors, "2023-08-15", IssueType.INVALID, stack.push(cs.getNamedChild("concept"), -1, null, null), statedCount > 0, I18nConstants.CODESYSTEM_CS_COUNT_NOTPRESENT_ZERO, statedCount);
|
||||||
|
break;
|
||||||
|
case "supplement":
|
||||||
|
CodeSystem css = context.fetchCodeSystem(supp);
|
||||||
|
if (css != null) {
|
||||||
|
rule(errors, "2023-08-15", IssueType.INVALID, nstack, count == css.getCount(), I18nConstants.CODESYSTEM_CS_COUNT_SUPPLEMENT_WRONG, css.getCount(), statedCount);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("not-present".equals(content)) {
|
||||||
|
List<Element> concepts = cs.getChildrenByName("concept");
|
||||||
|
if (concepts.size() > 0) {
|
||||||
|
rule(errors, "2023-08-15", IssueType.INVALID, stack.push(concepts.get(0), 0, null, null), false, I18nConstants.CODESYSTEM_CS_COUNT_NO_CONTENT_ALLOWED);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue