add value set qa checking
This commit is contained in:
parent
e324047735
commit
8980df2364
|
@ -922,6 +922,8 @@ public class I18nConstants {
|
|||
public static final String TERMINOLOGY_TX_HINT = "TERMINOLOGY_TX_HINT";
|
||||
public static final String TERMINOLOGY_TX_WARNING = "TERMINOLOGY_TX_WARNING";
|
||||
public static final String SD_ED_TYPE_PROFILE_WRONG_TYPE = "SD_ED_TYPE_PROFILE_WRONG_TYPE";
|
||||
public static final String VALUESET_CONCEPT_DISPLAY_PRESENCE_MIXED = "VALUESET_CONCEPT_DISPLAY_PRESENCE_MIXED";
|
||||
public static final String VALUESET_CONCEPT_DISPLAY_SCT_TAG_MIXED = "VALUESET_CONCEPT_DISPLAY_SCT_TAG_MIXED";
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -977,3 +977,5 @@ TERMINOLOGY_TX_HINT = {1}
|
|||
TERMINOLOGY_TX_WARNING = {1}
|
||||
SD_ED_TYPE_WRONG_TYPE_one = The element has a type {0} which is different to the type {1} on the base profile {2}
|
||||
SD_ED_TYPE_WRONG_TYPE_other = The element has a type {0} which is not in the types {1} on the base profile {2}
|
||||
VALUESET_CONCEPT_DISPLAY_PRESENCE_MIXED = This include has some concepts with displays and some without - check that this is what is intended
|
||||
VALUESET_CONCEPT_DISPLAY_SCT_TAG_MIXED = This SNOMED-CT based include has some concepts with semantic tags (FSN terms) and some without (preferred terms) - check that this is what is intended
|
||||
|
|
|
@ -22,10 +22,79 @@ import org.hl7.fhir.utilities.validation.ValidationOptions;
|
|||
import org.hl7.fhir.validation.BaseValidator;
|
||||
import org.hl7.fhir.validation.TimeTracker;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||
import org.hl7.fhir.validation.instance.type.ValueSetValidator.SystemLevelValidator;
|
||||
import org.hl7.fhir.validation.instance.utils.NodeStack;
|
||||
|
||||
public class ValueSetValidator extends BaseValidator {
|
||||
|
||||
public class SystemLevelValidator {
|
||||
protected List<ValidationMessage> errors;
|
||||
protected Element inc;
|
||||
protected NodeStack stack;
|
||||
|
||||
private boolean noDisplay = false;
|
||||
private boolean hasDisplay = false;
|
||||
protected SystemLevelValidator(List<ValidationMessage> errors, Element inc, NodeStack stack) {
|
||||
super();
|
||||
this.errors = errors;
|
||||
this.inc = inc;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public void checkConcept(String code, String display) {
|
||||
if (Utilities.noString(display)) {
|
||||
noDisplay = true;
|
||||
} else {
|
||||
hasDisplay = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
hint(errors, "2023-07-21", IssueType.BUSINESSRULE, inc.line(), inc.col(), stack.getLiteralPath(), !(noDisplay && hasDisplay), I18nConstants.VALUESET_CONCEPT_DISPLAY_PRESENCE_MIXED);
|
||||
}
|
||||
}
|
||||
|
||||
public class SnomedCTValidator extends SystemLevelValidator {
|
||||
private boolean noTag = false;
|
||||
private boolean hasTag = false;
|
||||
|
||||
protected SnomedCTValidator(List<ValidationMessage> errors, Element inc, NodeStack stack) {
|
||||
super(errors, inc, stack);
|
||||
}
|
||||
public void checkConcept(String code, String display) {
|
||||
super.checkConcept(code, display);
|
||||
if (!Utilities.noString(display)) {
|
||||
boolean tagged = display.endsWith(")") && display.indexOf("(") > display.length() - 20;
|
||||
if (tagged) {
|
||||
hasTag = true;
|
||||
} else {
|
||||
noTag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void finish() {
|
||||
hint(errors, "2023-07-21", IssueType.BUSINESSRULE, inc.line(), inc.col(), stack.getLiteralPath(), !(noTag && hasTag), I18nConstants.VALUESET_CONCEPT_DISPLAY_SCT_TAG_MIXED);
|
||||
}
|
||||
}
|
||||
|
||||
public class GeneralValidator extends SystemLevelValidator {
|
||||
|
||||
protected GeneralValidator(List<ValidationMessage> errors, Element inc, NodeStack stack) {
|
||||
super(errors, inc, stack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private SystemLevelValidator getSystemValidator(String system, List<ValidationMessage> errors, Element inc, NodeStack stack) {
|
||||
if (system == null) {
|
||||
return new GeneralValidator(errors, inc, stack);
|
||||
}
|
||||
switch (system) {
|
||||
case "http://snomed.info/sct" :return new SnomedCTValidator(errors, inc, stack);
|
||||
default: return new GeneralValidator(errors, inc, stack);
|
||||
}
|
||||
}
|
||||
|
||||
public class VSCodingValidationRequest extends CodingValidationRequest {
|
||||
|
||||
private NodeStack stack;
|
||||
|
@ -139,6 +208,8 @@ public class ValueSetValidator extends BaseValidator {
|
|||
}
|
||||
List<Element> concepts = include.getChildrenByName("concept");
|
||||
List<Element> filters = include.getChildrenByName("filter");
|
||||
|
||||
SystemLevelValidator slv = getSystemValidator(system, errors, include, stack);
|
||||
if (!Utilities.noString(system)) {
|
||||
boolean systemOk = true;
|
||||
int cc = 0;
|
||||
|
@ -147,10 +218,10 @@ public class ValueSetValidator extends BaseValidator {
|
|||
for (Element concept : concepts) {
|
||||
// we treat the first differently because we want to know if tbe system is worth validating. if it is, then we batch the rest
|
||||
if (first) {
|
||||
systemOk = validateValueSetIncludeConcept(errors, concept, stack, stack.push(concept, cc, null, null), system, version);
|
||||
systemOk = validateValueSetIncludeConcept(errors, concept, stack, stack.push(concept, cc, null, null), system, version, slv);
|
||||
first = false;
|
||||
} else if (systemOk) {
|
||||
batch.add(prepareValidateValueSetIncludeConcept(errors, concept, stack.push(concept, cc, null, null), system, version));
|
||||
batch.add(prepareValidateValueSetIncludeConcept(errors, concept, stack.push(concept, cc, null, null), system, version, slv));
|
||||
}
|
||||
cc++;
|
||||
}
|
||||
|
@ -180,19 +251,24 @@ public class ValueSetValidator extends BaseValidator {
|
|||
|
||||
int cf = 0;
|
||||
for (Element filter : filters) {
|
||||
if (systemOk && !validateValueSetIncludeFilter(errors, include, stack.push(filter, cf, null, null), system, version)) {
|
||||
if (systemOk && !validateValueSetIncludeFilter(errors, include, stack.push(filter, cf, null, null), system, version, slv)) {
|
||||
systemOk = false;
|
||||
}
|
||||
cf++;
|
||||
}
|
||||
slv.finish();
|
||||
} else {
|
||||
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), filters.size() == 0 && concepts.size() == 0, I18nConstants.VALUESET_NO_SYSTEM_WARNING);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateValueSetIncludeConcept(List<ValidationMessage> errors, Element concept, NodeStack stackInc, NodeStack stack, String system, String version) {
|
||||
|
||||
private boolean validateValueSetIncludeConcept(List<ValidationMessage> errors, Element concept, NodeStack stackInc, NodeStack stack, String system, String version, SystemLevelValidator slv) {
|
||||
String code = concept.getChildValue("code");
|
||||
String display = concept.getChildValue("display");
|
||||
slv.checkConcept(code, display);
|
||||
|
||||
if (version == null) {
|
||||
ValidationResult vv = context.validateCode(ValidationOptions.defaults(), new Coding(system, code, null), null);
|
||||
if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
|
@ -229,8 +305,11 @@ public class ValueSetValidator extends BaseValidator {
|
|||
return true;
|
||||
}
|
||||
|
||||
private VSCodingValidationRequest prepareValidateValueSetIncludeConcept(List<ValidationMessage> errors, Element concept, NodeStack stack, String system, String version) {
|
||||
private VSCodingValidationRequest prepareValidateValueSetIncludeConcept(List<ValidationMessage> errors, Element concept, NodeStack stack, String system, String version, SystemLevelValidator slv) {
|
||||
String code = concept.getChildValue("code");
|
||||
String display = concept.getChildValue("display");
|
||||
slv.checkConcept(code, display);
|
||||
|
||||
Coding c = new Coding(system, code, null);
|
||||
if (version != null) {
|
||||
c.setVersion(version);
|
||||
|
@ -238,7 +317,11 @@ public class ValueSetValidator extends BaseValidator {
|
|||
return new VSCodingValidationRequest(stack, c);
|
||||
}
|
||||
|
||||
private boolean validateValueSetIncludeFilter(List<ValidationMessage> errors, Element include, NodeStack push, String system, String version) {
|
||||
private boolean validateValueSetIncludeFilter(List<ValidationMessage> errors, Element filter, NodeStack push, String system, String version, SystemLevelValidator slv) {
|
||||
//
|
||||
// String display = concept.getChildValue("display");
|
||||
// slv.checkConcept(code, display);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue