fix up display validation on codes

This commit is contained in:
Grahame Grieve 2019-05-29 08:39:59 +10:00
parent c476e89091
commit e3faaa5ccc
3 changed files with 29 additions and 23 deletions

View File

@ -167,10 +167,12 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
}
// also check to see if the value set has another display
ConceptReferenceComponent vs = findValueSetRef(code.getSystem(), code.getCode());
if (vs != null && vs.hasDisplay()) {
b.append(vs.getDisplay());
if (code.getDisplay().equalsIgnoreCase(vs.getDisplay()))
return new ValidationResult(cc);
if (vs != null && (vs.hasDisplay() ||vs.hasDesignation())) {
if (vs.hasDisplay()) {
b.append(vs.getDisplay());
if (code.getDisplay().equalsIgnoreCase(vs.getDisplay()))
return new ValidationResult(cc);
}
for (ConceptReferenceDesignationComponent ds : vs.getDesignation()) {
b.append(ds.getValue());
if (code.getDisplay().equalsIgnoreCase(ds.getValue()))
@ -188,7 +190,7 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
if (system.equals(exp.getSystem()) && code.equals(exp.getCode())) {
ConceptReferenceComponent cc = new ConceptReferenceComponent();
cc.setDisplay(exp.getDisplay());
cc.setDesignation(cc.getDesignation());
cc.setDesignation(exp.getDesignation());
return cc;
}
}
@ -382,6 +384,7 @@ public class ValueSetCheckerSimple implements ValueSetChecker {
private boolean codeInConceptFilter(CodeSystem cs, ConceptSetFilterComponent f, String code) throws FHIRException {
switch (f.getOp()) {
case ISA: return codeInConceptIsAFilter(cs, f, code);
case ISNOTA: return !codeInConceptIsAFilter(cs, f, code);
default:
System.out.println("todo: handle concept filters with op = "+f.getOp());
throw new FHIRException("Unable to handle system "+cs.getUrl()+" concept filter with op = "+f.getOp());

View File

@ -821,14 +821,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
// public API
private boolean checkCode(List<ValidationMessage> errors, Element element, String path, String code, String system, String display) throws TerminologyServiceException {
private boolean checkCode(List<ValidationMessage> errors, Element element, String path, String code, String system, String display, boolean checkDisplay) throws TerminologyServiceException {
long t = System.nanoTime();
boolean ss = context.supportsSystem(system);
txTime = txTime + (System.nanoTime() - t);
if (ss) {
t = System.nanoTime();
ValidationResult s = context.validateCode(system, code, display);
ValidationResult s = context.validateCode(system, code, checkDisplay ? display : null);
txTime = txTime + (System.nanoTime() - t);
if (s == null)
return true;
@ -936,7 +935,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
private void checkCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext) {
private boolean checkCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext) {
boolean res = true;
if (!noTerminologyChecks && theElementCntext != null && theElementCntext.hasBinding()) {
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, "Binding for " + path + " missing (cc)")) {
@ -969,6 +969,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// ignore this since we can't validate but it doesn't matter..
} else {
ValidationResult vr = context.validateCode(cc, valueset);
res = false;
if (!vr.isOk()) {
bindingsOk = false;
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) {
@ -1023,6 +1024,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
}
return res;
}
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, CodeableConcept cc) {
@ -1099,7 +1101,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
checkFixedValue(errors, path + ".userSelected", focus.getNamedChild("userSelected"), fixed.getUserSelectedElement(), "userSelected", focus);
}
private void checkCoding(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, boolean inCodeableConcept) {
private void checkCoding(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, ElementDefinition theElementCntext, boolean inCodeableConcept, boolean checkDisplay) {
String code = element.getNamedChildValue("code");
String system = element.getNamedChildValue("system");
String display = element.getNamedChildValue("display");
@ -1108,7 +1110,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (system != null && code != null && !noTerminologyChecks) {
rule(errors, IssueType.CODEINVALID, element.line(), element.col(), path, !isValueSet(system), "The Coding references a value set, not a code system (\""+system+"\")");
try {
if (checkCode(errors, element, path, code, system, display))
if (checkCode(errors, element, path, code, system, display, checkDisplay))
if (theElementCntext != null && theElementCntext.hasBinding()) {
ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
if (warning(errors, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, "Binding for " + path + " missing")) {
@ -1237,7 +1239,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), path + "[url='" + url + "']", allowedTypes.contains(actualType), "The Extension '" + url + "' definition allows for the types "+allowedTypes.toString()+" but found type "+actualType);
// 3. is the content of the extension valid?
validateElement(hostContext, errors, ex, ex.getSnapshot().getElement().get(0), null, null, resource, element, "Extension", stack, false);
validateElement(hostContext, errors, ex, ex.getSnapshot().getElement().get(0), null, null, resource, element, "Extension", stack, false, true);
}
return ex;
@ -2790,7 +2792,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
(rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), defn.hasSnapshot(),
"StructureDefinition has no snapshot - validation is against the snapshot, so it must be provided"))) {
// Don't need to validate against the resource if there's a profile because the profile snapshot will include the relevant parts of the resources
validateElement(hostContext, errors, defn, defn.getSnapshot().getElement().get(0), null, null, resource, element, element.getName(), stack, false);
validateElement(hostContext, errors, defn, defn.getSnapshot().getElement().get(0), null, null, resource, element, element.getName(), stack, false, true);
}
// specific known special validations
@ -2809,7 +2811,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// todo: re-enable this when I can deal with the impact... (GG)
// if (!profileUsage.getProfile().getType().equals(resource.fhirType()))
// throw new FHIRException("Profile type mismatch - resource is "+resource.fhirType()+", and profile is for "+profileUsage.getProfile().getType());
validateElement(hostContext, errors, profileUsage.getProfile(), profileUsage.getProfile().getSnapshot().getElement().get(0), null, null, resource, element, element.getName(), stack, false);
validateElement(hostContext, errors, profileUsage.getProfile(), profileUsage.getProfile().getSnapshot().getElement().get(0), null, null, resource, element, element.getName(), stack, false, true);
}
}
@ -3632,7 +3634,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
// firstBase = ebase == null ? base : ebase;
private void validateElement(ValidatorHostContext hostContext, List<ValidationMessage> errors, StructureDefinition profile, ElementDefinition definition, StructureDefinition cprofile, ElementDefinition context,
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept) throws FHIRException, FHIRException, IOException {
Element resource, Element element, String actualType, NodeStack stack, boolean inCodeableConcept, boolean checkDisplayInContext) throws FHIRException, FHIRException, IOException {
// element.markValidation(profile, definition);
// System.out.println(" "+stack.getLiteralPath()+" "+Long.toString((System.nanoTime() - time) / 1000000));
@ -3877,6 +3879,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
String eiPath = ei.path;
assert(eiPath.equals(localStackLiterapPath)) : "ei.path: " + ei.path + " - localStack.getLiteralPath: " + localStackLiterapPath;
boolean thisIsCodeableConcept = false;
boolean checkDisplay = true;
ei.element.markValidation(profile, ei.definition);
if (type != null) {
@ -3893,9 +3896,9 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
if (type.equals("Identifier")) {
checkIdentifier(errors, ei.path, ei.element, ei.definition);
} else if (type.equals("Coding")) {
checkCoding(errors, ei.path, ei.element, profile, ei.definition, inCodeableConcept);
checkCoding(errors, ei.path, ei.element, profile, ei.definition, inCodeableConcept, checkDisplayInContext);
} else if (type.equals("CodeableConcept")) {
checkCodeableConcept(errors, ei.path, ei.element, profile, ei.definition);
checkDisplay = checkCodeableConcept(errors, ei.path, ei.element, profile, ei.definition);
thisIsCodeableConcept = true;
} else if (type.equals("Reference")) {
checkReference(hostContext, errors, ei.path, ei.element, profile, ei.definition, actualType, localStack);
@ -3908,7 +3911,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
}
} else {
if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), stack.getLiteralPath(), ei.definition != null, "Unrecognised Content " + ei.name))
validateElement(hostContext, errors, profile, ei.definition, null, null, resource, ei.element, type, localStack, false);
validateElement(hostContext, errors, profile, ei.definition, null, null, resource, ei.element, type, localStack, false, true);
}
StructureDefinition p = null;
boolean elementValidated = false;
@ -3948,7 +3951,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
p = this.context.fetchResource(StructureDefinition.class, typeProfile);
if (rule(errors, IssueType.STRUCTURE, ei.line(), ei.col(), ei.path, p != null, "Unknown profile " + typeProfile)) {
List<ValidationMessage> profileErrors = new ArrayList<ValidationMessage>();
validateElement(hostContext, profileErrors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.element, type, localStack, thisIsCodeableConcept);
validateElement(hostContext, profileErrors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.element, type, localStack, thisIsCodeableConcept, checkDisplay);
boolean hasError = false;
for (ValidationMessage msg : profileErrors) {
if (msg.getLevel()==ValidationMessage.IssueSeverity.ERROR || msg.getLevel()==ValidationMessage.IssueSeverity.FATAL) {
@ -3978,13 +3981,13 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
}
if (p!=null) {
if (!elementValidated) {
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.element, type, localStack, thisIsCodeableConcept);
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.element, type, localStack, thisIsCodeableConcept, checkDisplay);
}
int index = profile.getSnapshot().getElement().indexOf(ei.definition);
if (index < profile.getSnapshot().getElement().size() - 1) {
String nextPath = profile.getSnapshot().getElement().get(index+1).getPath();
if (!nextPath.equals(ei.definition.getPath()) && nextPath.startsWith(ei.definition.getPath()))
validateElement(hostContext, errors, profile, ei.definition, null, null, resource, ei.element, type, localStack, thisIsCodeableConcept);
validateElement(hostContext, errors, profile, ei.definition, null, null, resource, ei.element, type, localStack, thisIsCodeableConcept, checkDisplay);
}
}
}

View File

@ -138,7 +138,7 @@
},
"patient-au-5.json" : {
"errorCount": 0,
"warningCount": 0,
"warningCount": 1,
"profile" : {
"source" : "profile-patient-au.xml",
"errorCount": 0
@ -563,7 +563,7 @@
},
"patient-translated-codes.xml" : {
"errorCount": 0,
"warningCount": 4,
"warningCount": 2,
"profile" : {
"source" : "patient-translated-codes.profile.xml",
"errorCount": 0,