Added expand filter impl for R5 and dstu3, changed the filter logic

This commit is contained in:
Frank Tao 2020-11-18 22:26:21 -05:00
parent f65fdb0d52
commit 878c22192e
8 changed files with 197 additions and 8 deletions

View File

@ -24,6 +24,7 @@ import java.io.CharArrayWriter;
import java.nio.charset.StandardCharsets;
import java.text.Normalizer;
import java.util.Arrays;
import java.util.StringTokenizer;
public class StringUtil {
@ -78,4 +79,24 @@ public class StringUtil {
return new String(bytes, StandardCharsets.UTF_8);
}
/**
* Check the input string has prefix token
*
* @param theInput the input string
* @param thePrefix the prefix string of a token
* @return Return true if a input string token separated by space start with the prefix
*/
public static boolean isStartsWithIgnoreCase(final String theInput, final String thePrefix) {
if (theInput == null || thePrefix == null)
return false;
StringTokenizer tok = new StringTokenizer(theInput);
while (tok.hasMoreTokens()) {
if (org.apache.commons.lang3.StringUtils.startsWithIgnoreCase(tok.nextToken(), thePrefix))
return true;
}
return false;
}
}

View File

@ -10,6 +10,8 @@ import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class StringUtilTest {
@Test
@ -51,4 +53,14 @@ public class StringUtilTest {
assertEquals("a/a", StringUtil.chompCharacter("a/a////", '/'));
}
@Test
public void testIsStartsWithIgnoreCase() {
assertFalse(StringUtil.isStartsWithIgnoreCase(null, null));
assertFalse(StringUtil.isStartsWithIgnoreCase(null, "hei"));
assertFalse(StringUtil.isStartsWithIgnoreCase("Body height", null));
assertTrue(StringUtil.isStartsWithIgnoreCase("Body height", "he"));
assertTrue(StringUtil.isStartsWithIgnoreCase("Body height", "bo"));
assertFalse(StringUtil.isStartsWithIgnoreCase("Body height", "ei"));
assertFalse(StringUtil.isStartsWithIgnoreCase("Body height", "dy"));
}
}

View File

@ -33,6 +33,8 @@ import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.StringUtil;
import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.IntegerType;
@ -224,7 +226,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
for (int idx = 0; idx < theContains.size(); idx++) {
ValueSetExpansionContainsComponent next = theContains.get(idx);
if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) {
if (isBlank(next.getDisplay()) || !StringUtil.isStartsWithIgnoreCase(next.getDisplay(), theFilter)) {
theContains.remove(idx);
idx--;
if (theTotalElement.getValue() != null) {
@ -238,7 +240,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
if (ElementUtil.isEmpty(include.getConcept())) {
if (isNotBlank(theFilter)) {
include.addFilter().setProperty("display").setOp(FilterOperator.EQUAL).setValue(theFilter);
include.addFilter().setProperty("display").setOp(FilterOperator.EXISTS).setValue(theFilter);
}
}
}

View File

@ -33,6 +33,8 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.StringUtil;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -208,7 +210,11 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
for (int idx = 0; idx < theContains.size(); idx++) {
ValueSetExpansionContainsComponent next = theContains.get(idx);
if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) {
// e.g. For a display text of Body height:
// searching on "Bo" or "he" should find it
// searching on "ei" or "dy" should not find it
if (isBlank(next.getDisplay()) || !StringUtil.isStartsWithIgnoreCase(next.getDisplay(), theFilter)) {
theContains.remove(idx);
idx--;
if (theTotalElement.getValue() != null) {
@ -218,7 +224,7 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
applyFilter(theTotalElement, next.getContains(), theFilter);
}
}
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
if (ElementUtil.isEmpty(include.getConcept())) {
if (isNotBlank(theFilter)) {

View File

@ -31,6 +31,8 @@ import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.StringUtil;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -208,7 +210,7 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
for (int idx = 0; idx < theContains.size(); idx++) {
ValueSetExpansionContainsComponent next = theContains.get(idx);
if (isBlank(next.getDisplay()) || !org.apache.commons.lang3.StringUtils.containsIgnoreCase(next.getDisplay(), theFilter)) {
if (isBlank(next.getDisplay()) || !StringUtil.isStartsWithIgnoreCase(next.getDisplay(), theFilter)) {
theContains.remove(idx);
idx--;
if (theTotalElement.getValue() != null) {
@ -222,7 +224,7 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
private void addFilterIfPresent(String theFilter, ConceptSetComponent include) {
if (ElementUtil.isEmpty(include.getConcept())) {
if (isNotBlank(theFilter)) {
include.addFilter().setProperty("display").setOp(Enumerations.FilterOperator.EQUAL).setValue(theFilter);
include.addFilter().setProperty("display").setOp(Enumerations.FilterOperator.EXISTS).setValue(theFilter);
}
}
}

View File

@ -50,6 +50,7 @@ import java.util.List;
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest.URL_MY_CODE_SYSTEM;
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoDstu3TerminologyTest.URL_MY_VALUE_SET;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.jupiter.api.Assertions.*;
@ -857,6 +858,68 @@ public class ResourceProviderDstu3ValueSetTest extends BaseResourceProviderDstu3
}
@Test
public void testExpandByValueSetWithFilterContainsPrefixValue() throws IOException {
loadAndPersistCodeSystem();
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringType("blo"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, stringContainsInOrder("<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>"));
}
@Test
public void testExpandByValueSetWithFilterContainsNoPrefixValue() throws IOException {
loadAndPersistCodeSystem();
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringType("lood"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
}
@Test
public void testExpandByValueSetWithFilterNotContainsAnyValue() throws IOException {
loadAndPersistCodeSystem();
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
Parameters respParam = ourClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringType("loood"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
}
@Test
public void testExpandByUrlWithFilter() throws Exception {
loadAndPersistCodeSystemAndValueSet();

View File

@ -1195,7 +1195,7 @@ public class ResourceProviderR4ValueSetNoVerCSNoVerTest extends BaseResourceProv
}
@Test
public void testExpandByValueSetWithFilterContainsPartialValue() throws IOException {
public void testExpandByValueSetWithFilterContainsPrefixValue() throws IOException {
loadAndPersistCodeSystem();
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
@ -1205,7 +1205,7 @@ public class ResourceProviderR4ValueSetNoVerCSNoVerTest extends BaseResourceProv
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringType("loo"))
.andParameter("filter", new StringType("blo"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
@ -1214,6 +1214,27 @@ public class ResourceProviderR4ValueSetNoVerCSNoVerTest extends BaseResourceProv
assertThat(resp, stringContainsInOrder("<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>"));
}
@Test
public void testExpandByValueSetWithFilterContainsNoPrefixValue() throws IOException {
loadAndPersistCodeSystem();
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
Parameters respParam = myClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringType("lood"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
}
@Test
public void testExpandByValueSetWithFilterNotContainsAnyValue() throws IOException {
loadAndPersistCodeSystem();

View File

@ -1440,6 +1440,68 @@ public class ResourceProviderR5ValueSetTest extends BaseResourceProviderR5Test {
}
@Test
public void testExpandByValueSetWithFilterContainsPrefixValue() throws IOException {
loadAndPersistCodeSystem(HTTPVerb.POST);
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
Parameters respParam = myClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringType("blo"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, stringContainsInOrder("<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>"));
}
@Test
public void testExpandByValueSetWithFilterContainsNoPrefixValue() throws IOException {
loadAndPersistCodeSystem(HTTPVerb.POST);
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
Parameters respParam = myClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringType("lood"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
}
@Test
public void testExpandByValueSetWithFilterNotContainsAnyValue() throws IOException {
loadAndPersistCodeSystem(HTTPVerb.POST);
ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-3-vs.xml");
Parameters respParam = myClient
.operation()
.onType(ValueSet.class)
.named("expand")
.withParameter(Parameters.class, "valueSet", toExpand)
.andParameter("filter", new StringType("loood"))
.execute();
ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource();
String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded);
ourLog.info(resp);
assertThat(resp, not(stringContainsInOrder("<code value=\"11378-7\"/>","<display value=\"Systolic blood pressure at First encounter\"/>")));
}
@Test
public void testExpandByUrlWithFilter() throws Exception {
loadAndPersistCodeSystemAndValueSet(HTTPVerb.POST);