Add value set validation
This commit is contained in:
parent
9dd0e06d9c
commit
44d7a59115
|
@ -506,4 +506,9 @@ public class I18nConstants {
|
|||
public static final String SEARCHPARAMETER_BASE_WRONG = "SEARCHPARAMETER_BASE_WRONG";
|
||||
public static final String SEARCHPARAMETER_TYPE_WRONG = "SEARCHPARAMETER_TYPE_WRONG";
|
||||
public static final String SEARCHPARAMETER_EXP_WRONG = "SEARCHPARAMETER_EXP_WRONG";
|
||||
public static final String VALUESET_NO_SYSTEM_WARNING = "VALUESET_NO_SYSTEM_WARNING";
|
||||
public static final String VALUESET_UNC_SYSTEM_WARNING = "VALUESET_UNC_SYSTEM_WARNING";
|
||||
public static final String VALUESET_UNC_SYSTEM_WARNING_VER = "VALUESET_UNC_SYSTEM_WARNING_VER";
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE";
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER";
|
||||
}
|
|
@ -507,3 +507,8 @@ SEARCHPARAMETER_NOTFOUND = Unable to find the base Search Parameter {0} so can't
|
|||
SEARCHPARAMETER_BASE_WRONG = The base {1} is not listed as a base in the derivedFrom SearchParameter
|
||||
SEARCHPARAMETER_TYPE_WRONG = The type {1} is different to the type {0} in the derivedFrom SearchParameter
|
||||
SEARCHPARAMETER_TYPE_WRONG = The expression "{1}" is different to the expression "{0}" in the derivedFrom SearchParameter, and this likely indicates that the derivation relationship is not valid
|
||||
VALUESET_NO_SYSTEM_WARNING = No System specified, so Concepts and Filters can't be checked
|
||||
VALUESET_INCLUDE_INVALID_CONCEPT_CODE = The code {1} is not valid in the system {0}
|
||||
VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = The code {2} is not valid in the system {0} version {1}
|
||||
VALUESET_UNC_SYSTEM_WARNING = Unknown System specified, so Concepts and Filters can't be checked
|
||||
VALUESET_UNC_SYSTEM_WARNING_VER = Unknown System/Version specified, so Concepts and Filters can't be checked
|
||||
|
|
|
@ -459,9 +459,10 @@ public class BaseValidator {
|
|||
* 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 warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) {
|
||||
protected boolean warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass) {
|
||||
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.WARNING, null);
|
||||
String message = context.formatMessage(msg, theMessageArguments);
|
||||
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.WARNING, null);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
|
@ -473,7 +474,7 @@ public class BaseValidator {
|
|||
* 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 warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) {
|
||||
protected boolean warningHtml(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) {
|
||||
if (!thePass) {
|
||||
addValidationMessage(errors, type, path, msg, html, IssueSeverity.WARNING, null);
|
||||
}
|
||||
|
@ -487,7 +488,7 @@ public class BaseValidator {
|
|||
* 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 warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
|
||||
protected boolean warningHtml(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
|
||||
if (!thePass) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
addValidationMessage(errors, type, path, nmsg, html, IssueSeverity.WARNING, msg);
|
||||
|
|
|
@ -141,6 +141,7 @@ import org.hl7.fhir.validation.instance.type.CodeSystemValidator;
|
|||
import org.hl7.fhir.validation.instance.type.MeasureValidator;
|
||||
import org.hl7.fhir.validation.instance.type.QuestionnaireValidator;
|
||||
import org.hl7.fhir.validation.instance.type.SearchParameterValidator;
|
||||
import org.hl7.fhir.validation.instance.type.ValueSetValidator;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.Utilities.DecimalStatus;
|
||||
|
@ -3467,6 +3468,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
new CodeSystemValidator(context, timeTracker).validateCodeSystem(errors, element, stack);
|
||||
} else if (element.getType().equals("SearchParameter")) {
|
||||
new SearchParameterValidator(context, timeTracker).validateSearchParameter(errors, element, stack);
|
||||
} else if (element.getType().equals("ValueSet")) {
|
||||
new ValueSetValidator(context, timeTracker).validateValueSet(errors, element, stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
package org.hl7.fhir.validation.instance.type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
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;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||
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.utils.NodeStack;
|
||||
|
||||
public class ValueSetValidator extends BaseValidator {
|
||||
|
||||
public ValueSetValidator(IWorkerContext context, TimeTracker timeTracker) {
|
||||
super(context);
|
||||
source = Source.InstanceValidator;
|
||||
this.timeTracker = timeTracker;
|
||||
}
|
||||
|
||||
public void validateValueSet(List<ValidationMessage> errors, Element vs, NodeStack stack) {
|
||||
if (!VersionUtilities.isR2Ver(context.getVersion())) {
|
||||
List<Element> composes = vs.getChildrenByName("compose");
|
||||
int cc = 0;
|
||||
for (Element compose : composes) {
|
||||
validateValueSetCompose(errors, compose, stack.push(compose, cc, null, null));
|
||||
cc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateValueSetCompose(List<ValidationMessage> errors, Element compose, NodeStack stack) {
|
||||
List<Element> includes = compose.getChildrenByName("include");
|
||||
int ci = 0;
|
||||
for (Element include : includes) {
|
||||
validateValueSetInclude(errors, include, stack.push(include, ci, null, null));
|
||||
ci++;
|
||||
}
|
||||
List<Element> excludes = compose.getChildrenByName("exclude");
|
||||
int ce = 0;
|
||||
for (Element exclude : excludes) {
|
||||
validateValueSetInclude(errors, exclude, stack.push(exclude, ce, null, null));
|
||||
ce++;
|
||||
}
|
||||
}
|
||||
|
||||
private void validateValueSetInclude(List<ValidationMessage> errors, Element include, NodeStack stack) {
|
||||
String system = include.getChildValue("system");
|
||||
String version = include.getChildValue("version");
|
||||
boolean systemOk = true;
|
||||
List<Element> concepts = include.getChildrenByName("concept");
|
||||
List<Element> filters = include.getChildrenByName("filter");
|
||||
if (!Utilities.noString(system)) {
|
||||
int cc = 0;
|
||||
for (Element concept : concepts) {
|
||||
if (systemOk && !validateValueSetIncludeConcept(errors, concept, stack.push(concept, cc, null, null), system, version)) {
|
||||
systemOk = false;
|
||||
}
|
||||
cc++;
|
||||
}
|
||||
int cf = 0;
|
||||
for (Element filter : filters) {
|
||||
if (systemOk && !validateValueSetIncludeFilter(errors, include, stack.push(filter, cf, null, null), system, version)) {
|
||||
systemOk = false;
|
||||
}
|
||||
cf++;
|
||||
}
|
||||
warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), systemOk, version == null ? I18nConstants.VALUESET_UNC_SYSTEM_WARNING : I18nConstants.VALUESET_UNC_SYSTEM_WARNING_VER);
|
||||
} else {
|
||||
warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), filters.size() == 0 && concepts.size() == 0, I18nConstants.VALUESET_NO_SYSTEM_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateValueSetIncludeConcept(List<ValidationMessage> errors, Element concept, NodeStack stack, String system, String version) {
|
||||
String code = concept.getChildValue("code");
|
||||
if (version == null) {
|
||||
ValidationResult vv = context.validateCode(ValidationOptions.defaults(), new Coding(system, code, null), null);
|
||||
if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
return false;
|
||||
} else {
|
||||
boolean ok = vv.isOk();
|
||||
warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, code);
|
||||
}
|
||||
} else {
|
||||
ValidationResult vv = context.validateCode(ValidationOptions.defaults(), new Coding(system, code, null).setVersion(version), null);
|
||||
if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
return false;
|
||||
} else {
|
||||
boolean ok = vv.isOk();
|
||||
warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, code);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean validateValueSetIncludeFilter(List<ValidationMessage> errors, Element include, NodeStack push, String system, String version) {
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue