Skip to content

Commit

Permalink
4853 validation does not error when display is not the same as the di…
Browse files Browse the repository at this point in the history
…splay defined in the codesystem 2 (#4854)

* added failing test

* implemented the solution

* changed test name

* added change log

* Update hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/4853-validation-does-not-error-when-display-is-not-the-same-as-the-display-defined-in-the-codesystem-2.yaml

Co-authored-by: James Agnew <[email protected]>

---------

Co-authored-by: Steven Li <[email protected]>
Co-authored-by: James Agnew <[email protected]>
  • Loading branch information
3 people committed May 11, 2023
1 parent 9d9df27 commit 22c9a18
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
type: fix
issue: 4853
title: "Previously, when validating resources that contain a display in a Coding/CodeableConcept different from the
display defined in the CodeSystem that is used, no errors are returned in the outcome. This is now fixed."
Original file line number Diff line number Diff line change
Expand Up @@ -2200,6 +2200,7 @@ public CodeValidationResult validateCodeInValueSet(ValidationSupportContext theV
public IValidationSupport.CodeValidationResult validateCode(@Nonnull ValidationSupportContext theValidationSupportContext, @Nonnull ConceptValidationOptions theOptions, String theCodeSystemUrl, String theCode, String theDisplay, String theValueSetUrl) {
//TODO GGG TRY TO JUST AUTO_PASS HERE AND SEE WHAT HAPPENS.
invokeRunnableForUnitTest();
theOptions.setValidateDisplay(isNotBlank(theDisplay));

if (isNotBlank(theValueSetUrl)) {
return validateCodeInValueSet(theValidationSupportContext, theOptions, theValueSetUrl, theCodeSystemUrl, theCode, theDisplay);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,14 +678,14 @@ public void testValidateCode_InMemoryExpansionAgainstHugeValueSet() throws Excep
obs.getCode().getCoding().clear();
obs.getCategory().clear();
obs.getCategoryFirstRep().addCoding().setSystem("http:https://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("CODE4").setDisplay("Display 3");
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("CODE4").setDisplay("Display 4");
oo = validateAndReturnOutcome(obs);
assertEquals("No issues detected during validation", oo.getIssueFirstRep().getDiagnostics(), encode(oo));
myCaptureQueriesListener.logSelectQueriesForCurrentThread();

myCaptureQueriesListener.clear();
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("CODE4").setDisplay("Display 3");
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("CODE4").setDisplay("Display 4");
oo = validateAndReturnOutcome(obs);
assertEquals("No issues detected during validation", oo.getIssueFirstRep().getDiagnostics(), encode(oo));
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
Expand Down Expand Up @@ -737,7 +737,7 @@ public void testValidateProfileTargetType_PolicyCheckValid() throws IOException
obs.setStatus(ObservationStatus.FINAL);
obs.setValue(new StringType("This is the value"));
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("123-4").setDisplay("Display 3");
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("123-4").setDisplay("Code 123 4");

OperationOutcome oo;

Expand Down Expand Up @@ -807,7 +807,7 @@ public void testValidateProfileTargetType_PolicyCheckExistsAndType() throws IOEx
obs.setStatus(ObservationStatus.FINAL);
obs.setValue(new StringType("This is the value"));
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("123-4").setDisplay("Display 3");
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("123-4").setDisplay("Code 123 4");

OperationOutcome oo;

Expand Down Expand Up @@ -878,7 +878,7 @@ public void testValidateProfileTargetType_PolicyCheckExists() throws IOException
obs.setStatus(ObservationStatus.FINAL);
obs.setValue(new StringType("This is the value"));
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("123-4").setDisplay("Display 3");
obs.getCode().getCodingFirstRep().setSystem("http:https://loinc.org").setCode("123-4").setDisplay("Code 123 4");

// Non-existent target
obs.setSubject(new Reference("Group/123"));
Expand Down Expand Up @@ -1381,6 +1381,43 @@ public void testValidateUsingExternallyDefinedCode() {

}

@Test
public void testValidateUsingExternallyDefinedCodeMisMatchDisplay_ShouldError() {
CodeSystem codeSystem = new CodeSystem();
codeSystem.setUrl("http:https://foo");
codeSystem.setContent(CodeSystem.CodeSystemContentMode.NOTPRESENT);
IIdType csId = myCodeSystemDao.create(codeSystem).getId();

TermCodeSystemVersion csv = new TermCodeSystemVersion();
csv.addConcept().setCode("bar").setDisplay("Bar Code");
myTermCodeSystemStorageSvc.storeNewCodeSystemVersion(codeSystem, csv, mySrd, Collections.emptyList(), Collections.emptyList());

// Validate a resource containing this codesystem in a field with an extendable binding
Patient patient = new Patient();
patient.getText().setStatus(Narrative.NarrativeStatus.GENERATED).setDivAsString("<div>hello</div>");
patient
.addIdentifier()
.setSystem("http:https://example.com")
.setValue("12345")
.getType()
.addCoding()
.setSystem("http:https://foo")
.setCode("bar")
.setDisplay("not bar code");
MethodOutcome outcome = myPatientDao.validate(patient, null, encode(patient), EncodingEnum.JSON, ValidationModeEnum.CREATE, null, mySrd);
OperationOutcome oo = (OperationOutcome) outcome.getOperationOutcome();
ourLog.debug(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(oo));

// It would be ok for this to produce 0 issues, or just an information message too
assertEquals(2, OperationOutcomeUtil.getIssueCount(myFhirContext, oo));
assertThat(OperationOutcomeUtil.getFirstIssueDetails(myFhirContext, oo),
containsString("None of the codings provided are in the value set 'IdentifierType'"));
assertThat(OperationOutcomeUtil.getFirstIssueDetails(myFhirContext, oo),
containsString("a coding should come from this value set unless it has no suitable code (note that the validator cannot judge what is suitable) (codes = http:https://foo#bar)"));
assertEquals(OperationOutcome.IssueSeverity.ERROR, oo.getIssue().get(1).getSeverity());
assertThat(oo.getIssue().get(1).getDiagnostics(), containsString("Unable to validate code http:https://foo#bar - Concept Display "));
}

private OperationOutcome doTestValidateResourceContainingProfileDeclaration(String methodName, EncodingEnum enc) throws IOException {
Bundle vss = loadResourceFromClasspath(Bundle.class, "/org/hl7/fhir/r4/model/valueset/valuesets.xml");
myValueSetDao.update((ValueSet) findResourceByIdInBundle(vss, "observation-status"), mySrd);
Expand Down

0 comments on commit 22c9a18

Please sign in to comment.