Avoid error when unknown code system behaviour set to warning (#3436)
* Avoid error when unknown code system behaviour set to warning * Add changelog * Test fix * Build fix * Fixes * Address review comment
This commit is contained in:
parent
2cba62b4e8
commit
f614eaf6c8
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 3436
|
||||||
|
jira: SMILE-3563
|
||||||
|
title: "A regression in HAPI FHIR 5.7.0 meant that when UnknownCodeSystemWarningValidationSupport was
|
||||||
|
configured for WARNING behaviour, validating a field with an implicit code system could
|
||||||
|
incorrectly result in an error."
|
|
@ -75,16 +75,17 @@ public class JpaValidationSupportChain extends ValidationSupportChain {
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void postConstruct() {
|
public void postConstruct() {
|
||||||
addValidationSupport(myUnknownCodeSystemWarningValidationSupport);
|
|
||||||
addValidationSupport(myDefaultProfileValidationSupport);
|
addValidationSupport(myDefaultProfileValidationSupport);
|
||||||
addValidationSupport(myJpaValidationSupport);
|
addValidationSupport(myJpaValidationSupport);
|
||||||
//TODO MAKE SURE THAT THIS IS BEING CAL
|
|
||||||
addValidationSupport(myTerminologyService);
|
addValidationSupport(myTerminologyService);
|
||||||
addValidationSupport(new SnapshotGeneratingValidationSupport(myFhirContext));
|
addValidationSupport(new SnapshotGeneratingValidationSupport(myFhirContext));
|
||||||
addValidationSupport(new InMemoryTerminologyServerValidationSupport(myFhirContext));
|
addValidationSupport(new InMemoryTerminologyServerValidationSupport(myFhirContext));
|
||||||
addValidationSupport(myNpmJpaValidationSupport);
|
addValidationSupport(myNpmJpaValidationSupport);
|
||||||
addValidationSupport(new CommonCodeSystemsTerminologyService(myFhirContext));
|
addValidationSupport(new CommonCodeSystemsTerminologyService(myFhirContext));
|
||||||
addValidationSupport(myConceptMappingSvc);
|
addValidationSupport(myConceptMappingSvc);
|
||||||
|
|
||||||
|
// This needs to be last in the chain, it was designed for that
|
||||||
|
addValidationSupport(myUnknownCodeSystemWarningValidationSupport);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.AllergyIntolerance;
|
import org.hl7.fhir.r4.model.AllergyIntolerance;
|
||||||
|
import org.hl7.fhir.r4.model.Binary;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
|
||||||
import org.hl7.fhir.r4.model.CanonicalType;
|
import org.hl7.fhir.r4.model.CanonicalType;
|
||||||
|
@ -125,23 +126,11 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(UnknownCodeSystemWarningValidationSupport.DEFAULT_SEVERITY);
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(UnknownCodeSystemWarningValidationSupport.DEFAULT_SEVERITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* By default an unknown code system should fail vaildation
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeInValueSetWithUnknownCodeSystem_FailValidation() {
|
public void testValidateCodeInValueSetWithUnknownCodeSystem_FailValidation() {
|
||||||
createStructureDefWithBindingToUnknownCs();
|
createStructureDefWithBindingToUnknownCs(true);
|
||||||
|
|
||||||
Observation obs = new Observation();
|
Observation obs = createObservationForUnknownCodeSystemTest();
|
||||||
obs.getMeta().addProfile("http://sd");
|
|
||||||
obs.getText().setDivAsString("<div>Hello</div>");
|
|
||||||
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
|
||||||
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
|
||||||
obs.getCode().setText("hello");
|
|
||||||
obs.setSubject(new Reference("Patient/123"));
|
|
||||||
obs.addPerformer(new Reference("Practitioner/123"));
|
|
||||||
obs.setEffective(DateTimeType.now());
|
|
||||||
obs.setStatus(ObservationStatus.FINAL);
|
|
||||||
|
|
||||||
OperationOutcome oo;
|
OperationOutcome oo;
|
||||||
|
|
||||||
|
@ -163,6 +152,210 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeInEnumeratedValueSetWithUnknownCodeSystem_Information() {
|
||||||
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.INFORMATION);
|
||||||
|
|
||||||
|
createStructureDefWithBindingToUnknownCs(true);
|
||||||
|
|
||||||
|
Observation obs = createObservationForUnknownCodeSystemTest();
|
||||||
|
|
||||||
|
OperationOutcome oo;
|
||||||
|
String encoded;
|
||||||
|
|
||||||
|
// Valid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, false);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertEquals("No issues detected during validation", oo.getIssueFirstRep().getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.INFORMATION, oo.getIssueFirstRep().getSeverity());
|
||||||
|
|
||||||
|
// Invalid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, true);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertEquals("The code provided (http://cs#code99) is not in the value set http://vs, and a code from this value set is required: Unknown code 'http://cs#code99' for in-memory expansion of ValueSet 'http://vs'", oo.getIssueFirstRep().getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.ERROR, oo.getIssueFirstRep().getSeverity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, an unknown code system should fail validation
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeInEnumeratedValueSetWithUnknownCodeSystem_Warning() {
|
||||||
|
// set to warning
|
||||||
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.WARNING);
|
||||||
|
|
||||||
|
createStructureDefWithBindingToUnknownCs(true);
|
||||||
|
|
||||||
|
Observation obs = createObservationForUnknownCodeSystemTest();
|
||||||
|
|
||||||
|
OperationOutcome oo;
|
||||||
|
String encoded;
|
||||||
|
|
||||||
|
// Valid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, false);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertEquals("CodeSystem is unknown and can't be validated: http://cs for 'http://cs#code1'", oo.getIssueFirstRep().getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.WARNING, oo.getIssueFirstRep().getSeverity());
|
||||||
|
|
||||||
|
// Invalid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, true);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(2, oo.getIssue().size());
|
||||||
|
assertEquals("CodeSystem is unknown and can't be validated: http://cs for 'http://cs#code99'", oo.getIssue().get(0).getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.WARNING, oo.getIssue().get(0).getSeverity());
|
||||||
|
assertEquals("The code provided (http://cs#code99) is not in the value set http://vs, and a code from this value set is required: Unknown code 'http://cs#code99' for in-memory expansion of ValueSet 'http://vs'", oo.getIssue().get(1).getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.ERROR, oo.getIssue().get(1).getSeverity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeInEnumeratedValueSetWithUnknownCodeSystem_Error() {
|
||||||
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.ERROR);
|
||||||
|
|
||||||
|
createStructureDefWithBindingToUnknownCs(true);
|
||||||
|
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.getMeta().addProfile("http://sd");
|
||||||
|
obs.getText().setDivAsString("<div>Hello</div>");
|
||||||
|
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||||
|
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
||||||
|
obs.getCode().setText("hello");
|
||||||
|
obs.setSubject(new Reference("Patient/123"));
|
||||||
|
obs.addPerformer(new Reference("Practitioner/123"));
|
||||||
|
obs.setEffective(DateTimeType.now());
|
||||||
|
obs.setStatus(ObservationStatus.FINAL);
|
||||||
|
|
||||||
|
OperationOutcome oo;
|
||||||
|
String encoded;
|
||||||
|
|
||||||
|
// Valid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, false);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertTrue(oo.getIssueFirstRep().getDiagnostics().contains("No issues detected during validation"));
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.INFORMATION, oo.getIssueFirstRep().getSeverity());
|
||||||
|
|
||||||
|
// Invalid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, true);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertTrue(oo.getIssueFirstRep()
|
||||||
|
.getDiagnostics().contains("The code provided (http://cs#code99) is not in the value set http://vs, and a code from this value set is required: Unknown code 'http://cs#code99' for in-memory expansion of ValueSet 'http://vs'")
|
||||||
|
);
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.ERROR, oo.getIssueFirstRep().getSeverity());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeInNonEnumeratedValueSetWithUnknownCodeSystem_Information() {
|
||||||
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.INFORMATION);
|
||||||
|
|
||||||
|
createStructureDefWithBindingToUnknownCs(false);
|
||||||
|
|
||||||
|
Observation obs = createObservationForUnknownCodeSystemTest();
|
||||||
|
|
||||||
|
OperationOutcome oo;
|
||||||
|
String encoded;
|
||||||
|
|
||||||
|
// Valid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, false);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertEquals("No issues detected during validation", oo.getIssueFirstRep().getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.INFORMATION, oo.getIssueFirstRep().getSeverity());
|
||||||
|
|
||||||
|
// Invalid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, false);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertEquals("No issues detected during validation", oo.getIssueFirstRep().getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.INFORMATION, oo.getIssueFirstRep().getSeverity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, an unknown code system should fail validation
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeInNonEnumeratedValueSetWithUnknownCodeSystem_Warning() {
|
||||||
|
// set to warning
|
||||||
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.WARNING);
|
||||||
|
|
||||||
|
createStructureDefWithBindingToUnknownCs(false);
|
||||||
|
|
||||||
|
Observation obs = createObservationForUnknownCodeSystemTest();
|
||||||
|
|
||||||
|
OperationOutcome oo;
|
||||||
|
String encoded;
|
||||||
|
|
||||||
|
// Valid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, false);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertEquals("CodeSystem is unknown and can't be validated: http://cs for 'http://cs#code1'", oo.getIssueFirstRep().getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.WARNING, oo.getIssueFirstRep().getSeverity());
|
||||||
|
|
||||||
|
// Invalid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, false);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertEquals("CodeSystem is unknown and can't be validated: http://cs for 'http://cs#code99'", oo.getIssue().get(0).getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.WARNING, oo.getIssue().get(0).getSeverity());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateCodeInNonEnumeratedValueSetWithUnknownCodeSystem_Error() {
|
||||||
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.ERROR);
|
||||||
|
|
||||||
|
createStructureDefWithBindingToUnknownCs(false);
|
||||||
|
|
||||||
|
Observation obs = new Observation();
|
||||||
|
obs.getMeta().addProfile("http://sd");
|
||||||
|
obs.getText().setDivAsString("<div>Hello</div>");
|
||||||
|
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||||
|
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
||||||
|
obs.getCode().setText("hello");
|
||||||
|
obs.setSubject(new Reference("Patient/123"));
|
||||||
|
obs.addPerformer(new Reference("Practitioner/123"));
|
||||||
|
obs.setEffective(DateTimeType.now());
|
||||||
|
obs.setStatus(ObservationStatus.FINAL);
|
||||||
|
|
||||||
|
OperationOutcome oo;
|
||||||
|
String encoded;
|
||||||
|
|
||||||
|
// Valid code
|
||||||
|
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
||||||
|
oo = validateAndReturnOutcome(obs, true);
|
||||||
|
encoded = encode(oo);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
assertEquals(1, oo.getIssue().size());
|
||||||
|
assertEquals("The code provided (http://cs#code1) is not in the value set http://vs, and a code from this value set is required: Failed to expand ValueSet 'http://vs' (in-memory). Could not validate code http://cs#code1. Error was: HAPI-0702: Unable to expand ValueSet because CodeSystem could not be found: http://cs", oo.getIssueFirstRep().getDiagnostics());
|
||||||
|
assertEquals(OperationOutcome.IssueSeverity.ERROR, oo.getIssueFirstRep().getSeverity());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Observation createObservationForUnknownCodeSystemTest() {
|
private Observation createObservationForUnknownCodeSystemTest() {
|
||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.getMeta().addProfile("http://sd");
|
obs.getMeta().addProfile("http://sd");
|
||||||
|
@ -177,85 +370,60 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
return obs;
|
return obs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* By default, an unknown code system should fail validation
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeInValueSetWithUnknownCodeSystem_Warning() {
|
public void testValidateCodeInValueSet_InferredCodeSystem_WarningOnUnknown() {
|
||||||
// set to warning
|
// set to warning
|
||||||
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.WARNING);
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.WARNING);
|
||||||
|
|
||||||
createStructureDefWithBindingToUnknownCs();
|
|
||||||
|
|
||||||
Observation obs = createObservationForUnknownCodeSystemTest();
|
|
||||||
|
|
||||||
OperationOutcome oo;
|
OperationOutcome oo;
|
||||||
String encoded;
|
String encoded;
|
||||||
|
|
||||||
|
Binary binary = new Binary();
|
||||||
|
binary.setContentType("application/text");
|
||||||
|
binary.setContent("hello".getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
// Valid code
|
// Valid code
|
||||||
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
oo = validateAndReturnOutcome(binary);
|
||||||
oo = validateAndReturnOutcome(obs);
|
|
||||||
encoded = encode(oo);
|
encoded = encode(oo);
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
assertTrue(oo.getIssueFirstRep().getDiagnostics().contains("No issues detected during validation"));
|
assertTrue(oo.getIssueFirstRep().getDiagnostics().contains("No issues detected during validation"));
|
||||||
|
|
||||||
// Invalid code
|
|
||||||
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
|
||||||
oo = validateAndReturnOutcome(obs);
|
|
||||||
encoded = encode(oo);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
assertTrue(oo.getIssueFirstRep().getDiagnostics().contains("No issues detected during validation"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateCodeInValueSetWithUnknownCodeSystem_Error() {
|
public void testValidateCodeInValueSet_InferredCodeSystem_ErrorOnUnknown() {
|
||||||
|
// set to warning
|
||||||
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.ERROR);
|
myUnknownCodeSystemWarningValidationSupport.setNonExistentCodeSystemSeverity(IValidationSupport.IssueSeverity.ERROR);
|
||||||
|
|
||||||
createStructureDefWithBindingToUnknownCs();
|
|
||||||
|
|
||||||
Observation obs = new Observation();
|
|
||||||
obs.getMeta().addProfile("http://sd");
|
|
||||||
obs.getText().setDivAsString("<div>Hello</div>");
|
|
||||||
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
|
||||||
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
|
||||||
obs.getCode().setText("hello");
|
|
||||||
obs.setSubject(new Reference("Patient/123"));
|
|
||||||
obs.addPerformer(new Reference("Practitioner/123"));
|
|
||||||
obs.setEffective(DateTimeType.now());
|
|
||||||
obs.setStatus(ObservationStatus.FINAL);
|
|
||||||
|
|
||||||
OperationOutcome oo;
|
OperationOutcome oo;
|
||||||
String encoded;
|
String encoded;
|
||||||
|
|
||||||
|
Binary binary = new Binary();
|
||||||
|
binary.setContentType("application/text");
|
||||||
|
binary.setContent("hello".getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
// Valid code
|
// Valid code
|
||||||
obs.setValue(new Quantity().setSystem("http://cs").setCode("code1").setValue(123));
|
oo = validateAndReturnOutcome(binary);
|
||||||
oo = validateAndReturnOutcome(obs);
|
|
||||||
encoded = encode(oo);
|
encoded = encode(oo);
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
assertTrue(oo.getIssueFirstRep().getDiagnostics().contains("No issues detected during validation"));
|
assertTrue(oo.getIssueFirstRep().getDiagnostics().contains("No issues detected during validation"));
|
||||||
|
|
||||||
|
|
||||||
// Invalid code
|
|
||||||
obs.setValue(new Quantity().setSystem("http://cs").setCode("code99").setValue(123));
|
|
||||||
oo = validateAndReturnOutcome(obs);
|
|
||||||
encoded = encode(oo);
|
|
||||||
ourLog.info(encoded);
|
|
||||||
assertTrue(oo.getIssueFirstRep()
|
|
||||||
.getDiagnostics().contains("The code provided (http://cs#code99) is not in the value set http://vs, and a code from this value set is required: Unknown code 'http://cs#code99' for in-memory expansion of ValueSet 'http://vs'")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createStructureDefWithBindingToUnknownCs() {
|
|
||||||
|
public void createStructureDefWithBindingToUnknownCs(boolean theEnumeratedCodeSystem) {
|
||||||
myValidationSupport.fetchCodeSystem("http://not-exist"); // preload DefaultProfileValidationSupport
|
myValidationSupport.fetchCodeSystem("http://not-exist"); // preload DefaultProfileValidationSupport
|
||||||
|
|
||||||
ValueSet vs = new ValueSet();
|
ValueSet vs = new ValueSet();
|
||||||
vs.setUrl("http://vs");
|
vs.setUrl("http://vs");
|
||||||
vs
|
ValueSet.ConceptSetComponent include = vs
|
||||||
.getCompose()
|
.getCompose()
|
||||||
.addInclude()
|
.addInclude()
|
||||||
.setSystem("http://cs")
|
.setSystem("http://cs");
|
||||||
.addConcept(new ValueSet.ConceptReferenceComponent(new CodeType("code1")))
|
if (theEnumeratedCodeSystem) {
|
||||||
.addConcept(new ValueSet.ConceptReferenceComponent(new CodeType("code2")));
|
include.addConcept(new ValueSet.ConceptReferenceComponent(new CodeType("code1")));
|
||||||
|
include.addConcept(new ValueSet.ConceptReferenceComponent(new CodeType("code2")));
|
||||||
|
}
|
||||||
myValueSetDao.create(vs);
|
myValueSetDao.create(vs);
|
||||||
|
|
||||||
StructureDefinition sd = new StructureDefinition();
|
StructureDefinition sd = new StructureDefinition();
|
||||||
|
@ -1105,6 +1273,17 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T extends IBaseResource> OperationOutcome validateAndReturnOutcome(T theObs, Boolean theWantError) {
|
||||||
|
IFhirResourceDao<T> dao = (IFhirResourceDao<T>) myDaoRegistry.getResourceDao(theObs.getClass());
|
||||||
|
try {
|
||||||
|
MethodOutcome outcome = dao.validate(theObs, null, null, null, ValidationModeEnum.CREATE, null, mySrd);
|
||||||
|
assertTrue(theWantError == null || !theWantError, "Wanted an error response but got a non-error");
|
||||||
|
return (OperationOutcome) outcome.getOperationOutcome();
|
||||||
|
} catch (PreconditionFailedException e) {
|
||||||
|
assertTrue(theWantError == null || theWantError, "Wanted a non-error response but got an error");
|
||||||
|
return (OperationOutcome) e.getOperationOutcome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateStructureDefinition() throws Exception {
|
public void testValidateStructureDefinition() throws Exception {
|
||||||
|
@ -1140,6 +1319,9 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||||
ourLog.info("Starting validation");
|
ourLog.info("Starting validation");
|
||||||
try {
|
try {
|
||||||
MethodOutcome outcome = myBundleDao.validate(document, null, null, null, ValidationModeEnum.CREATE, null, mySrd);
|
MethodOutcome outcome = myBundleDao.validate(document, null, null, null, ValidationModeEnum.CREATE, null, mySrd);
|
||||||
|
String encodedResponse = myFhirContext.newJsonParser().encodeResourceToString(outcome.getOperationOutcome());
|
||||||
|
ourLog.info("Validation result: {}", encodedResponse);
|
||||||
|
fail();
|
||||||
} catch (PreconditionFailedException e) {
|
} catch (PreconditionFailedException e) {
|
||||||
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,24 +77,6 @@ public class HttpProxyTest {
|
||||||
int port = JettyUtil.getPortForStartedServer(server);
|
int port = JettyUtil.getPortForStartedServer(server);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// final String authUser = "username";
|
|
||||||
// final String authPassword = "password";
|
|
||||||
// CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
|
||||||
// credsProvider.setCredentials(new AuthScope("127.0.0.1", port), new UsernamePasswordCredentials(authUser, authPassword));
|
|
||||||
//
|
|
||||||
// HttpHost myProxy = new HttpHost("127.0.0.1", port);
|
|
||||||
//
|
|
||||||
// //@formatter:off
|
|
||||||
// HttpClientBuilder clientBuilder = HttpClientBuilder.create();
|
|
||||||
// clientBuilder
|
|
||||||
// .setProxy(myProxy)
|
|
||||||
// .setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy())
|
|
||||||
// .setDefaultCredentialsProvider(credsProvider)
|
|
||||||
// .disableCookieManagement();
|
|
||||||
// CloseableHttpClient httpClient = clientBuilder.build();
|
|
||||||
// //@formatter:on
|
|
||||||
// ourCtx.getRestfulClientFactory().setHttpClient(httpClient);
|
|
||||||
|
|
||||||
ourCtx.getRestfulClientFactory().setProxy("127.0.0.1", port);
|
ourCtx.getRestfulClientFactory().setProxy("127.0.0.1", port);
|
||||||
ourCtx.getRestfulClientFactory().setProxyCredentials("username", "password");
|
ourCtx.getRestfulClientFactory().setProxyCredentials("username", "password");
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,9 @@ import java.net.URL;
|
||||||
|
|
||||||
public class HtmlUtil {
|
public class HtmlUtil {
|
||||||
|
|
||||||
|
private HtmlUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
public static HtmlPage parseAsHtml(String theRespString, URL theUrl) throws IOException {
|
public static HtmlPage parseAsHtml(String theRespString, URL theUrl) throws IOException {
|
||||||
StringWebResponse response = new StringWebResponse(theRespString, theUrl);
|
StringWebResponse response = new StringWebResponse(theRespString, theUrl);
|
||||||
WebClient client = new WebClient(BrowserVersion.BEST_SUPPORTED, false, null, -1);
|
WebClient client = new WebClient(BrowserVersion.BEST_SUPPORTED, false, null, -1);
|
||||||
|
@ -42,7 +45,7 @@ public class HtmlUtil {
|
||||||
|
|
||||||
final HtmlPage page = new HtmlPage(response, client.getCurrentWindow());
|
final HtmlPage page = new HtmlPage(response, client.getCurrentWindow());
|
||||||
HtmlUnitNekoHtmlParser htmlUnitNekoHtmlParser = new HtmlUnitNekoHtmlParser();
|
HtmlUnitNekoHtmlParser htmlUnitNekoHtmlParser = new HtmlUnitNekoHtmlParser();
|
||||||
htmlUnitNekoHtmlParser.parse(response, page, false);
|
htmlUnitNekoHtmlParser.parse(response, page, false, false);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.hl7.fhir.common.hapi.validation.support;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -42,28 +43,35 @@ public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSup
|
||||||
return canValidateCodeSystem(theValidationSupportContext, theSystem);
|
return canValidateCodeSystem(theValidationSupportContext, theSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public LookupCodeResult lookupCode(ValidationSupportContext theValidationSupportContext, String theSystem, String theCode, String theDisplayLanguage) {
|
||||||
|
// filters out error/fatal
|
||||||
|
if (canValidateCodeSystem(theValidationSupportContext, theSystem)) {
|
||||||
|
return new LookupCodeResult()
|
||||||
|
.setFound(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CodeValidationResult validateCode(@Nonnull ValidationSupportContext theValidationSupportContext, @Nonnull ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, String theValueSetUrl) {
|
public CodeValidationResult validateCode(@Nonnull ValidationSupportContext theValidationSupportContext, @Nonnull ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, String theValueSetUrl) {
|
||||||
// filters out error/fatal
|
// filters out error/fatal
|
||||||
// NB: this is a secondary check. isCodeSystemSupported
|
|
||||||
// should prevent this from ever calling validate code here
|
|
||||||
// ... but should it ever get called, we'll return null
|
|
||||||
if (!canValidateCodeSystem(theValidationSupportContext, theCodeSystem)) {
|
if (!canValidateCodeSystem(theValidationSupportContext, theCodeSystem)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeValidationResult result = new CodeValidationResult()
|
CodeValidationResult result = new CodeValidationResult();
|
||||||
.setSeverity(myNonExistentCodeSystemSeverity); // will be warning or info (error/fatal filtered out above)
|
// will be warning or info (error/fatal filtered out above)
|
||||||
|
result.setSeverity(myNonExistentCodeSystemSeverity);
|
||||||
|
result.setMessage("CodeSystem is unknown and can't be validated: " + theCodeSystem);
|
||||||
|
|
||||||
result.setMessage("No issues detected during validation");
|
if (myNonExistentCodeSystemSeverity == IssueSeverity.INFORMATION) {
|
||||||
|
// for warnings, we don't set the code
|
||||||
switch (myNonExistentCodeSystemSeverity) {
|
// cause if we do, the severity is stripped out
|
||||||
case INFORMATION:
|
// (see VersionSpecificWorkerContextWrapper.convertValidationResult)
|
||||||
// for warnings, we don't set the code
|
result.setCode(theCode);
|
||||||
// cause if we do, the severity is stripped out
|
|
||||||
// (see VersionSpecificWorkerContextWrapper.convertValidationResult)
|
|
||||||
result.setCode(theCode);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -126,8 +134,6 @@ public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSup
|
||||||
/**
|
/**
|
||||||
* If set to allow, code system violations will be flagged with Warning by default.
|
* If set to allow, code system violations will be flagged with Warning by default.
|
||||||
* Use setNonExistentCodeSystemSeverity instead.
|
* Use setNonExistentCodeSystemSeverity instead.
|
||||||
*
|
|
||||||
* @param theAllowNonExistentCodeSystem
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setAllowNonExistentCodeSystem(boolean theAllowNonExistentCodeSystem) {
|
public void setAllowNonExistentCodeSystem(boolean theAllowNonExistentCodeSystem) {
|
||||||
|
@ -140,9 +146,9 @@ public class UnknownCodeSystemWarningValidationSupport extends BaseValidationSup
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the non-existent code system severity.
|
* Sets the non-existent code system severity.
|
||||||
* @param theSeverity
|
|
||||||
*/
|
*/
|
||||||
public void setNonExistentCodeSystemSeverity(IssueSeverity theSeverity) {
|
public void setNonExistentCodeSystemSeverity(@Nonnull IssueSeverity theSeverity) {
|
||||||
|
Validate.notNull(theSeverity, "theSeverity must not be null");
|
||||||
myNonExistentCodeSystemSeverity = theSeverity;
|
myNonExistentCodeSystemSeverity = theSeverity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -1197,7 +1197,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sourceforge.htmlunit</groupId>
|
<groupId>net.sourceforge.htmlunit</groupId>
|
||||||
<artifactId>htmlunit</artifactId>
|
<artifactId>htmlunit</artifactId>
|
||||||
<version>2.56.0</version>
|
<version>2.58.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.sf.json-lib</groupId>
|
<groupId>net.sf.json-lib</groupId>
|
||||||
|
|
Loading…
Reference in New Issue