Correctly handle below expansion with missing system
This commit is contained in:
parent
f02d80365e
commit
ebc52e6b48
|
@ -109,6 +109,8 @@ ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor.failedToExtractPa
|
||||||
ca.uhn.fhir.jpa.dao.SearchBuilder.invalidQuantityPrefix=Unable to handle quantity prefix "{0}" for value: {1}
|
ca.uhn.fhir.jpa.dao.SearchBuilder.invalidQuantityPrefix=Unable to handle quantity prefix "{0}" for value: {1}
|
||||||
ca.uhn.fhir.jpa.dao.SearchBuilder.invalidNumberPrefix=Unable to handle number prefix "{0}" for value: {1}
|
ca.uhn.fhir.jpa.dao.SearchBuilder.invalidNumberPrefix=Unable to handle number prefix "{0}" for value: {1}
|
||||||
ca.uhn.fhir.jpa.dao.SearchBuilder.sourceParamDisabled=The _source parameter is disabled on this server
|
ca.uhn.fhir.jpa.dao.SearchBuilder.sourceParamDisabled=The _source parameter is disabled on this server
|
||||||
|
ca.uhn.fhir.jpa.dao.SearchBuilder.invalidCodeMissingSystem=Invalid token specified for parameter {0} - No system specified: {1}|{2}
|
||||||
|
ca.uhn.fhir.jpa.dao.SearchBuilder.invalidCodeMissingCode=Invalid token specified for parameter {0} - No code specified: {1}|{2}
|
||||||
|
|
||||||
ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoConceptMapDstu3.matchesFound=Matches found!
|
ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoConceptMapDstu3.matchesFound=Matches found!
|
||||||
ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoConceptMapDstu3.noMatchesFound=No matches found!
|
ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoConceptMapDstu3.noMatchesFound=No matches found!
|
||||||
|
|
|
@ -1857,9 +1857,11 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
codes.addAll(myTerminologySvc.expandValueSet(code));
|
codes.addAll(myTerminologySvc.expandValueSet(code));
|
||||||
} else if (modifier == TokenParamModifier.ABOVE) {
|
} else if (modifier == TokenParamModifier.ABOVE) {
|
||||||
system = determineSystemIfMissing(theParamName, code, system);
|
system = determineSystemIfMissing(theParamName, code, system);
|
||||||
|
validateHaveSystemAndCodeForToken(theParamName, code, system);
|
||||||
codes.addAll(myTerminologySvc.findCodesAbove(system, code));
|
codes.addAll(myTerminologySvc.findCodesAbove(system, code));
|
||||||
} else if (modifier == TokenParamModifier.BELOW) {
|
} else if (modifier == TokenParamModifier.BELOW) {
|
||||||
system = determineSystemIfMissing(theParamName, code, system);
|
system = determineSystemIfMissing(theParamName, code, system);
|
||||||
|
validateHaveSystemAndCodeForToken(theParamName, code, system);
|
||||||
codes.addAll(myTerminologySvc.findCodesBelow(system, code));
|
codes.addAll(myTerminologySvc.findCodesBelow(system, code));
|
||||||
} else {
|
} else {
|
||||||
codes.add(new VersionIndependentConcept(system, code));
|
codes.add(new VersionIndependentConcept(system, code));
|
||||||
|
@ -1902,6 +1904,19 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateHaveSystemAndCodeForToken(String theParamName, String theCode, String theSystem) {
|
||||||
|
String systemDesc = defaultIfBlank(theSystem, "(missing)");
|
||||||
|
String codeDesc = defaultIfBlank(theCode, "(missing)");
|
||||||
|
if (isBlank(theCode)) {
|
||||||
|
String msg = myContext.getLocalizer().getMessage(SearchBuilder.class, "invalidCodeMissingSystem", theParamName, systemDesc, codeDesc);
|
||||||
|
throw new InvalidRequestException(msg);
|
||||||
|
}
|
||||||
|
if (isBlank(theSystem)) {
|
||||||
|
String msg = myContext.getLocalizer().getMessage(SearchBuilder.class, "invalidCodeMissingCode", theParamName, systemDesc, codeDesc);
|
||||||
|
throw new InvalidRequestException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Predicate addPredicateToken(String theResourceName, String theParamName, CriteriaBuilder theBuilder, From<?, ResourceIndexedSearchParamToken> theFrom, List<VersionIndependentConcept> theTokens, TokenParamModifier theModifier, TokenModeEnum theTokenMode) {
|
private Predicate addPredicateToken(String theResourceName, String theParamName, CriteriaBuilder theBuilder, From<?, ResourceIndexedSearchParamToken> theFrom, List<VersionIndependentConcept> theTokens, TokenParamModifier theModifier, TokenModeEnum theTokenMode) {
|
||||||
if (myDontUseHashesForSearch) {
|
if (myDontUseHashesForSearch) {
|
||||||
final Path<String> systemExpression = theFrom.get("mySystem");
|
final Path<String> systemExpression = theFrom.get("mySystem");
|
||||||
|
|
|
@ -2,10 +2,15 @@ package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
import ca.uhn.fhir.jpa.model.entity.*;
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
|
||||||
|
@ -34,7 +39,11 @@ import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
|
||||||
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
|
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
|
||||||
import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType;
|
import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType;
|
||||||
import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus;
|
import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus;
|
||||||
import org.junit.*;
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.support.TransactionCallback;
|
import org.springframework.transaction.support.TransactionCallback;
|
||||||
|
@ -45,11 +54,29 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.junit.Assert.*;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
import static org.hamcrest.Matchers.hasItems;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "Duplicates"})
|
@SuppressWarnings({"unchecked", "Duplicates"})
|
||||||
|
@ -1978,6 +2005,52 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchOnCodesWithBelow() {
|
||||||
|
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
|
||||||
|
|
||||||
|
CodeSystem cs = new CodeSystem();
|
||||||
|
cs.setUrl("http://foo");
|
||||||
|
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||||
|
cs.addConcept().setCode("111-1")
|
||||||
|
.addConcept().setCode("111-2");
|
||||||
|
cs.addConcept().setCode("222-1")
|
||||||
|
.addConcept().setCode("222-2");
|
||||||
|
myCodeSystemDao.create(cs);
|
||||||
|
|
||||||
|
Observation obs1 = new Observation();
|
||||||
|
obs1.getCode().addCoding().setSystem("http://foo").setCode("111-1");
|
||||||
|
String id1 = myObservationDao.create(obs1).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
|
Observation obs2 = new Observation();
|
||||||
|
obs2.getCode().addCoding().setSystem("http://foo").setCode("111-2");
|
||||||
|
String id2 = myObservationDao.create(obs2).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
|
|
||||||
|
IBundleProvider result;
|
||||||
|
|
||||||
|
result = myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_CODE, new TokenParam("http://foo", "111-1")));
|
||||||
|
assertThat(toUnqualifiedVersionlessIds(result).toString(), toUnqualifiedVersionlessIdValues(result), containsInAnyOrder(id1));
|
||||||
|
|
||||||
|
result = myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_CODE, new TokenParam("http://foo", "111-1").setModifier(TokenParamModifier.BELOW)));
|
||||||
|
assertThat(toUnqualifiedVersionlessIds(result).toString(), toUnqualifiedVersionlessIdValues(result), containsInAnyOrder(id1, id2));
|
||||||
|
|
||||||
|
try {
|
||||||
|
myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_CODE, new TokenParam(null, "111-1").setModifier(TokenParamModifier.BELOW)));
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("Invalid token specified for parameter code - No code specified: (missing)|111-1", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_CODE, new TokenParam("111-1", null).setModifier(TokenParamModifier.BELOW)));
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertEquals("Invalid token specified for parameter code - No system specified: 111-1|(missing)", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchParamChangesType() {
|
public void testSearchParamChangesType() {
|
||||||
String name = "testSearchParamChangesType";
|
String name = "testSearchParamChangesType";
|
||||||
|
|
Loading…
Reference in New Issue