diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_0_0/3515-supporting-canonical-system-uri-during-valueset-expansion.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_0_0/3515-supporting-canonical-system-uri-during-valueset-expansion.yaml
new file mode 100644
index 00000000000..41a6575b391
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_0_0/3515-supporting-canonical-system-uri-during-valueset-expansion.yaml
@@ -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."
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java
index 3a1d6817baf..e56eda7b765 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupport.java
@@ -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 true
if at least one code was addded
+ * Returns true
if at least one code was added
*/
private boolean expandValueSetR5IncludeOrExclude(ValidationSupportContext theValidationSupportContext, Consumer 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 codeSystemLoader = newCodeSystemLoader(theValidationSupportContext);
Function valueSetLoader = newValueSetLoader(theValidationSupportContext);
List 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 {
diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupportTest.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupportTest.java
index bd904241639..2953280fbf0 100644
--- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupportTest.java
+++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupportTest.java
@@ -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 myDstu2ValueSets;
PrePopulatedValidationSupportDstu2(FhirContext theFhirContext) {