Fixing ValueSet expansion not supporting canonical url. (#3501)
* 2991 - WIP, starting to implement test to reproduce the issue. * Adding capability to extract url & version from the valueSet.include.url * parsing codeSystem canonical URL to extra version if required. * WIP * Cleaning up the test. * Replacing hard code value with variable. * Removing non required test. * Modifications following first code review. * Further modifications following first code review. * Refining the test for better code coverage. * Prefixing the change log file name with the hapi-fhir issue number. Co-authored-by: Etienne Poirier <etienne.poirier@smilecdr.com>
This commit is contained in:
parent
9e0c364fb4
commit
26784ba7c8
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 3515
|
||||
jira: SMILE-2991
|
||||
title: "Supporting expansion of ValueSet include/exclude system URI expressed in canonical format during validation."
|
|
@ -1,12 +1,12 @@
|
|||
package org.hl7.fhir.common.hapi.validation.support;
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.util.FhirVersionIndependentConcept;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
@ -36,9 +36,12 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.contains;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.substringAfter;
|
||||
import static org.apache.commons.lang3.StringUtils.substringBefore;
|
||||
|
||||
/**
|
||||
* This class is a basic in-memory terminology service, designed to expand ValueSets and validate codes
|
||||
|
@ -47,6 +50,8 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||
* external term service API)
|
||||
*/
|
||||
public class InMemoryTerminologyServerValidationSupport implements IValidationSupport {
|
||||
private static final String OUR_PIPE_CHARACTER = "|";
|
||||
|
||||
private final FhirContext myCtx;
|
||||
|
||||
public InMemoryTerminologyServerValidationSupport(FhirContext theCtx) {
|
||||
|
@ -539,13 +544,15 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if at least one code was addded
|
||||
* Returns <code>true</code> if at least one code was added
|
||||
*/
|
||||
private boolean expandValueSetR5IncludeOrExclude(ValidationSupportContext theValidationSupportContext, Consumer<FhirVersionIndependentConcept> theConsumer, @Nullable String theWantSystemUrlAndVersion, @Nullable String theWantCode, org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent theInclude) throws ExpansionCouldNotBeCompletedInternallyException {
|
||||
|
||||
String wantSystemUrl = null;
|
||||
String wantSystemVersion = null;
|
||||
|
||||
if (theWantSystemUrlAndVersion != null) {
|
||||
int versionIndex = theWantSystemUrlAndVersion.indexOf("|");
|
||||
int versionIndex = theWantSystemUrlAndVersion.indexOf(OUR_PIPE_CHARACTER);
|
||||
if (versionIndex > -1) {
|
||||
wantSystemUrl = theWantSystemUrlAndVersion.substring(0, versionIndex);
|
||||
wantSystemVersion = theWantSystemUrlAndVersion.substring(versionIndex + 1);
|
||||
|
@ -554,15 +561,20 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
|||
}
|
||||
}
|
||||
|
||||
String includeOrExcludeConceptSystemUrl = theInclude.getSystem();
|
||||
String includeOrExcludeConceptSystemVersion = theInclude.getVersion();
|
||||
|
||||
Function<String, CodeSystem> codeSystemLoader = newCodeSystemLoader(theValidationSupportContext);
|
||||
Function<String, org.hl7.fhir.r5.model.ValueSet> valueSetLoader = newValueSetLoader(theValidationSupportContext);
|
||||
|
||||
List<FhirVersionIndependentConcept> nextCodeList = new ArrayList<>();
|
||||
String includeOrExcludeConceptSystemUrl = theInclude.getSystem();
|
||||
String includeOrExcludeConceptSystemVersion = theInclude.getVersion();
|
||||
CodeSystem includeOrExcludeSystemResource = null;
|
||||
|
||||
if (isNotBlank(includeOrExcludeConceptSystemUrl)) {
|
||||
|
||||
includeOrExcludeConceptSystemVersion = optionallyPopulateVersionFromUrl(includeOrExcludeConceptSystemUrl, includeOrExcludeConceptSystemVersion);
|
||||
includeOrExcludeConceptSystemUrl = substringBefore(includeOrExcludeConceptSystemUrl, OUR_PIPE_CHARACTER);
|
||||
|
||||
if (wantSystemUrl != null && !wantSystemUrl.equals(includeOrExcludeConceptSystemUrl)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -573,7 +585,7 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
|||
|
||||
String loadedCodeSystemUrl;
|
||||
if (includeOrExcludeConceptSystemVersion != null) {
|
||||
loadedCodeSystemUrl = includeOrExcludeConceptSystemUrl + "|" + includeOrExcludeConceptSystemVersion;
|
||||
loadedCodeSystemUrl = includeOrExcludeConceptSystemUrl + OUR_PIPE_CHARACTER + includeOrExcludeConceptSystemVersion;
|
||||
} else {
|
||||
loadedCodeSystemUrl = includeOrExcludeConceptSystemUrl;
|
||||
}
|
||||
|
@ -810,6 +822,12 @@ public class InMemoryTerminologyServerValidationSupport implements IValidationSu
|
|||
}
|
||||
}
|
||||
|
||||
private String optionallyPopulateVersionFromUrl(String theSystemUrl, String theVersion) {
|
||||
if(contains(theSystemUrl, OUR_PIPE_CHARACTER) && isBlank(theVersion)){
|
||||
theVersion = substringAfter(theSystemUrl, OUR_PIPE_CHARACTER);
|
||||
}
|
||||
return theVersion;
|
||||
}
|
||||
|
||||
public enum FailureType {
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ import org.hl7.fhir.r4.model.Enumerations;
|
|||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -423,8 +425,42 @@ public class InMemoryTerminologyServerValidationSupportTest {
|
|||
assertEquals("MODERNA COVID-19 mRNA-1273", valueSet.getExpansion().getContains().get(0).getDisplay());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"http://terminology.hl7.org/CodeSystem/v2-0360|2.7","http://terminology.hl7.org/CodeSystem/v2-0360"})
|
||||
void testValidateCodeInValueSet_VsExpandedWithIncludes(String theCodeSystemUri) {
|
||||
ConceptValidationOptions options = new ConceptValidationOptions();
|
||||
ValidationSupportContext valCtx = new ValidationSupportContext(myChain);
|
||||
String codeMD = "MD";
|
||||
|
||||
private static class PrePopulatedValidationSupportDstu2 extends PrePopulatedValidationSupport {
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||
cs.setUrl(theCodeSystemUri);
|
||||
cs.addConcept()
|
||||
.setCode(codeMD)
|
||||
.setDisplay("Doctor of Medicine");
|
||||
myPrePopulated.addCodeSystem(cs);
|
||||
|
||||
ValueSet theValueSet = new ValueSet();
|
||||
theValueSet.setUrl("http://someValueSetURL");
|
||||
theValueSet.setVersion("0360");
|
||||
theValueSet.getCompose().addInclude().setSystem(theCodeSystemUri);
|
||||
|
||||
String theCodeToValidateCodeSystemUrl = theCodeSystemUri;
|
||||
String theCodeToValidate = codeMD;
|
||||
|
||||
IValidationSupport.CodeValidationResult codeValidationResult = mySvc.validateCodeInValueSet(
|
||||
valCtx,
|
||||
options,
|
||||
theCodeToValidateCodeSystemUrl,
|
||||
theCodeToValidate,
|
||||
null,
|
||||
theValueSet);
|
||||
|
||||
assertTrue(codeValidationResult.isOk());
|
||||
}
|
||||
|
||||
private static class PrePopulatedValidationSupportDstu2 extends PrePopulatedValidationSupport {
|
||||
private final Map<String, IBaseResource> myDstu2ValueSets;
|
||||
|
||||
PrePopulatedValidationSupportDstu2(FhirContext theFhirContext) {
|
||||
|
|
Loading…
Reference in New Issue