compiles. now to run the tests...
This commit is contained in:
parent
49743352a6
commit
ab74e66870
|
@ -26,7 +26,6 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
|||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceSearchViewDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||
|
@ -38,10 +37,8 @@ import ca.uhn.fhir.jpa.model.entity.*;
|
|||
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.jpa.util.*;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
@ -130,12 +127,9 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
private List<ResourcePersistentId> myAlsoIncludePids;
|
||||
private CriteriaBuilder myBuilder;
|
||||
private BaseHapiFhirDao<?> myCallingDao;
|
||||
private IndexJoins myIndexJoins = new IndexJoins();
|
||||
private SearchParameterMap myParams;
|
||||
private ArrayList<Predicate> myPredicates;
|
||||
private String myResourceName;
|
||||
private AbstractQuery<Long> myResourceTableQuery;
|
||||
private Root<ResourceTable> myResourceTableRoot;
|
||||
private Class<? extends IBaseResource> myResourceType;
|
||||
private String mySearchUuid;
|
||||
private int myFetchSize;
|
||||
|
@ -143,6 +137,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
private Set<ResourcePersistentId> myPidSet;
|
||||
private boolean myHaveIndexJoins = false;
|
||||
private PredicateBuilder myPredicateBuilder;
|
||||
private final QueryRoot myQueryRoot = new QueryRoot();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -227,8 +222,6 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
}
|
||||
|
||||
private TypedQuery<Long> createQuery(SortSpec sort, Integer theMaximumResults, boolean theCount, RequestDetails theRequest) {
|
||||
myPredicates = new ArrayList<>();
|
||||
|
||||
CriteriaQuery<Long> outerQuery;
|
||||
/*
|
||||
* Sort
|
||||
|
@ -241,17 +234,16 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
outerQuery = myBuilder.createQuery(Long.class);
|
||||
myResourceTableQuery = outerQuery;
|
||||
myResourceTableRoot = myResourceTableQuery.from(ResourceTable.class);
|
||||
myQueryRoot.push(myResourceTableQuery.from(ResourceTable.class));
|
||||
if (theCount) {
|
||||
outerQuery.multiselect(myBuilder.countDistinct(myResourceTableRoot));
|
||||
outerQuery.multiselect(myBuilder.countDistinct(myQueryRoot.getRoot()));
|
||||
} else {
|
||||
outerQuery.multiselect(myResourceTableRoot.get("myId").as(Long.class));
|
||||
outerQuery.multiselect(myQueryRoot.get("myId").as(Long.class));
|
||||
}
|
||||
|
||||
List<Order> orders = Lists.newArrayList();
|
||||
List<Predicate> predicates = myPredicates; // Lists.newArrayList();
|
||||
|
||||
createSort(myBuilder, myResourceTableRoot, sort, orders, predicates);
|
||||
createSort(myBuilder, myQueryRoot, sort, orders);
|
||||
if (orders.size() > 0) {
|
||||
outerQuery.orderBy(orders);
|
||||
}
|
||||
|
@ -260,18 +252,18 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
outerQuery = myBuilder.createQuery(Long.class);
|
||||
myResourceTableQuery = outerQuery;
|
||||
myResourceTableRoot = myResourceTableQuery.from(ResourceTable.class);
|
||||
myQueryRoot.push(myResourceTableQuery.from(ResourceTable.class));
|
||||
if (theCount) {
|
||||
outerQuery.multiselect(myBuilder.countDistinct(myResourceTableRoot));
|
||||
outerQuery.multiselect(myBuilder.countDistinct(myQueryRoot.getRoot()));
|
||||
} else {
|
||||
outerQuery.multiselect(myResourceTableRoot.get("myId").as(Long.class));
|
||||
outerQuery.multiselect(myQueryRoot.get("myId").as(Long.class));
|
||||
outerQuery.distinct(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (myParams.getEverythingMode() != null) {
|
||||
Join<ResourceTable, ResourceLink> join = myResourceTableRoot.join("myResourceLinks", JoinType.LEFT);
|
||||
Join<ResourceTable, ResourceLink> join = myQueryRoot.join("myResourceLinks", JoinType.LEFT);
|
||||
|
||||
if (myParams.get(IAnyResource.SP_RES_ID) != null) {
|
||||
StringParam idParm = (StringParam) myParams.get(IAnyResource.SP_RES_ID).get(0).get(0);
|
||||
|
@ -280,11 +272,11 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
myAlsoIncludePids = new ArrayList<>(1);
|
||||
}
|
||||
myAlsoIncludePids.add(pid);
|
||||
myPredicates.add(myBuilder.equal(join.get("myTargetResourcePid").as(Long.class), pid.getIdAsLong()));
|
||||
myQueryRoot.addPredicate(myBuilder.equal(join.get("myTargetResourcePid").as(Long.class), pid.getIdAsLong()));
|
||||
} else {
|
||||
Predicate targetTypePredicate = myBuilder.equal(join.get("myTargetResourceType").as(String.class), myResourceName);
|
||||
Predicate sourceTypePredicate = myBuilder.equal(myResourceTableRoot.get("myResourceType").as(String.class), myResourceName);
|
||||
myPredicates.add(myBuilder.or(sourceTypePredicate, targetTypePredicate));
|
||||
Predicate sourceTypePredicate = myBuilder.equal(myQueryRoot.get("myResourceType").as(String.class), myResourceName);
|
||||
myQueryRoot.addPredicate(myBuilder.or(sourceTypePredicate, targetTypePredicate));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -315,7 +307,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
pids = Collections.singletonList(new ResourcePersistentId(-1L));
|
||||
}
|
||||
|
||||
myPredicates.add(myResourceTableRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(pids)));
|
||||
myQueryRoot.addPredicate(myQueryRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(pids)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -327,17 +319,17 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
*/
|
||||
if (!myHaveIndexJoins) {
|
||||
if (myParams.getEverythingMode() == null) {
|
||||
myPredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), myResourceName));
|
||||
myQueryRoot.addPredicate(myBuilder.equal(myQueryRoot.get("myResourceType"), myResourceName));
|
||||
}
|
||||
myPredicates.add(myBuilder.isNull(myResourceTableRoot.get("myDeleted")));
|
||||
myQueryRoot.addPredicate(myBuilder.isNull(myQueryRoot.get("myDeleted")));
|
||||
}
|
||||
|
||||
// Last updated
|
||||
DateRangeParam lu = myParams.getLastUpdated();
|
||||
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(lu, myBuilder, myResourceTableRoot);
|
||||
myPredicates.addAll(lastUpdatedPredicates);
|
||||
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(lu, myBuilder, myQueryRoot.getRoot());
|
||||
myQueryRoot.addPredicates(lastUpdatedPredicates);
|
||||
|
||||
myResourceTableQuery.where(myBuilder.and(SearchBuilder.toArray(myPredicates)));
|
||||
myResourceTableQuery.where(myBuilder.and(myQueryRoot.getPredicateArray()));
|
||||
|
||||
/*
|
||||
* Now perform the search
|
||||
|
@ -355,32 +347,32 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
* @return Returns {@literal true} if any search parameter sorts were found, or false if
|
||||
* no sorts were found, or only non-search parameters ones (e.g. _id, _lastUpdated)
|
||||
*/
|
||||
private boolean createSort(CriteriaBuilder theBuilder, Root<ResourceTable> theFrom, SortSpec theSort, List<Order> theOrders, List<Predicate> thePredicates) {
|
||||
private boolean createSort(CriteriaBuilder theBuilder, QueryRoot theQueryRoot, SortSpec theSort, List<Order> theOrders) {
|
||||
if (theSort == null || isBlank(theSort.getParamName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IAnyResource.SP_RES_ID.equals(theSort.getParamName())) {
|
||||
From<?, ?> forcedIdJoin = theFrom.join("myForcedId", JoinType.LEFT);
|
||||
From<?, ?> forcedIdJoin = theQueryRoot.join("myForcedId", JoinType.LEFT);
|
||||
if (theSort.getOrder() == null || theSort.getOrder() == SortOrderEnum.ASC) {
|
||||
theOrders.add(theBuilder.asc(forcedIdJoin.get("myForcedId")));
|
||||
theOrders.add(theBuilder.asc(theFrom.get("myId")));
|
||||
theOrders.add(theBuilder.asc(theQueryRoot.get("myId")));
|
||||
} else {
|
||||
theOrders.add(theBuilder.desc(forcedIdJoin.get("myForcedId")));
|
||||
theOrders.add(theBuilder.desc(theFrom.get("myId")));
|
||||
theOrders.add(theBuilder.desc(theQueryRoot.get("myId")));
|
||||
}
|
||||
|
||||
return createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
|
||||
return createSort(theBuilder, theQueryRoot, theSort.getChain(), theOrders);
|
||||
}
|
||||
|
||||
if (Constants.PARAM_LASTUPDATED.equals(theSort.getParamName())) {
|
||||
if (theSort.getOrder() == null || theSort.getOrder() == SortOrderEnum.ASC) {
|
||||
theOrders.add(theBuilder.asc(theFrom.get("myUpdated")));
|
||||
theOrders.add(theBuilder.asc(theQueryRoot.get("myUpdated")));
|
||||
} else {
|
||||
theOrders.add(theBuilder.desc(theFrom.get("myUpdated")));
|
||||
theOrders.add(theBuilder.desc(theQueryRoot.get("myUpdated")));
|
||||
}
|
||||
|
||||
return createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
|
||||
return createSort(theBuilder, theQueryRoot, theSort.getChain(), theOrders);
|
||||
}
|
||||
|
||||
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceName);
|
||||
|
@ -441,20 +433,20 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
* sorting on, we'll also sort with it. Otherwise we need a new join.
|
||||
*/
|
||||
SearchBuilderJoinKey key = new SearchBuilderJoinKey(theSort.getParamName(), joinType);
|
||||
Join<?, ?> join = myIndexJoins.get(key);
|
||||
Join<?, ?> join = theQueryRoot.getIndexJoin(key);
|
||||
if (join == null) {
|
||||
join = theFrom.join(joinAttrName, JoinType.LEFT);
|
||||
join = theQueryRoot.join(joinAttrName, JoinType.LEFT);
|
||||
|
||||
if (param.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
||||
thePredicates.add(join.get("mySourcePath").as(String.class).in(param.getPathsSplit()));
|
||||
theQueryRoot.addPredicate(join.get("mySourcePath").as(String.class).in(param.getPathsSplit()));
|
||||
} else {
|
||||
if (myDontUseHashesForSearch) {
|
||||
Predicate joinParam1 = theBuilder.equal(join.get("myParamName"), theSort.getParamName());
|
||||
thePredicates.add(joinParam1);
|
||||
theQueryRoot.addPredicate(joinParam1);
|
||||
} else {
|
||||
Long hashIdentity = BaseResourceIndexedSearchParam.calculateHashIdentity(myResourceName, theSort.getParamName());
|
||||
Predicate joinParam1 = theBuilder.equal(join.get("myHashIdentity"), hashIdentity);
|
||||
thePredicates.add(joinParam1);
|
||||
theQueryRoot.addPredicate(joinParam1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -469,7 +461,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
|
||||
createSort(theBuilder, theQueryRoot, theSort.getChain(), theOrders);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -863,9 +855,9 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
private void addPredicateCompositeStringUnique(@Nonnull SearchParameterMap theParams, String theIndexdString) {
|
||||
myHaveIndexJoins = true;
|
||||
|
||||
Join<ResourceTable, ResourceIndexedCompositeStringUnique> join = myResourceTableRoot.join("myParamsCompositeStringUnique", JoinType.LEFT);
|
||||
Join<ResourceTable, ResourceIndexedCompositeStringUnique> join = myQueryRoot.join("myParamsCompositeStringUnique", JoinType.LEFT);
|
||||
Predicate predicate = myBuilder.equal(join.get("myIndexString"), theIndexdString);
|
||||
myPredicates.add(predicate);
|
||||
myQueryRoot.addPredicate(predicate);
|
||||
|
||||
// Remove any empty parameters remaining after this
|
||||
theParams.clean();
|
||||
|
@ -901,16 +893,8 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
return myBuilder;
|
||||
}
|
||||
|
||||
public Root<ResourceTable> getResourceTableRoot() {
|
||||
return myResourceTableRoot;
|
||||
}
|
||||
|
||||
public IndexJoins getIndexJoins() {
|
||||
return myIndexJoins;
|
||||
}
|
||||
|
||||
public ArrayList<Predicate> getPredicates() {
|
||||
return myPredicates;
|
||||
public QueryRoot getQueryRoot() {
|
||||
return myQueryRoot;
|
||||
}
|
||||
|
||||
public AbstractQuery<Long> getResourceTableQuery() {
|
||||
|
@ -1220,13 +1204,13 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(theLastUpdated, builder, from);
|
||||
lastUpdatedPredicates.add(from.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(thePids)));
|
||||
|
||||
cq.where(SearchBuilder.toArray(lastUpdatedPredicates));
|
||||
cq.where(SearchBuilder.toPredicateArray(lastUpdatedPredicates));
|
||||
TypedQuery<Long> query = theEntityManager.createQuery(cq);
|
||||
|
||||
return ResourcePersistentId.fromLongList(query.getResultList());
|
||||
}
|
||||
|
||||
private static Predicate[] toArray(List<Predicate> thePredicates) {
|
||||
private static Predicate[] toPredicateArray(List<Predicate> thePredicates) {
|
||||
return thePredicates.toArray(new Predicate[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,7 @@ abstract class BasePredicateBuilder {
|
|||
boolean myDontUseHashesForSearch;
|
||||
final BaseHapiFhirDao<?> myCallingDao;
|
||||
final CriteriaBuilder myBuilder;
|
||||
final Root<ResourceTable> myResourceTableRoot;
|
||||
final IndexJoins myIndexJoins;
|
||||
final ArrayList<Predicate> myPredicates;
|
||||
final QueryRoot myQueryRoot;
|
||||
final Class<? extends IBaseResource> myResourceType;
|
||||
final String myResourceName;
|
||||
final AbstractQuery<Long> myResourceTableQuery;
|
||||
|
@ -46,9 +44,7 @@ abstract class BasePredicateBuilder {
|
|||
BasePredicateBuilder(SearchBuilder theSearchBuilder) {
|
||||
myCallingDao = theSearchBuilder.getCallingDao();
|
||||
myBuilder = theSearchBuilder.getBuilder();
|
||||
myResourceTableRoot = theSearchBuilder.getResourceTableRoot();
|
||||
myIndexJoins = theSearchBuilder.getIndexJoins();
|
||||
myPredicates = theSearchBuilder.getPredicates();
|
||||
myQueryRoot = theSearchBuilder.getQueryRoot();
|
||||
myResourceType = theSearchBuilder.getResourceType();
|
||||
myResourceName = theSearchBuilder.getResourceName();
|
||||
myResourceTableQuery = theSearchBuilder.getResourceTableQuery();
|
||||
|
@ -65,59 +61,59 @@ abstract class BasePredicateBuilder {
|
|||
Join<ResourceTable, ResourceIndexedSearchParamDate> join = null;
|
||||
switch (theType) {
|
||||
case DATE:
|
||||
join = myResourceTableRoot.join("myParamsDate", JoinType.LEFT);
|
||||
join = myQueryRoot.join("myParamsDate", JoinType.LEFT);
|
||||
break;
|
||||
case NUMBER:
|
||||
join = myResourceTableRoot.join("myParamsNumber", JoinType.LEFT);
|
||||
join = myQueryRoot.join("myParamsNumber", JoinType.LEFT);
|
||||
break;
|
||||
case QUANTITY:
|
||||
join = myResourceTableRoot.join("myParamsQuantity", JoinType.LEFT);
|
||||
join = myQueryRoot.join("myParamsQuantity", JoinType.LEFT);
|
||||
break;
|
||||
case REFERENCE:
|
||||
join = myResourceTableRoot.join("myResourceLinks", JoinType.LEFT);
|
||||
join = myQueryRoot.join("myResourceLinks", JoinType.LEFT);
|
||||
break;
|
||||
case STRING:
|
||||
join = myResourceTableRoot.join("myParamsString", JoinType.LEFT);
|
||||
join = myQueryRoot.join("myParamsString", JoinType.LEFT);
|
||||
break;
|
||||
case URI:
|
||||
join = myResourceTableRoot.join("myParamsUri", JoinType.LEFT);
|
||||
join = myQueryRoot.join("myParamsUri", JoinType.LEFT);
|
||||
break;
|
||||
case TOKEN:
|
||||
join = myResourceTableRoot.join("myParamsToken", JoinType.LEFT);
|
||||
join = myQueryRoot.join("myParamsToken", JoinType.LEFT);
|
||||
break;
|
||||
case COORDS:
|
||||
join = myResourceTableRoot.join("myParamsCoords", JoinType.LEFT);
|
||||
join = myQueryRoot.join("myParamsCoords", JoinType.LEFT);
|
||||
break;
|
||||
}
|
||||
|
||||
SearchBuilderJoinKey key = new SearchBuilderJoinKey(theSearchParameterName, theType);
|
||||
myIndexJoins.put(key, join);
|
||||
myQueryRoot.putIndex(key, join);
|
||||
|
||||
return (Join<ResourceTable, T>) join;
|
||||
}
|
||||
|
||||
void addPredicateParamMissing(String theResourceName, String theParamName, boolean theMissing) {
|
||||
// if (myDontUseHashesForSearch) {
|
||||
// Join<ResourceTable, SearchParamPresent> paramPresentJoin = myResourceTableRoot.join("mySearchParamPresents", JoinType.LEFT);
|
||||
// Join<ResourceTable, SearchParamPresent> paramPresentJoin = myQueryRoot.join("mySearchParamPresents", JoinType.LEFT);
|
||||
// Join<Object, Object> paramJoin = paramPresentJoin.join("mySearchParam", JoinType.LEFT);
|
||||
//
|
||||
// myPredicates.add(myBuilder.equal(paramJoin.get("myResourceName"), theResourceName));
|
||||
// myPredicates.add(myBuilder.equal(paramJoin.get("myParamName"), theParamName));
|
||||
// myPredicates.add(myBuilder.equal(paramPresentJoin.get("myPresent"), !theMissing));
|
||||
// myQueryRoot.addPredicate(myBuilder.equal(paramJoin.get("myResourceName"), theResourceName));
|
||||
// myQueryRoot.addPredicate(myBuilder.equal(paramJoin.get("myParamName"), theParamName));
|
||||
// myQueryRoot.addPredicate(myBuilder.equal(paramPresentJoin.get("myPresent"), !theMissing));
|
||||
// }
|
||||
|
||||
Join<ResourceTable, SearchParamPresent> paramPresentJoin = myResourceTableRoot.join("mySearchParamPresents", JoinType.LEFT);
|
||||
Join<ResourceTable, SearchParamPresent> paramPresentJoin = myQueryRoot.join("mySearchParamPresents", JoinType.LEFT);
|
||||
|
||||
Expression<Long> hashPresence = paramPresentJoin.get("myHashPresence").as(Long.class);
|
||||
Long hash = SearchParamPresent.calculateHashPresence(theResourceName, theParamName, !theMissing);
|
||||
myPredicates.add(myBuilder.equal(hashPresence, hash));
|
||||
myQueryRoot.addPredicate(myBuilder.equal(hashPresence, hash));
|
||||
}
|
||||
|
||||
void addPredicateParamMissing(String theResourceName, String theParamName, boolean theMissing, Join<ResourceTable, ? extends BaseResourceIndexedSearchParam> theJoin) {
|
||||
|
||||
myPredicates.add(myBuilder.equal(theJoin.get("myResourceType"), theResourceName));
|
||||
myPredicates.add(myBuilder.equal(theJoin.get("myParamName"), theParamName));
|
||||
myPredicates.add(myBuilder.equal(theJoin.get("myMissing"), theMissing));
|
||||
myQueryRoot.addPredicate(myBuilder.equal(theJoin.get("myResourceType"), theResourceName));
|
||||
myQueryRoot.addPredicate(myBuilder.equal(theJoin.get("myParamName"), theParamName));
|
||||
myQueryRoot.addPredicate(myBuilder.equal(theJoin.get("myMissing"), theMissing));
|
||||
}
|
||||
|
||||
Predicate combineParamIndexPredicateWithParamNamePredicate(String theResourceName, String theParamName, From<?, ? extends BaseResourceIndexedSearchParam> theFrom, Predicate thePredicate) {
|
||||
|
@ -133,7 +129,6 @@ abstract class BasePredicateBuilder {
|
|||
return myBuilder.and(hashIdentityPredicate, thePredicate);
|
||||
}
|
||||
|
||||
|
||||
Predicate createPredicateNumeric(String theResourceName,
|
||||
String theParamName,
|
||||
From<?, ? extends BaseResourceIndexedSearchParam> theFrom,
|
||||
|
@ -166,7 +161,7 @@ abstract class BasePredicateBuilder {
|
|||
num = builder.notEqual(thePath, theValue);
|
||||
break;
|
||||
case APPROXIMATE:
|
||||
BigDecimal mul = calculateFuzzAmount(thePrefix, theValue);
|
||||
BigDecimal mul = FuzzCalculator.calculateFuzzAmount(thePrefix, theValue);
|
||||
BigDecimal low = theValue.subtract(mul, MathContext.DECIMAL64);
|
||||
BigDecimal high = theValue.add(mul, MathContext.DECIMAL64);
|
||||
Predicate lowPred;
|
||||
|
@ -189,28 +184,6 @@ abstract class BasePredicateBuilder {
|
|||
return combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, theFrom, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Figures out the tolerance for a search. For example, if the user is searching for <code>4.00</code>, this method
|
||||
* returns <code>0.005</code> because we shold actually match values which are
|
||||
* <code>4 (+/-) 0.005</code> according to the FHIR specs.
|
||||
*/
|
||||
static BigDecimal calculateFuzzAmount(ParamPrefixEnum cmpValue, BigDecimal theValue) {
|
||||
if (cmpValue == ParamPrefixEnum.APPROXIMATE) {
|
||||
return theValue.multiply(new BigDecimal(0.1));
|
||||
} else {
|
||||
String plainString = theValue.toPlainString();
|
||||
int dotIdx = plainString.indexOf('.');
|
||||
if (dotIdx == -1) {
|
||||
return new BigDecimal(0.5);
|
||||
}
|
||||
|
||||
int precision = plainString.length() - (dotIdx);
|
||||
double mul = Math.pow(10, -precision);
|
||||
double val = mul * 5.0d;
|
||||
return new BigDecimal(val);
|
||||
}
|
||||
}
|
||||
|
||||
static String createLeftAndRightMatchLikeExpression(String likeExpression) {
|
||||
return "%" + likeExpression.replace("%", "[%]") + "%";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package ca.uhn.fhir.jpa.dao.predicate;
|
||||
|
||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public interface FuzzCalculator {
|
||||
/**
|
||||
* Figures out the tolerance for a search. For example, if the user is searching for <code>4.00</code>, this method
|
||||
* returns <code>0.005</code> because we shold actually match values which are
|
||||
* <code>4 (+/-) 0.005</code> according to the FHIR specs.
|
||||
*/
|
||||
static BigDecimal calculateFuzzAmount(ParamPrefixEnum cmpValue, BigDecimal theValue) {
|
||||
if (cmpValue == ParamPrefixEnum.APPROXIMATE) {
|
||||
return theValue.multiply(new BigDecimal(0.1));
|
||||
} else {
|
||||
String plainString = theValue.toPlainString();
|
||||
int dotIdx = plainString.indexOf('.');
|
||||
if (dotIdx == -1) {
|
||||
return new BigDecimal(0.5);
|
||||
}
|
||||
|
||||
int precision = plainString.length() - (dotIdx);
|
||||
double mul = Math.pow(10, -precision);
|
||||
double val = mul * 5.0d;
|
||||
return new BigDecimal(val);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -129,7 +129,7 @@ public class PredicateBuilderCoords extends BasePredicateBuilder {
|
|||
}
|
||||
|
||||
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
||||
myPredicates.add(retVal);
|
||||
myQueryRoot.addPredicate(retVal);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,12 +52,10 @@ public class PredicateBuilderDate extends BasePredicateBuilder {
|
|||
}
|
||||
|
||||
Predicate orPredicates = myBuilder.or(toArray(codePredicates));
|
||||
myPredicates.add(orPredicates);
|
||||
myQueryRoot.addPredicate(orPredicates);
|
||||
return orPredicates;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Predicate createPredicateDate(IQueryParameterType theParam,
|
||||
String theResourceName,
|
||||
String theParamName,
|
||||
|
|
|
@ -78,7 +78,7 @@ public class PredicateBuilderNumber extends BasePredicateBuilder {
|
|||
}
|
||||
|
||||
Predicate predicate = myBuilder.or(toArray(codePredicates));
|
||||
myPredicates.add(predicate);
|
||||
myQueryRoot.addPredicate(predicate);
|
||||
return predicate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public class PredicateBuilderQuantity extends BasePredicateBuilder {
|
|||
}
|
||||
|
||||
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
||||
myPredicates.add(retVal);
|
||||
myQueryRoot.addPredicate(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,13 +161,13 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
|
||||
if (codePredicates.size() > 0) {
|
||||
Predicate predicate = myBuilder.or(toArray(codePredicates));
|
||||
myPredicates.add(predicate);
|
||||
myQueryRoot.addPredicate(predicate);
|
||||
return predicate;
|
||||
} else {
|
||||
// Add a predicate that will never match
|
||||
Predicate pidPredicate = join.get("myTargetResourcePid").in(-1L);
|
||||
myPredicates.clear();
|
||||
myPredicates.add(pidPredicate);
|
||||
myQueryRoot.clearPredicates();
|
||||
myQueryRoot.addPredicate(pidPredicate);
|
||||
return pidPredicate;
|
||||
}
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
}
|
||||
|
||||
Predicate predicate = myBuilder.or(toArray(theCodePredicates));
|
||||
myPredicates.add(predicate);
|
||||
myQueryRoot.addPredicate(predicate);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
|
@ -372,29 +372,22 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
* stack and run a subquery
|
||||
*/
|
||||
|
||||
Root<ResourceTable> stackRoot = myResourceTableRoot;
|
||||
ArrayList<Predicate> stackPredicates = myPredicates;
|
||||
IndexJoins stackIndexJoins = myIndexJoins;
|
||||
|
||||
myResourceTableRoot = subQfrom;
|
||||
myPredicates = Lists.newArrayList();
|
||||
myIndexJoins = new IndexJoins();
|
||||
myQueryRoot.push(subQfrom);
|
||||
// FIXME KHS stack in all predicates
|
||||
|
||||
// Create the subquery predicates
|
||||
myPredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), theSubResourceName));
|
||||
myPredicates.add(myBuilder.isNull(myResourceTableRoot.get("myDeleted")));
|
||||
myQueryRoot.addPredicate(myBuilder.equal(myQueryRoot.get("myResourceType"), theSubResourceName));
|
||||
myQueryRoot.addPredicate(myBuilder.isNull(myQueryRoot.get("myDeleted")));
|
||||
|
||||
if (theFoundChainMatch) {
|
||||
searchForIdsWithAndOr(theSubResourceName, theChain, andOrParams, theRequest);
|
||||
subQ.where(toArray(myPredicates));
|
||||
subQ.where(myQueryRoot.getPredicateArray());
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop the old query root and predicate list back
|
||||
*/
|
||||
myResourceTableRoot = stackRoot;
|
||||
myPredicates = stackPredicates;
|
||||
myIndexJoins = stackIndexJoins;
|
||||
myQueryRoot.pop();
|
||||
return subQ;
|
||||
}
|
||||
|
||||
|
@ -508,12 +501,13 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
// TODO: we clear the predicates below because the filter builds up
|
||||
// its own collection of predicates. It'd probably be good at some
|
||||
// point to do something more fancy...
|
||||
ArrayList<Predicate> holdPredicates = new ArrayList<>(myPredicates);
|
||||
// FIXME KHS
|
||||
ArrayList<Predicate> holdPredicates = new ArrayList<>(myQueryRoot.getPredicates());
|
||||
|
||||
Predicate filterPredicate = processFilter(filter, theResourceName, theRequest);
|
||||
myPredicates.clear();
|
||||
myPredicates.addAll(holdPredicates);
|
||||
myPredicates.add(filterPredicate);
|
||||
myQueryRoot.clearPredicates();
|
||||
myQueryRoot.addPredicates(holdPredicates);
|
||||
myQueryRoot.addPredicate(filterPredicate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,13 +699,13 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
Predicate predicate = null;
|
||||
if ((operation == null) ||
|
||||
(operation == SearchFilterParser.CompareOperation.eq)) {
|
||||
predicate = myResourceTableRoot.get("myLanguage").as(String.class).in(values);
|
||||
predicate = myQueryRoot.get("myLanguage").as(String.class).in(values);
|
||||
} else if (operation == SearchFilterParser.CompareOperation.ne) {
|
||||
predicate = myResourceTableRoot.get("myLanguage").as(String.class).in(values).not();
|
||||
predicate = myQueryRoot.get("myLanguage").as(String.class).in(values).not();
|
||||
} else {
|
||||
throw new InvalidRequestException("Unsupported operator specified in language query, only \"eq\" and \"ne\" are supported");
|
||||
}
|
||||
myPredicates.add(predicate);
|
||||
myQueryRoot.addPredicate(predicate);
|
||||
if (operation != null) {
|
||||
return predicate;
|
||||
}
|
||||
|
@ -732,7 +726,7 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
throw new InvalidRequestException(msg);
|
||||
}
|
||||
|
||||
Join<ResourceTable, ResourceHistoryProvenanceEntity> join = myResourceTableRoot.join("myProvenance", JoinType.LEFT);
|
||||
Join<ResourceTable, ResourceHistoryProvenanceEntity> join = myQueryRoot.join("myProvenance", JoinType.LEFT);
|
||||
|
||||
List<Predicate> codePredicates = new ArrayList<>();
|
||||
|
||||
|
@ -752,7 +746,7 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
}
|
||||
|
||||
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
||||
myPredicates.add(retVal);
|
||||
myQueryRoot.addPredicate(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -809,11 +803,11 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
|
||||
Subquery<Long> subQ = myPredicateBuilder.createLinkSubquery(true, parameterName, targetResourceType, orValues, theRequest);
|
||||
|
||||
Join<ResourceTable, ResourceLink> join = myResourceTableRoot.join("myResourceLinksAsTarget", JoinType.LEFT);
|
||||
Join<ResourceTable, ResourceLink> join = myQueryRoot.join("myResourceLinksAsTarget", JoinType.LEFT);
|
||||
Predicate pathPredicate = myPredicateBuilder.createResourceLinkPathPredicate(targetResourceType, paramReference, join);
|
||||
Predicate pidPredicate = join.get("mySourceResourcePid").in(subQ);
|
||||
Predicate andPredicate = myBuilder.and(pathPredicate, pidPredicate);
|
||||
myPredicates.add(andPredicate);
|
||||
myQueryRoot.addPredicate(andPredicate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -828,11 +822,11 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
|||
|
||||
RuntimeSearchParam left = theParamDef.getCompositeOf().get(0);
|
||||
IQueryParameterType leftValue = cp.getLeftValue();
|
||||
myPredicates.add(createCompositeParamPart(theResourceName, myResourceTableRoot, left, leftValue));
|
||||
myQueryRoot.addPredicate(createCompositeParamPart(theResourceName, myQueryRoot.getRoot(), left, leftValue));
|
||||
|
||||
RuntimeSearchParam right = theParamDef.getCompositeOf().get(1);
|
||||
IQueryParameterType rightValue = cp.getRightValue();
|
||||
myPredicates.add(createCompositeParamPart(theResourceName, myResourceTableRoot, right, rightValue));
|
||||
myQueryRoot.addPredicate(createCompositeParamPart(theResourceName, myQueryRoot.getRoot(), right, rightValue));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,10 @@ public class PredicateBuilderResourceId extends BasePredicateBuilder {
|
|||
|
||||
Predicate addPredicateResourceId(List<List<IQueryParameterType>> theValues, String theResourceName, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequest) {
|
||||
|
||||
Predicate nextPredicate = createPredicateResourceId(myResourceTableRoot, theResourceName, theValues, theOperation, theRequest);
|
||||
Predicate nextPredicate = createPredicateResourceId(myQueryRoot.getRoot(), theResourceName, theValues, theOperation, theRequest);
|
||||
|
||||
if (nextPredicate != null) {
|
||||
myPredicates.add(nextPredicate);
|
||||
myQueryRoot.addPredicate(nextPredicate);
|
||||
return nextPredicate;
|
||||
}
|
||||
|
||||
|
@ -96,12 +96,12 @@ public class PredicateBuilderResourceId extends BasePredicateBuilder {
|
|||
default:
|
||||
case eq:
|
||||
codePredicates.add(theRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(allOrPids)));
|
||||
codePredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), theResourceName));
|
||||
codePredicates.add(myBuilder.equal(myQueryRoot.get("myResourceType"), theResourceName));
|
||||
nextPredicate = myBuilder.and(toArray(codePredicates));
|
||||
break;
|
||||
case ne:
|
||||
codePredicates.add(theRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(allOrPids)).not());
|
||||
codePredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), theResourceName));
|
||||
codePredicates.add(myBuilder.equal(myQueryRoot.get("myResourceType"), theResourceName));
|
||||
nextPredicate = myBuilder.and(toArray(codePredicates));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class PredicateBuilderString extends BasePredicateBuilder {
|
|||
}
|
||||
|
||||
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
||||
myPredicates.add(retVal);
|
||||
myQueryRoot.addPredicate(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,7 +135,13 @@ public class PredicateBuilderTag extends BasePredicateBuilder {
|
|||
Root<ResourceTag> subQfrom = subQ.from(ResourceTag.class);
|
||||
subQ.select(subQfrom.get("myResourceId").as(Long.class));
|
||||
|
||||
myPredicates.add(myBuilder.not(myBuilder.in(myResourceTableRoot.get("myId")).value(subQ)));
|
||||
myQueryRoot.addPredicate(
|
||||
myBuilder.not(
|
||||
myBuilder.in(
|
||||
myQueryRoot.get("myId")
|
||||
).value(subQ)
|
||||
)
|
||||
);
|
||||
|
||||
Subquery<Long> defJoin = subQ.subquery(Long.class);
|
||||
Root<TagDefinition> defJoinFrom = defJoin.from(TagDefinition.class);
|
||||
|
@ -149,11 +155,11 @@ public class PredicateBuilderTag extends BasePredicateBuilder {
|
|||
continue;
|
||||
}
|
||||
|
||||
Join<ResourceTable, ResourceTag> tagJoin = myResourceTableRoot.join("myTags", JoinType.LEFT);
|
||||
Join<ResourceTable, ResourceTag> tagJoin = myQueryRoot.join("myTags", JoinType.LEFT);
|
||||
From<ResourceTag, TagDefinition> defJoin = tagJoin.join("myTag");
|
||||
|
||||
Predicate tagListPredicate = createPredicateTagList(defJoin, myBuilder, tagType, tokens);
|
||||
myPredicates.add(tagListPredicate);
|
||||
myQueryRoot.addPredicate(tagListPredicate);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ public class PredicateBuilderToken extends BasePredicateBuilder {
|
|||
codePredicates.addAll(singleCode);
|
||||
|
||||
Predicate spPredicate = myBuilder.or(toArray(codePredicates));
|
||||
myPredicates.add(spPredicate);
|
||||
myQueryRoot.addPredicate(spPredicate);
|
||||
return spPredicate;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ public class PredicateBuilderUri extends BasePredicateBuilder {
|
|||
*/
|
||||
if (codePredicates.isEmpty()) {
|
||||
Predicate predicate = myBuilder.isNull(join.get("myMissing").as(String.class));
|
||||
myPredicates.add(predicate);
|
||||
myQueryRoot.addPredicate(predicate);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ public class PredicateBuilderUri extends BasePredicateBuilder {
|
|||
theParamName,
|
||||
join,
|
||||
orPredicate);
|
||||
myPredicates.add(outerPredicate);
|
||||
myQueryRoot.addPredicate(outerPredicate);
|
||||
return outerPredicate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package ca.uhn.fhir.jpa.dao.predicate;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
|
||||
import javax.persistence.criteria.*;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
public class QueryRoot {
|
||||
private final Stack<QueryRootEntry> myQueryRootStack = new Stack<>();
|
||||
|
||||
public void push(Root<ResourceTable> theResourceTableRoot) {
|
||||
myQueryRootStack.push(new QueryRootEntry(theResourceTableRoot));
|
||||
}
|
||||
|
||||
private QueryRootEntry top() {
|
||||
return myQueryRootStack.peek();
|
||||
}
|
||||
|
||||
void pop() {
|
||||
myQueryRootStack.pop();
|
||||
}
|
||||
|
||||
public Root<ResourceTable> getRoot() {
|
||||
return top().getRoot();
|
||||
}
|
||||
|
||||
public <Y> Path<Y> get(String theAttributeName) {
|
||||
return top().get(theAttributeName);
|
||||
}
|
||||
|
||||
public <Y> Join<ResourceTable, Y> join(String theAttributeName, JoinType theJoinType) {
|
||||
return top().join(theAttributeName, theJoinType);
|
||||
}
|
||||
|
||||
public Join<?,?> getIndexJoin(SearchBuilderJoinKey theKey) {
|
||||
return top().getIndexJoin(theKey);
|
||||
}
|
||||
|
||||
public void addPredicate(Predicate thePredicate) {
|
||||
top().addPredicate(thePredicate);
|
||||
}
|
||||
|
||||
public void addPredicates(List<Predicate> thePredicates) {
|
||||
top().addPredicates(thePredicates);
|
||||
}
|
||||
|
||||
public Predicate[] getPredicateArray() {
|
||||
return top().getPredicateArray();
|
||||
}
|
||||
|
||||
void putIndex(SearchBuilderJoinKey theKey, Join<ResourceTable, ResourceIndexedSearchParamDate> theJoin) {
|
||||
top().putIndex(theKey, theJoin);
|
||||
}
|
||||
|
||||
void clearPredicates() {
|
||||
top().clearPredicates();
|
||||
}
|
||||
|
||||
// FIXME KHS don't leak
|
||||
List<Predicate> getPredicates() {
|
||||
return top().getPredicates();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package ca.uhn.fhir.jpa.dao.predicate;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
|
||||
import javax.persistence.criteria.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class QueryRootEntry {
|
||||
private final Root<ResourceTable> myResourceTableRoot;
|
||||
private final ArrayList<Predicate> myPredicates = new ArrayList<>();
|
||||
private final IndexJoins myIndexJoins = new IndexJoins();
|
||||
|
||||
public QueryRootEntry(Root<ResourceTable> theResourceTableRoot) {
|
||||
myResourceTableRoot = theResourceTableRoot;
|
||||
}
|
||||
|
||||
public Root<ResourceTable> getRoot() {
|
||||
return myResourceTableRoot;
|
||||
}
|
||||
|
||||
public <Y> Path<Y> get(String theAttributeName) {
|
||||
return myResourceTableRoot.get(theAttributeName);
|
||||
}
|
||||
|
||||
public <Y> Join<ResourceTable, Y> join(String theAttributeName, JoinType theJoinType) {
|
||||
return myResourceTableRoot.join(theAttributeName, theJoinType);
|
||||
}
|
||||
|
||||
public Join<?,?> getIndexJoin(SearchBuilderJoinKey theKey) {
|
||||
return myIndexJoins.get(theKey);
|
||||
}
|
||||
|
||||
public void addPredicate(Predicate thePredicate) {
|
||||
myPredicates.add(thePredicate);
|
||||
}
|
||||
|
||||
public void addPredicates(List<Predicate> thePredicates) {
|
||||
myPredicates.addAll(thePredicates);
|
||||
}
|
||||
|
||||
public Predicate[] getPredicateArray() {
|
||||
return myPredicates.toArray(new Predicate[0]);
|
||||
}
|
||||
|
||||
void putIndex(SearchBuilderJoinKey theKey, Join<ResourceTable, ResourceIndexedSearchParamDate> theJoin) {
|
||||
myIndexJoins.put(theKey, theJoin);
|
||||
}
|
||||
|
||||
void clearPredicates() {
|
||||
myPredicates.clear();
|
||||
}
|
||||
|
||||
// FIXME KHS don't leak
|
||||
List<Predicate> getPredicates() {
|
||||
return myPredicates;
|
||||
}
|
||||
}
|
|
@ -4,107 +4,25 @@ import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
|
|||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SearchBuilderTest {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(SearchBuilderTest.class);
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualNoDecimal() {
|
||||
BigDecimal in = new BigDecimal("200");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertEquals("0.5", out.toPlainString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_() {
|
||||
BigDecimal in = new BigDecimal("200.");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertEquals("0.5", out.toPlainString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision123_010() {
|
||||
BigDecimal in = new BigDecimal("123.010");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.0005"));
|
||||
|
||||
BigDecimal low = in.subtract(out, MathContext.DECIMAL64);
|
||||
BigDecimal high = in.add(out, MathContext.DECIMAL64);
|
||||
ourLog.info("{} <= {} <= {}", new Object[] {low.toPlainString(), in.toPlainString(), high.toPlainString()});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_0() {
|
||||
BigDecimal in = new BigDecimal("200.0");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.05000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_3() {
|
||||
BigDecimal in = new BigDecimal("200.3");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.05000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_300() {
|
||||
BigDecimal in = new BigDecimal("200.300");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.0005000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_30000000() {
|
||||
BigDecimal in = new BigDecimal("200.30000000");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.000000005000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_300000001() {
|
||||
BigDecimal in = new BigDecimal("200.300000001");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.0000000005000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierApprox() {
|
||||
BigDecimal in = new BigDecimal("200");
|
||||
BigDecimal out = SearchBuilder.calculateFuzzAmount(ParamPrefixEnum.APPROXIMATE, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("20.000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncludeIterator() {
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package ca.uhn.fhir.jpa.dao.predicate;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.dao.SearchBuilderTest;
|
||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class FuzzCalculatorTest {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(SearchBuilderTest.class);
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualNoDecimal() {
|
||||
BigDecimal in = new BigDecimal("200");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertEquals("0.5", out.toPlainString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_() {
|
||||
BigDecimal in = new BigDecimal("200.");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertEquals("0.5", out.toPlainString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision123_010() {
|
||||
BigDecimal in = new BigDecimal("123.010");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.0005"));
|
||||
|
||||
BigDecimal low = in.subtract(out, MathContext.DECIMAL64);
|
||||
BigDecimal high = in.add(out, MathContext.DECIMAL64);
|
||||
ourLog.info("{} <= {} <= {}", new Object[] {low.toPlainString(), in.toPlainString(), high.toPlainString()});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_0() {
|
||||
BigDecimal in = new BigDecimal("200.0");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.05000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_3() {
|
||||
BigDecimal in = new BigDecimal("200.3");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.05000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_300() {
|
||||
BigDecimal in = new BigDecimal("200.300");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.0005000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_30000000() {
|
||||
BigDecimal in = new BigDecimal("200.30000000");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.000000005000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualDecimalPrecision200_300000001() {
|
||||
BigDecimal in = new BigDecimal("200.300000001");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.EQUAL, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("0.0000000005000000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierApprox() {
|
||||
BigDecimal in = new BigDecimal("200");
|
||||
BigDecimal out = FuzzCalculator.calculateFuzzAmount(ParamPrefixEnum.APPROXIMATE, in);
|
||||
ourLog.info(out.toPlainString());
|
||||
assertThat(out.toPlainString(), startsWith("20.000"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue