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.HookParams;
|
||||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
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.IResourceSearchViewDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
||||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
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.SearchRuntimeDetails;
|
||||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||||
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
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.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
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.jpa.util.*;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
@ -130,12 +127,9 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
private List<ResourcePersistentId> myAlsoIncludePids;
|
private List<ResourcePersistentId> myAlsoIncludePids;
|
||||||
private CriteriaBuilder myBuilder;
|
private CriteriaBuilder myBuilder;
|
||||||
private BaseHapiFhirDao<?> myCallingDao;
|
private BaseHapiFhirDao<?> myCallingDao;
|
||||||
private IndexJoins myIndexJoins = new IndexJoins();
|
|
||||||
private SearchParameterMap myParams;
|
private SearchParameterMap myParams;
|
||||||
private ArrayList<Predicate> myPredicates;
|
|
||||||
private String myResourceName;
|
private String myResourceName;
|
||||||
private AbstractQuery<Long> myResourceTableQuery;
|
private AbstractQuery<Long> myResourceTableQuery;
|
||||||
private Root<ResourceTable> myResourceTableRoot;
|
|
||||||
private Class<? extends IBaseResource> myResourceType;
|
private Class<? extends IBaseResource> myResourceType;
|
||||||
private String mySearchUuid;
|
private String mySearchUuid;
|
||||||
private int myFetchSize;
|
private int myFetchSize;
|
||||||
|
@ -143,6 +137,7 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
private Set<ResourcePersistentId> myPidSet;
|
private Set<ResourcePersistentId> myPidSet;
|
||||||
private boolean myHaveIndexJoins = false;
|
private boolean myHaveIndexJoins = false;
|
||||||
private PredicateBuilder myPredicateBuilder;
|
private PredicateBuilder myPredicateBuilder;
|
||||||
|
private final QueryRoot myQueryRoot = new QueryRoot();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -227,8 +222,6 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypedQuery<Long> createQuery(SortSpec sort, Integer theMaximumResults, boolean theCount, RequestDetails theRequest) {
|
private TypedQuery<Long> createQuery(SortSpec sort, Integer theMaximumResults, boolean theCount, RequestDetails theRequest) {
|
||||||
myPredicates = new ArrayList<>();
|
|
||||||
|
|
||||||
CriteriaQuery<Long> outerQuery;
|
CriteriaQuery<Long> outerQuery;
|
||||||
/*
|
/*
|
||||||
* Sort
|
* Sort
|
||||||
|
@ -241,17 +234,16 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
|
|
||||||
outerQuery = myBuilder.createQuery(Long.class);
|
outerQuery = myBuilder.createQuery(Long.class);
|
||||||
myResourceTableQuery = outerQuery;
|
myResourceTableQuery = outerQuery;
|
||||||
myResourceTableRoot = myResourceTableQuery.from(ResourceTable.class);
|
myQueryRoot.push(myResourceTableQuery.from(ResourceTable.class));
|
||||||
if (theCount) {
|
if (theCount) {
|
||||||
outerQuery.multiselect(myBuilder.countDistinct(myResourceTableRoot));
|
outerQuery.multiselect(myBuilder.countDistinct(myQueryRoot.getRoot()));
|
||||||
} else {
|
} else {
|
||||||
outerQuery.multiselect(myResourceTableRoot.get("myId").as(Long.class));
|
outerQuery.multiselect(myQueryRoot.get("myId").as(Long.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Order> orders = Lists.newArrayList();
|
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) {
|
if (orders.size() > 0) {
|
||||||
outerQuery.orderBy(orders);
|
outerQuery.orderBy(orders);
|
||||||
}
|
}
|
||||||
|
@ -260,18 +252,18 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
|
|
||||||
outerQuery = myBuilder.createQuery(Long.class);
|
outerQuery = myBuilder.createQuery(Long.class);
|
||||||
myResourceTableQuery = outerQuery;
|
myResourceTableQuery = outerQuery;
|
||||||
myResourceTableRoot = myResourceTableQuery.from(ResourceTable.class);
|
myQueryRoot.push(myResourceTableQuery.from(ResourceTable.class));
|
||||||
if (theCount) {
|
if (theCount) {
|
||||||
outerQuery.multiselect(myBuilder.countDistinct(myResourceTableRoot));
|
outerQuery.multiselect(myBuilder.countDistinct(myQueryRoot.getRoot()));
|
||||||
} else {
|
} else {
|
||||||
outerQuery.multiselect(myResourceTableRoot.get("myId").as(Long.class));
|
outerQuery.multiselect(myQueryRoot.get("myId").as(Long.class));
|
||||||
outerQuery.distinct(true);
|
outerQuery.distinct(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myParams.getEverythingMode() != null) {
|
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) {
|
if (myParams.get(IAnyResource.SP_RES_ID) != null) {
|
||||||
StringParam idParm = (StringParam) myParams.get(IAnyResource.SP_RES_ID).get(0).get(0);
|
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 = new ArrayList<>(1);
|
||||||
}
|
}
|
||||||
myAlsoIncludePids.add(pid);
|
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 {
|
} else {
|
||||||
Predicate targetTypePredicate = myBuilder.equal(join.get("myTargetResourceType").as(String.class), myResourceName);
|
Predicate targetTypePredicate = myBuilder.equal(join.get("myTargetResourceType").as(String.class), myResourceName);
|
||||||
Predicate sourceTypePredicate = myBuilder.equal(myResourceTableRoot.get("myResourceType").as(String.class), myResourceName);
|
Predicate sourceTypePredicate = myBuilder.equal(myQueryRoot.get("myResourceType").as(String.class), myResourceName);
|
||||||
myPredicates.add(myBuilder.or(sourceTypePredicate, targetTypePredicate));
|
myQueryRoot.addPredicate(myBuilder.or(sourceTypePredicate, targetTypePredicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -315,7 +307,7 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
pids = Collections.singletonList(new ResourcePersistentId(-1L));
|
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 (!myHaveIndexJoins) {
|
||||||
if (myParams.getEverythingMode() == null) {
|
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
|
// Last updated
|
||||||
DateRangeParam lu = myParams.getLastUpdated();
|
DateRangeParam lu = myParams.getLastUpdated();
|
||||||
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(lu, myBuilder, myResourceTableRoot);
|
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(lu, myBuilder, myQueryRoot.getRoot());
|
||||||
myPredicates.addAll(lastUpdatedPredicates);
|
myQueryRoot.addPredicates(lastUpdatedPredicates);
|
||||||
|
|
||||||
myResourceTableQuery.where(myBuilder.and(SearchBuilder.toArray(myPredicates)));
|
myResourceTableQuery.where(myBuilder.and(myQueryRoot.getPredicateArray()));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now perform the search
|
* 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
|
* @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)
|
* 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())) {
|
if (theSort == null || isBlank(theSort.getParamName())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IAnyResource.SP_RES_ID.equals(theSort.getParamName())) {
|
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) {
|
if (theSort.getOrder() == null || theSort.getOrder() == SortOrderEnum.ASC) {
|
||||||
theOrders.add(theBuilder.asc(forcedIdJoin.get("myForcedId")));
|
theOrders.add(theBuilder.asc(forcedIdJoin.get("myForcedId")));
|
||||||
theOrders.add(theBuilder.asc(theFrom.get("myId")));
|
theOrders.add(theBuilder.asc(theQueryRoot.get("myId")));
|
||||||
} else {
|
} else {
|
||||||
theOrders.add(theBuilder.desc(forcedIdJoin.get("myForcedId")));
|
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 (Constants.PARAM_LASTUPDATED.equals(theSort.getParamName())) {
|
||||||
if (theSort.getOrder() == null || theSort.getOrder() == SortOrderEnum.ASC) {
|
if (theSort.getOrder() == null || theSort.getOrder() == SortOrderEnum.ASC) {
|
||||||
theOrders.add(theBuilder.asc(theFrom.get("myUpdated")));
|
theOrders.add(theBuilder.asc(theQueryRoot.get("myUpdated")));
|
||||||
} else {
|
} 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);
|
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.
|
* sorting on, we'll also sort with it. Otherwise we need a new join.
|
||||||
*/
|
*/
|
||||||
SearchBuilderJoinKey key = new SearchBuilderJoinKey(theSort.getParamName(), joinType);
|
SearchBuilderJoinKey key = new SearchBuilderJoinKey(theSort.getParamName(), joinType);
|
||||||
Join<?, ?> join = myIndexJoins.get(key);
|
Join<?, ?> join = theQueryRoot.getIndexJoin(key);
|
||||||
if (join == null) {
|
if (join == null) {
|
||||||
join = theFrom.join(joinAttrName, JoinType.LEFT);
|
join = theQueryRoot.join(joinAttrName, JoinType.LEFT);
|
||||||
|
|
||||||
if (param.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
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 {
|
} else {
|
||||||
if (myDontUseHashesForSearch) {
|
if (myDontUseHashesForSearch) {
|
||||||
Predicate joinParam1 = theBuilder.equal(join.get("myParamName"), theSort.getParamName());
|
Predicate joinParam1 = theBuilder.equal(join.get("myParamName"), theSort.getParamName());
|
||||||
thePredicates.add(joinParam1);
|
theQueryRoot.addPredicate(joinParam1);
|
||||||
} else {
|
} else {
|
||||||
Long hashIdentity = BaseResourceIndexedSearchParam.calculateHashIdentity(myResourceName, theSort.getParamName());
|
Long hashIdentity = BaseResourceIndexedSearchParam.calculateHashIdentity(myResourceName, theSort.getParamName());
|
||||||
Predicate joinParam1 = theBuilder.equal(join.get("myHashIdentity"), hashIdentity);
|
Predicate joinParam1 = theBuilder.equal(join.get("myHashIdentity"), hashIdentity);
|
||||||
thePredicates.add(joinParam1);
|
theQueryRoot.addPredicate(joinParam1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -863,9 +855,9 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
private void addPredicateCompositeStringUnique(@Nonnull SearchParameterMap theParams, String theIndexdString) {
|
private void addPredicateCompositeStringUnique(@Nonnull SearchParameterMap theParams, String theIndexdString) {
|
||||||
myHaveIndexJoins = true;
|
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);
|
Predicate predicate = myBuilder.equal(join.get("myIndexString"), theIndexdString);
|
||||||
myPredicates.add(predicate);
|
myQueryRoot.addPredicate(predicate);
|
||||||
|
|
||||||
// Remove any empty parameters remaining after this
|
// Remove any empty parameters remaining after this
|
||||||
theParams.clean();
|
theParams.clean();
|
||||||
|
@ -901,16 +893,8 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
return myBuilder;
|
return myBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Root<ResourceTable> getResourceTableRoot() {
|
public QueryRoot getQueryRoot() {
|
||||||
return myResourceTableRoot;
|
return myQueryRoot;
|
||||||
}
|
|
||||||
|
|
||||||
public IndexJoins getIndexJoins() {
|
|
||||||
return myIndexJoins;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<Predicate> getPredicates() {
|
|
||||||
return myPredicates;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractQuery<Long> getResourceTableQuery() {
|
public AbstractQuery<Long> getResourceTableQuery() {
|
||||||
|
@ -1220,13 +1204,13 @@ public class SearchBuilder implements ISearchBuilder {
|
||||||
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(theLastUpdated, builder, from);
|
List<Predicate> lastUpdatedPredicates = createLastUpdatedPredicates(theLastUpdated, builder, from);
|
||||||
lastUpdatedPredicates.add(from.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(thePids)));
|
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);
|
TypedQuery<Long> query = theEntityManager.createQuery(cq);
|
||||||
|
|
||||||
return ResourcePersistentId.fromLongList(query.getResultList());
|
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]);
|
return thePredicates.toArray(new Predicate[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,7 @@ abstract class BasePredicateBuilder {
|
||||||
boolean myDontUseHashesForSearch;
|
boolean myDontUseHashesForSearch;
|
||||||
final BaseHapiFhirDao<?> myCallingDao;
|
final BaseHapiFhirDao<?> myCallingDao;
|
||||||
final CriteriaBuilder myBuilder;
|
final CriteriaBuilder myBuilder;
|
||||||
final Root<ResourceTable> myResourceTableRoot;
|
final QueryRoot myQueryRoot;
|
||||||
final IndexJoins myIndexJoins;
|
|
||||||
final ArrayList<Predicate> myPredicates;
|
|
||||||
final Class<? extends IBaseResource> myResourceType;
|
final Class<? extends IBaseResource> myResourceType;
|
||||||
final String myResourceName;
|
final String myResourceName;
|
||||||
final AbstractQuery<Long> myResourceTableQuery;
|
final AbstractQuery<Long> myResourceTableQuery;
|
||||||
|
@ -46,9 +44,7 @@ abstract class BasePredicateBuilder {
|
||||||
BasePredicateBuilder(SearchBuilder theSearchBuilder) {
|
BasePredicateBuilder(SearchBuilder theSearchBuilder) {
|
||||||
myCallingDao = theSearchBuilder.getCallingDao();
|
myCallingDao = theSearchBuilder.getCallingDao();
|
||||||
myBuilder = theSearchBuilder.getBuilder();
|
myBuilder = theSearchBuilder.getBuilder();
|
||||||
myResourceTableRoot = theSearchBuilder.getResourceTableRoot();
|
myQueryRoot = theSearchBuilder.getQueryRoot();
|
||||||
myIndexJoins = theSearchBuilder.getIndexJoins();
|
|
||||||
myPredicates = theSearchBuilder.getPredicates();
|
|
||||||
myResourceType = theSearchBuilder.getResourceType();
|
myResourceType = theSearchBuilder.getResourceType();
|
||||||
myResourceName = theSearchBuilder.getResourceName();
|
myResourceName = theSearchBuilder.getResourceName();
|
||||||
myResourceTableQuery = theSearchBuilder.getResourceTableQuery();
|
myResourceTableQuery = theSearchBuilder.getResourceTableQuery();
|
||||||
|
@ -65,59 +61,59 @@ abstract class BasePredicateBuilder {
|
||||||
Join<ResourceTable, ResourceIndexedSearchParamDate> join = null;
|
Join<ResourceTable, ResourceIndexedSearchParamDate> join = null;
|
||||||
switch (theType) {
|
switch (theType) {
|
||||||
case DATE:
|
case DATE:
|
||||||
join = myResourceTableRoot.join("myParamsDate", JoinType.LEFT);
|
join = myQueryRoot.join("myParamsDate", JoinType.LEFT);
|
||||||
break;
|
break;
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
join = myResourceTableRoot.join("myParamsNumber", JoinType.LEFT);
|
join = myQueryRoot.join("myParamsNumber", JoinType.LEFT);
|
||||||
break;
|
break;
|
||||||
case QUANTITY:
|
case QUANTITY:
|
||||||
join = myResourceTableRoot.join("myParamsQuantity", JoinType.LEFT);
|
join = myQueryRoot.join("myParamsQuantity", JoinType.LEFT);
|
||||||
break;
|
break;
|
||||||
case REFERENCE:
|
case REFERENCE:
|
||||||
join = myResourceTableRoot.join("myResourceLinks", JoinType.LEFT);
|
join = myQueryRoot.join("myResourceLinks", JoinType.LEFT);
|
||||||
break;
|
break;
|
||||||
case STRING:
|
case STRING:
|
||||||
join = myResourceTableRoot.join("myParamsString", JoinType.LEFT);
|
join = myQueryRoot.join("myParamsString", JoinType.LEFT);
|
||||||
break;
|
break;
|
||||||
case URI:
|
case URI:
|
||||||
join = myResourceTableRoot.join("myParamsUri", JoinType.LEFT);
|
join = myQueryRoot.join("myParamsUri", JoinType.LEFT);
|
||||||
break;
|
break;
|
||||||
case TOKEN:
|
case TOKEN:
|
||||||
join = myResourceTableRoot.join("myParamsToken", JoinType.LEFT);
|
join = myQueryRoot.join("myParamsToken", JoinType.LEFT);
|
||||||
break;
|
break;
|
||||||
case COORDS:
|
case COORDS:
|
||||||
join = myResourceTableRoot.join("myParamsCoords", JoinType.LEFT);
|
join = myQueryRoot.join("myParamsCoords", JoinType.LEFT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchBuilderJoinKey key = new SearchBuilderJoinKey(theSearchParameterName, theType);
|
SearchBuilderJoinKey key = new SearchBuilderJoinKey(theSearchParameterName, theType);
|
||||||
myIndexJoins.put(key, join);
|
myQueryRoot.putIndex(key, join);
|
||||||
|
|
||||||
return (Join<ResourceTable, T>) join;
|
return (Join<ResourceTable, T>) join;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPredicateParamMissing(String theResourceName, String theParamName, boolean theMissing) {
|
void addPredicateParamMissing(String theResourceName, String theParamName, boolean theMissing) {
|
||||||
// if (myDontUseHashesForSearch) {
|
// 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);
|
// Join<Object, Object> paramJoin = paramPresentJoin.join("mySearchParam", JoinType.LEFT);
|
||||||
//
|
//
|
||||||
// myPredicates.add(myBuilder.equal(paramJoin.get("myResourceName"), theResourceName));
|
// myQueryRoot.addPredicate(myBuilder.equal(paramJoin.get("myResourceName"), theResourceName));
|
||||||
// myPredicates.add(myBuilder.equal(paramJoin.get("myParamName"), theParamName));
|
// myQueryRoot.addPredicate(myBuilder.equal(paramJoin.get("myParamName"), theParamName));
|
||||||
// myPredicates.add(myBuilder.equal(paramPresentJoin.get("myPresent"), !theMissing));
|
// 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);
|
Expression<Long> hashPresence = paramPresentJoin.get("myHashPresence").as(Long.class);
|
||||||
Long hash = SearchParamPresent.calculateHashPresence(theResourceName, theParamName, !theMissing);
|
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) {
|
void addPredicateParamMissing(String theResourceName, String theParamName, boolean theMissing, Join<ResourceTable, ? extends BaseResourceIndexedSearchParam> theJoin) {
|
||||||
|
|
||||||
myPredicates.add(myBuilder.equal(theJoin.get("myResourceType"), theResourceName));
|
myQueryRoot.addPredicate(myBuilder.equal(theJoin.get("myResourceType"), theResourceName));
|
||||||
myPredicates.add(myBuilder.equal(theJoin.get("myParamName"), theParamName));
|
myQueryRoot.addPredicate(myBuilder.equal(theJoin.get("myParamName"), theParamName));
|
||||||
myPredicates.add(myBuilder.equal(theJoin.get("myMissing"), theMissing));
|
myQueryRoot.addPredicate(myBuilder.equal(theJoin.get("myMissing"), theMissing));
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate combineParamIndexPredicateWithParamNamePredicate(String theResourceName, String theParamName, From<?, ? extends BaseResourceIndexedSearchParam> theFrom, Predicate thePredicate) {
|
Predicate combineParamIndexPredicateWithParamNamePredicate(String theResourceName, String theParamName, From<?, ? extends BaseResourceIndexedSearchParam> theFrom, Predicate thePredicate) {
|
||||||
|
@ -133,7 +129,6 @@ abstract class BasePredicateBuilder {
|
||||||
return myBuilder.and(hashIdentityPredicate, thePredicate);
|
return myBuilder.and(hashIdentityPredicate, thePredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Predicate createPredicateNumeric(String theResourceName,
|
Predicate createPredicateNumeric(String theResourceName,
|
||||||
String theParamName,
|
String theParamName,
|
||||||
From<?, ? extends BaseResourceIndexedSearchParam> theFrom,
|
From<?, ? extends BaseResourceIndexedSearchParam> theFrom,
|
||||||
|
@ -166,7 +161,7 @@ abstract class BasePredicateBuilder {
|
||||||
num = builder.notEqual(thePath, theValue);
|
num = builder.notEqual(thePath, theValue);
|
||||||
break;
|
break;
|
||||||
case APPROXIMATE:
|
case APPROXIMATE:
|
||||||
BigDecimal mul = calculateFuzzAmount(thePrefix, theValue);
|
BigDecimal mul = FuzzCalculator.calculateFuzzAmount(thePrefix, theValue);
|
||||||
BigDecimal low = theValue.subtract(mul, MathContext.DECIMAL64);
|
BigDecimal low = theValue.subtract(mul, MathContext.DECIMAL64);
|
||||||
BigDecimal high = theValue.add(mul, MathContext.DECIMAL64);
|
BigDecimal high = theValue.add(mul, MathContext.DECIMAL64);
|
||||||
Predicate lowPred;
|
Predicate lowPred;
|
||||||
|
@ -189,28 +184,6 @@ abstract class BasePredicateBuilder {
|
||||||
return combineParamIndexPredicateWithParamNamePredicate(theResourceName, theParamName, theFrom, num);
|
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) {
|
static String createLeftAndRightMatchLikeExpression(String likeExpression) {
|
||||||
return "%" + likeExpression.replace("%", "[%]") + "%";
|
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));
|
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
||||||
myPredicates.add(retVal);
|
myQueryRoot.addPredicate(retVal);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,12 +52,10 @@ public class PredicateBuilderDate extends BasePredicateBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate orPredicates = myBuilder.or(toArray(codePredicates));
|
Predicate orPredicates = myBuilder.or(toArray(codePredicates));
|
||||||
myPredicates.add(orPredicates);
|
myQueryRoot.addPredicate(orPredicates);
|
||||||
return orPredicates;
|
return orPredicates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Predicate createPredicateDate(IQueryParameterType theParam,
|
public Predicate createPredicateDate(IQueryParameterType theParam,
|
||||||
String theResourceName,
|
String theResourceName,
|
||||||
String theParamName,
|
String theParamName,
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class PredicateBuilderNumber extends BasePredicateBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate predicate = myBuilder.or(toArray(codePredicates));
|
Predicate predicate = myBuilder.or(toArray(codePredicates));
|
||||||
myPredicates.add(predicate);
|
myQueryRoot.addPredicate(predicate);
|
||||||
return predicate;
|
return predicate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ public class PredicateBuilderQuantity extends BasePredicateBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
||||||
myPredicates.add(retVal);
|
myQueryRoot.addPredicate(retVal);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,13 +161,13 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
||||||
|
|
||||||
if (codePredicates.size() > 0) {
|
if (codePredicates.size() > 0) {
|
||||||
Predicate predicate = myBuilder.or(toArray(codePredicates));
|
Predicate predicate = myBuilder.or(toArray(codePredicates));
|
||||||
myPredicates.add(predicate);
|
myQueryRoot.addPredicate(predicate);
|
||||||
return predicate;
|
return predicate;
|
||||||
} else {
|
} else {
|
||||||
// Add a predicate that will never match
|
// Add a predicate that will never match
|
||||||
Predicate pidPredicate = join.get("myTargetResourcePid").in(-1L);
|
Predicate pidPredicate = join.get("myTargetResourcePid").in(-1L);
|
||||||
myPredicates.clear();
|
myQueryRoot.clearPredicates();
|
||||||
myPredicates.add(pidPredicate);
|
myQueryRoot.addPredicate(pidPredicate);
|
||||||
return pidPredicate;
|
return pidPredicate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate predicate = myBuilder.or(toArray(theCodePredicates));
|
Predicate predicate = myBuilder.or(toArray(theCodePredicates));
|
||||||
myPredicates.add(predicate);
|
myQueryRoot.addPredicate(predicate);
|
||||||
return predicate;
|
return predicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,29 +372,22 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
||||||
* stack and run a subquery
|
* stack and run a subquery
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Root<ResourceTable> stackRoot = myResourceTableRoot;
|
myQueryRoot.push(subQfrom);
|
||||||
ArrayList<Predicate> stackPredicates = myPredicates;
|
// FIXME KHS stack in all predicates
|
||||||
IndexJoins stackIndexJoins = myIndexJoins;
|
|
||||||
|
|
||||||
myResourceTableRoot = subQfrom;
|
|
||||||
myPredicates = Lists.newArrayList();
|
|
||||||
myIndexJoins = new IndexJoins();
|
|
||||||
|
|
||||||
// Create the subquery predicates
|
// Create the subquery predicates
|
||||||
myPredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), theSubResourceName));
|
myQueryRoot.addPredicate(myBuilder.equal(myQueryRoot.get("myResourceType"), theSubResourceName));
|
||||||
myPredicates.add(myBuilder.isNull(myResourceTableRoot.get("myDeleted")));
|
myQueryRoot.addPredicate(myBuilder.isNull(myQueryRoot.get("myDeleted")));
|
||||||
|
|
||||||
if (theFoundChainMatch) {
|
if (theFoundChainMatch) {
|
||||||
searchForIdsWithAndOr(theSubResourceName, theChain, andOrParams, theRequest);
|
searchForIdsWithAndOr(theSubResourceName, theChain, andOrParams, theRequest);
|
||||||
subQ.where(toArray(myPredicates));
|
subQ.where(myQueryRoot.getPredicateArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pop the old query root and predicate list back
|
* Pop the old query root and predicate list back
|
||||||
*/
|
*/
|
||||||
myResourceTableRoot = stackRoot;
|
myQueryRoot.pop();
|
||||||
myPredicates = stackPredicates;
|
|
||||||
myIndexJoins = stackIndexJoins;
|
|
||||||
return subQ;
|
return subQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,12 +501,13 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
||||||
// TODO: we clear the predicates below because the filter builds up
|
// TODO: we clear the predicates below because the filter builds up
|
||||||
// its own collection of predicates. It'd probably be good at some
|
// its own collection of predicates. It'd probably be good at some
|
||||||
// point to do something more fancy...
|
// 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);
|
Predicate filterPredicate = processFilter(filter, theResourceName, theRequest);
|
||||||
myPredicates.clear();
|
myQueryRoot.clearPredicates();
|
||||||
myPredicates.addAll(holdPredicates);
|
myQueryRoot.addPredicates(holdPredicates);
|
||||||
myPredicates.add(filterPredicate);
|
myQueryRoot.addPredicate(filterPredicate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,13 +699,13 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
||||||
Predicate predicate = null;
|
Predicate predicate = null;
|
||||||
if ((operation == null) ||
|
if ((operation == null) ||
|
||||||
(operation == SearchFilterParser.CompareOperation.eq)) {
|
(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) {
|
} 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 {
|
} else {
|
||||||
throw new InvalidRequestException("Unsupported operator specified in language query, only \"eq\" and \"ne\" are supported");
|
throw new InvalidRequestException("Unsupported operator specified in language query, only \"eq\" and \"ne\" are supported");
|
||||||
}
|
}
|
||||||
myPredicates.add(predicate);
|
myQueryRoot.addPredicate(predicate);
|
||||||
if (operation != null) {
|
if (operation != null) {
|
||||||
return predicate;
|
return predicate;
|
||||||
}
|
}
|
||||||
|
@ -732,7 +726,7 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
||||||
throw new InvalidRequestException(msg);
|
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<>();
|
List<Predicate> codePredicates = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -752,7 +746,7 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
||||||
myPredicates.add(retVal);
|
myQueryRoot.addPredicate(retVal);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,11 +803,11 @@ public class PredicateBuilderReference extends BasePredicateBuilder {
|
||||||
|
|
||||||
Subquery<Long> subQ = myPredicateBuilder.createLinkSubquery(true, parameterName, targetResourceType, orValues, theRequest);
|
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 pathPredicate = myPredicateBuilder.createResourceLinkPathPredicate(targetResourceType, paramReference, join);
|
||||||
Predicate pidPredicate = join.get("mySourceResourcePid").in(subQ);
|
Predicate pidPredicate = join.get("mySourceResourcePid").in(subQ);
|
||||||
Predicate andPredicate = myBuilder.and(pathPredicate, pidPredicate);
|
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);
|
RuntimeSearchParam left = theParamDef.getCompositeOf().get(0);
|
||||||
IQueryParameterType leftValue = cp.getLeftValue();
|
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);
|
RuntimeSearchParam right = theParamDef.getCompositeOf().get(1);
|
||||||
IQueryParameterType rightValue = cp.getRightValue();
|
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 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) {
|
if (nextPredicate != null) {
|
||||||
myPredicates.add(nextPredicate);
|
myQueryRoot.addPredicate(nextPredicate);
|
||||||
return nextPredicate;
|
return nextPredicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,12 +96,12 @@ public class PredicateBuilderResourceId extends BasePredicateBuilder {
|
||||||
default:
|
default:
|
||||||
case eq:
|
case eq:
|
||||||
codePredicates.add(theRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(allOrPids)));
|
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));
|
nextPredicate = myBuilder.and(toArray(codePredicates));
|
||||||
break;
|
break;
|
||||||
case ne:
|
case ne:
|
||||||
codePredicates.add(theRoot.get("myId").as(Long.class).in(ResourcePersistentId.toLongList(allOrPids)).not());
|
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));
|
nextPredicate = myBuilder.and(toArray(codePredicates));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class PredicateBuilderString extends BasePredicateBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
Predicate retVal = myBuilder.or(toArray(codePredicates));
|
||||||
myPredicates.add(retVal);
|
myQueryRoot.addPredicate(retVal);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,13 @@ public class PredicateBuilderTag extends BasePredicateBuilder {
|
||||||
Root<ResourceTag> subQfrom = subQ.from(ResourceTag.class);
|
Root<ResourceTag> subQfrom = subQ.from(ResourceTag.class);
|
||||||
subQ.select(subQfrom.get("myResourceId").as(Long.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);
|
Subquery<Long> defJoin = subQ.subquery(Long.class);
|
||||||
Root<TagDefinition> defJoinFrom = defJoin.from(TagDefinition.class);
|
Root<TagDefinition> defJoinFrom = defJoin.from(TagDefinition.class);
|
||||||
|
@ -149,11 +155,11 @@ public class PredicateBuilderTag extends BasePredicateBuilder {
|
||||||
continue;
|
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");
|
From<ResourceTag, TagDefinition> defJoin = tagJoin.join("myTag");
|
||||||
|
|
||||||
Predicate tagListPredicate = createPredicateTagList(defJoin, myBuilder, tagType, tokens);
|
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);
|
codePredicates.addAll(singleCode);
|
||||||
|
|
||||||
Predicate spPredicate = myBuilder.or(toArray(codePredicates));
|
Predicate spPredicate = myBuilder.or(toArray(codePredicates));
|
||||||
myPredicates.add(spPredicate);
|
myQueryRoot.addPredicate(spPredicate);
|
||||||
return spPredicate;
|
return spPredicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ public class PredicateBuilderUri extends BasePredicateBuilder {
|
||||||
*/
|
*/
|
||||||
if (codePredicates.isEmpty()) {
|
if (codePredicates.isEmpty()) {
|
||||||
Predicate predicate = myBuilder.isNull(join.get("myMissing").as(String.class));
|
Predicate predicate = myBuilder.isNull(join.get("myMissing").as(String.class));
|
||||||
myPredicates.add(predicate);
|
myQueryRoot.addPredicate(predicate);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ public class PredicateBuilderUri extends BasePredicateBuilder {
|
||||||
theParamName,
|
theParamName,
|
||||||
join,
|
join,
|
||||||
orPredicate);
|
orPredicate);
|
||||||
myPredicates.add(outerPredicate);
|
myQueryRoot.addPredicate(outerPredicate);
|
||||||
return 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.ResourceLink;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.MathContext;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.startsWith;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class SearchBuilderTest {
|
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
|
@Test
|
||||||
public void testIncludeIterator() {
|
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