Allow for _total parameter
This commit is contained in:
parent
a0333a4767
commit
99cd4ce5f7
|
@ -197,6 +197,7 @@ public class Constants {
|
||||||
* This is provided for testing only! Use with caution as this property may change.
|
* This is provided for testing only! Use with caution as this property may change.
|
||||||
*/
|
*/
|
||||||
public static final String TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS = "TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS";
|
public static final String TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS = "TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS";
|
||||||
|
public static final String PARAM_SEARCH_TOTAL_MODE = "_total";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
CHARSET_UTF8 = Charset.forName(CHARSET_NAME_UTF8);
|
CHARSET_UTF8 = Charset.forName(CHARSET_NAME_UTF8);
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package ca.uhn.fhir.rest.api;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public enum SearchTotalModeEnum {
|
||||||
|
|
||||||
|
NONE("none"),
|
||||||
|
ESTIMATED("estimated"),
|
||||||
|
ACCURATE("accurate");
|
||||||
|
|
||||||
|
private static volatile Map<String, SearchTotalModeEnum> ourCodeToEnum;
|
||||||
|
private final String myCode;
|
||||||
|
|
||||||
|
SearchTotalModeEnum(String theCode) {
|
||||||
|
myCode = theCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return myCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SearchTotalModeEnum fromCode(String theCode) {
|
||||||
|
Map<String, SearchTotalModeEnum> map = ourCodeToEnum;
|
||||||
|
if (map == null) {
|
||||||
|
map = new HashMap<>();
|
||||||
|
for (SearchTotalModeEnum next : values()) {
|
||||||
|
map.put(next.getCode(), next);
|
||||||
|
}
|
||||||
|
ourCodeToEnum = map;
|
||||||
|
}
|
||||||
|
return map.get(theCode);
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,7 +67,7 @@ public enum SummaryEnum {
|
||||||
public static SummaryEnum fromCode(String theCode) {
|
public static SummaryEnum fromCode(String theCode) {
|
||||||
Map<String, SummaryEnum> c2s = ourCodeToSummary;
|
Map<String, SummaryEnum> c2s = ourCodeToSummary;
|
||||||
if (c2s == null) {
|
if (c2s == null) {
|
||||||
c2s = new HashMap<String, SummaryEnum>();
|
c2s = new HashMap<>();
|
||||||
for (SummaryEnum next : values()) {
|
for (SummaryEnum next : values()) {
|
||||||
c2s.put(next.getCode(), next);
|
c2s.put(next.getCode(), next);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,6 @@ public interface IClientExecutable<T extends IClientExecutable<?,Y>, Y> {
|
||||||
/**
|
/**
|
||||||
* Request that the server modify the response using the <code>_summary</code> param
|
* Request that the server modify the response using the <code>_summary</code> param
|
||||||
*/
|
*/
|
||||||
T summaryMode(SummaryEnum... theSummary);
|
T summaryMode(SummaryEnum theSummary);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ package ca.uhn.fhir.rest.gclient;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.rest.api.SearchStyleEnum;
|
import ca.uhn.fhir.rest.api.SearchStyleEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
|
||||||
import ca.uhn.fhir.rest.api.SortSpec;
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
|
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||||
|
|
||||||
|
@ -80,6 +82,14 @@ public interface IQuery<Y> extends IBaseQuery<IQuery<Y>>, IClientExecutable<IQue
|
||||||
*/
|
*/
|
||||||
<B extends IBaseBundle> IQuery<B> returnBundle(Class<B> theClass);
|
<B extends IBaseBundle> IQuery<B> returnBundle(Class<B> theClass);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request that the server modify the response using the <code>_total</code> param
|
||||||
|
*
|
||||||
|
* THIS IS AN EXPERIMENTAL FEATURE - Use with caution, as it may be
|
||||||
|
* removed or modified in a future version.
|
||||||
|
*/
|
||||||
|
IQuery<Y> totalMode(SearchTotalModeEnum theTotalMode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a "_revinclude" specification
|
* Add a "_revinclude" specification
|
||||||
*
|
*
|
||||||
|
|
|
@ -205,7 +205,7 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
<T> T invokeClient(FhirContext theContext, IClientResponseHandler<T> binding, BaseHttpClientInvocation clientInvocation, EncodingEnum theEncoding, Boolean thePrettyPrint,
|
<T> T invokeClient(FhirContext theContext, IClientResponseHandler<T> binding, BaseHttpClientInvocation clientInvocation, EncodingEnum theEncoding, Boolean thePrettyPrint,
|
||||||
boolean theLogRequestAndResponse, List<SummaryEnum> theSummaryMode, Set<String> theSubsetElements, CacheControlDirective theCacheControlDirective) {
|
boolean theLogRequestAndResponse, SummaryEnum theSummaryMode, Set<String> theSubsetElements, CacheControlDirective theCacheControlDirective) {
|
||||||
|
|
||||||
if (!myDontValidateConformance) {
|
if (!myDontValidateConformance) {
|
||||||
myFactory.validateServerBaseIfConfiguredToDoSo(myUrlBase, myClient, this);
|
myFactory.validateServerBaseIfConfiguredToDoSo(myUrlBase, myClient, this);
|
||||||
|
@ -227,8 +227,7 @@ public abstract class BaseClient implements IRestfulClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theSummaryMode != null) {
|
if (theSummaryMode != null) {
|
||||||
List<String> summaryModeStrings = theSummaryMode.stream().map(SummaryEnum::getCode).collect(Collectors.toList());;
|
params.put(Constants.PARAM_SUMMARY, Collections.singletonList(theSummaryMode.getCode()));
|
||||||
params.put(Constants.PARAM_SUMMARY, summaryModeStrings);
|
|
||||||
} else if (mySummary != null) {
|
} else if (mySummary != null) {
|
||||||
params.put(Constants.PARAM_SUMMARY, Collections.singletonList(mySummary.getCode()));
|
params.put(Constants.PARAM_SUMMARY, Collections.singletonList(mySummary.getCode()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends IBaseResource> T doReadOrVRead(final Class<T> theType, IIdType theId, boolean theVRead, ICallable<T> theNotModifiedHandler, String theIfVersionMatches, Boolean thePrettyPrint,
|
private <T extends IBaseResource> T doReadOrVRead(final Class<T> theType, IIdType theId, boolean theVRead, ICallable<T> theNotModifiedHandler, String theIfVersionMatches, Boolean thePrettyPrint,
|
||||||
List<SummaryEnum> theSummary, EncodingEnum theEncoding, Set<String> theSubsetElements) {
|
SummaryEnum theSummary, EncodingEnum theEncoding, Set<String> theSubsetElements) {
|
||||||
String resName = toResourceName(theType);
|
String resName = toResourceName(theType);
|
||||||
IIdType id = theId;
|
IIdType id = theId;
|
||||||
if (!id.hasBaseUrl()) {
|
if (!id.hasBaseUrl()) {
|
||||||
|
@ -127,8 +127,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
invocation.addHeader(Constants.HEADER_IF_NONE_MATCH, '"' + theIfVersionMatches + '"');
|
invocation.addHeader(Constants.HEADER_IF_NONE_MATCH, '"' + theIfVersionMatches + '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean allowHtmlResponse = (theSummary != null && theSummary.contains(SummaryEnum.TEXT)) || (theSummary == null && getSummary() == SummaryEnum.TEXT);
|
boolean allowHtmlResponse = SummaryEnum.TEXT.equals(theSummary);
|
||||||
ResourceResponseHandler<T> binding = new ResourceResponseHandler<T>(theType, (Class<? extends IBaseResource>) null, id, allowHtmlResponse);
|
ResourceResponseHandler<T> binding = new ResourceResponseHandler<>(theType, (Class<? extends IBaseResource>) null, id, allowHtmlResponse);
|
||||||
|
|
||||||
if (theNotModifiedHandler == null) {
|
if (theNotModifiedHandler == null) {
|
||||||
return invokeClient(myContext, binding, invocation, theEncoding, thePrettyPrint, myLogRequestAndResponse, theSummary, theSubsetElements, null);
|
return invokeClient(myContext, binding, invocation, theEncoding, thePrettyPrint, myLogRequestAndResponse, theSummary, theSubsetElements, null);
|
||||||
|
@ -368,7 +368,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
|
|
||||||
protected EncodingEnum myParamEncoding;
|
protected EncodingEnum myParamEncoding;
|
||||||
protected Boolean myPrettyPrint;
|
protected Boolean myPrettyPrint;
|
||||||
protected List<SummaryEnum> mySummaryMode;
|
protected SummaryEnum mySummaryMode;
|
||||||
protected CacheControlDirective myCacheControlDirective;
|
protected CacheControlDirective myCacheControlDirective;
|
||||||
private List<Class<? extends IBaseResource>> myPreferResponseTypes;
|
private List<Class<? extends IBaseResource>> myPreferResponseTypes;
|
||||||
private boolean myQueryLogRequestAndResponse;
|
private boolean myQueryLogRequestAndResponse;
|
||||||
|
@ -483,15 +483,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public T summaryMode(SummaryEnum... theSummary) {
|
public T summaryMode(SummaryEnum theSummary) {
|
||||||
mySummaryMode = null;
|
mySummaryMode = theSummary;
|
||||||
if (theSummary != null) {
|
|
||||||
if (theSummary.length == 1) {
|
|
||||||
mySummaryMode = Collections.singletonList(theSummary[0]);
|
|
||||||
} else {
|
|
||||||
mySummaryMode = Arrays.asList(theSummary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ((T) this);
|
return ((T) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1657,20 +1650,21 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
private class SearchInternal<OUTPUT> extends BaseSearch<IQuery<OUTPUT>, IQuery<OUTPUT>, OUTPUT> implements IQuery<OUTPUT>, IUntypedQuery<IQuery<OUTPUT>> {
|
private class SearchInternal<OUTPUT> extends BaseSearch<IQuery<OUTPUT>, IQuery<OUTPUT>, OUTPUT> implements IQuery<OUTPUT>, IUntypedQuery<IQuery<OUTPUT>> {
|
||||||
|
|
||||||
private String myCompartmentName;
|
private String myCompartmentName;
|
||||||
private List<Include> myInclude = new ArrayList<Include>();
|
private List<Include> myInclude = new ArrayList<>();
|
||||||
private DateRangeParam myLastUpdated;
|
private DateRangeParam myLastUpdated;
|
||||||
private Integer myParamLimit;
|
private Integer myParamLimit;
|
||||||
private List<Collection<String>> myProfiles = new ArrayList<Collection<String>>();
|
private List<Collection<String>> myProfiles = new ArrayList<>();
|
||||||
private String myResourceId;
|
private String myResourceId;
|
||||||
private String myResourceName;
|
private String myResourceName;
|
||||||
private Class<? extends IBaseResource> myResourceType;
|
private Class<? extends IBaseResource> myResourceType;
|
||||||
private Class<? extends IBaseBundle> myReturnBundleType;
|
private Class<? extends IBaseBundle> myReturnBundleType;
|
||||||
private List<Include> myRevInclude = new ArrayList<Include>();
|
private List<Include> myRevInclude = new ArrayList<>();
|
||||||
private SearchStyleEnum mySearchStyle;
|
private SearchStyleEnum mySearchStyle;
|
||||||
private String mySearchUrl;
|
private String mySearchUrl;
|
||||||
private List<TokenParam> mySecurity = new ArrayList<TokenParam>();
|
private List<TokenParam> mySecurity = new ArrayList<>();
|
||||||
private List<SortInternal> mySort = new ArrayList<SortInternal>();
|
private List<SortInternal> mySort = new ArrayList<>();
|
||||||
private List<TokenParam> myTags = new ArrayList<TokenParam>();
|
private List<TokenParam> myTags = new ArrayList<>();
|
||||||
|
private SearchTotalModeEnum myTotalMode;
|
||||||
|
|
||||||
public SearchInternal() {
|
public SearchInternal() {
|
||||||
myResourceType = null;
|
myResourceType = null;
|
||||||
|
@ -1792,6 +1786,10 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (myTotalMode != null) {
|
||||||
|
addParam(params, Constants.PARAM_SEARCH_TOTAL_MODE, myTotalMode.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
IClientResponseHandler<? extends IBase> binding;
|
IClientResponseHandler<? extends IBase> binding;
|
||||||
binding = new ResourceResponseHandler(myReturnBundleType, getPreferResponseTypes(myResourceType));
|
binding = new ResourceResponseHandler(myReturnBundleType, getPreferResponseTypes(myResourceType));
|
||||||
|
|
||||||
|
@ -1843,6 +1841,12 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
return count(theLimitTo);
|
return count(theLimitTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IQuery<OUTPUT> totalMode(SearchTotalModeEnum theSearchTotalModeEnum) {
|
||||||
|
myTotalMode = theSearchTotalModeEnum;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IQuery returnBundle(Class theClass) {
|
public IQuery returnBundle(Class theClass) {
|
||||||
if (theClass == null) {
|
if (theClass == null) {
|
||||||
|
|
|
@ -5,10 +5,7 @@ import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.*;
|
||||||
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.SortSpec;
|
|
||||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
|
||||||
import ca.uhn.fhir.rest.param.DateParam;
|
import ca.uhn.fhir.rest.param.DateParam;
|
||||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||||
import ca.uhn.fhir.util.ObjectUtil;
|
import ca.uhn.fhir.util.ObjectUtil;
|
||||||
|
@ -54,7 +51,8 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
||||||
private Integer myLoadSynchronousUpTo;
|
private Integer myLoadSynchronousUpTo;
|
||||||
private Set<Include> myRevIncludes;
|
private Set<Include> myRevIncludes;
|
||||||
private SortSpec mySort;
|
private SortSpec mySort;
|
||||||
private Set<SummaryEnum> mySummaryMode;
|
private SummaryEnum mySummaryMode;
|
||||||
|
private SearchTotalModeEnum mySearchTotalMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -70,20 +68,22 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
||||||
add(theName, theParam);
|
add(theName, theParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public SummaryEnum getSummaryMode() {
|
||||||
* @return An unmodifiable set
|
return mySummaryMode;
|
||||||
*/
|
|
||||||
public Set<SummaryEnum> getSummaryMode() {
|
|
||||||
if (mySummaryMode == null) {
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableSet(mySummaryMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSummaryMode(Set<SummaryEnum> theSummaryMode) {
|
public void setSummaryMode(SummaryEnum theSummaryMode) {
|
||||||
mySummaryMode = theSummaryMode;
|
mySummaryMode = theSummaryMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SearchTotalModeEnum getSearchTotalMode() {
|
||||||
|
return mySearchTotalMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchTotalMode(SearchTotalModeEnum theSearchTotalMode) {
|
||||||
|
mySearchTotalMode = theSearchTotalMode;
|
||||||
|
}
|
||||||
|
|
||||||
public SearchParameterMap add(String theName, DateParam theDateParam) {
|
public SearchParameterMap add(String theName, DateParam theDateParam) {
|
||||||
add(theName, (IQueryParameterOr<?>) theDateParam);
|
add(theName, (IQueryParameterOr<?>) theDateParam);
|
||||||
return this;
|
return this;
|
||||||
|
@ -261,7 +261,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
||||||
/**
|
/**
|
||||||
* This will only return true if all parameters have no modifier of any kind
|
* This will only return true if all parameters have no modifier of any kind
|
||||||
*/
|
*/
|
||||||
public boolean isAllParametersHaveNoModifier() {
|
boolean isAllParametersHaveNoModifier() {
|
||||||
for (List<List<? extends IQueryParameterType>> nextParamName : values()) {
|
for (List<List<? extends IQueryParameterType>> nextParamName : values()) {
|
||||||
for (List<? extends IQueryParameterType> nextAnd : nextParamName) {
|
for (List<? extends IQueryParameterType> nextAnd : nextParamName) {
|
||||||
for (IQueryParameterType nextOr : nextAnd) {
|
for (IQueryParameterType nextOr : nextAnd) {
|
||||||
|
@ -408,12 +408,10 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
||||||
|
|
||||||
// Summary
|
// Summary
|
||||||
if (getSummaryMode() != null) {
|
if (getSummaryMode() != null) {
|
||||||
for (SummaryEnum next : getSummaryMode()) {
|
addUrlParamSeparator(b);
|
||||||
addUrlParamSeparator(b);
|
b.append(Constants.PARAM_SUMMARY);
|
||||||
b.append(Constants.PARAM_SUMMARY);
|
b.append('=');
|
||||||
b.append('=');
|
b.append(getSummaryMode().getCode());
|
||||||
b.append(next.getCode());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.length() == 0) {
|
if (b.length() == 0) {
|
||||||
|
@ -489,7 +487,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
||||||
public class QueryParameterOrComparator implements Comparator<List<IQueryParameterType>> {
|
public class QueryParameterOrComparator implements Comparator<List<IQueryParameterType>> {
|
||||||
private final FhirContext myCtx;
|
private final FhirContext myCtx;
|
||||||
|
|
||||||
public QueryParameterOrComparator(FhirContext theCtx) {
|
QueryParameterOrComparator(FhirContext theCtx) {
|
||||||
myCtx = theCtx;
|
myCtx = theCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +503,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
||||||
|
|
||||||
private final FhirContext myCtx;
|
private final FhirContext myCtx;
|
||||||
|
|
||||||
public QueryParameterTypeComparator(FhirContext theCtx) {
|
QueryParameterTypeComparator(FhirContext theCtx) {
|
||||||
myCtx = theCtx;
|
myCtx = theCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,7 +514,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int compare(FhirContext theCtx, IQueryParameterType theO1, IQueryParameterType theO2) {
|
private static int compare(FhirContext theCtx, IQueryParameterType theO1, IQueryParameterType theO2) {
|
||||||
int retVal;
|
int retVal;
|
||||||
if (theO1.getMissing() == null && theO2.getMissing() == null) {
|
if (theO1.getMissing() == null && theO2.getMissing() == null) {
|
||||||
retVal = 0;
|
retVal = 0;
|
||||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.jpa.entity.*;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
import ca.uhn.fhir.rest.api.CacheControlDirective;
|
import ca.uhn.fhir.rest.api.CacheControlDirective;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
|
||||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.IPagingProvider;
|
import ca.uhn.fhir.rest.server.IPagingProvider;
|
||||||
|
@ -724,8 +725,8 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
||||||
*
|
*
|
||||||
* before doing anything else.
|
* before doing anything else.
|
||||||
*/
|
*/
|
||||||
boolean wantCount = myParams.getSummaryMode().contains(SummaryEnum.COUNT);
|
boolean wantOnlyCount = SummaryEnum.COUNT.equals(myParams.getSummaryMode());
|
||||||
boolean wantOnlyCount = wantCount && myParams.getSummaryMode().size() == 1;
|
boolean wantCount = wantOnlyCount || SearchTotalModeEnum.ACCURATE.equals(myParams.getSearchTotalMode());
|
||||||
if (wantCount) {
|
if (wantCount) {
|
||||||
ourLog.trace("Performing count");
|
ourLog.trace("Performing count");
|
||||||
ISearchBuilder sb = newSearchBuilder();
|
ISearchBuilder sb = newSearchBuilder();
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
import ca.uhn.fhir.jpa.entity.SearchStatusEnum;
|
import ca.uhn.fhir.jpa.entity.SearchStatusEnum;
|
||||||
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
||||||
|
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
|
||||||
import ca.uhn.fhir.rest.api.SortSpec;
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
@ -69,7 +70,7 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
params.setSort(new SortSpec(Patient.SP_NAME));
|
params.setSort(new SortSpec(Patient.SP_NAME));
|
||||||
params.setSummaryMode(Sets.newHashSet(SummaryEnum.COUNT));
|
params.setSummaryMode(SummaryEnum.COUNT);
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
IBundleProvider results = myPatientDao.search(params);
|
||||||
String uuid = results.getUuid();
|
String uuid = results.getUuid();
|
||||||
ourLog.info("** Search returned UUID: {}", uuid);
|
ourLog.info("** Search returned UUID: {}", uuid);
|
||||||
|
@ -98,7 +99,7 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
|
||||||
// Seach with count only
|
// Seach with count only
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
params.add(Patient.SP_NAME, new StringParam("FAM"));
|
params.add(Patient.SP_NAME, new StringParam("FAM"));
|
||||||
params.setSummaryMode(Sets.newHashSet(SummaryEnum.COUNT));
|
params.setSummaryMode((SummaryEnum.COUNT));
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
IBundleProvider results = myPatientDao.search(params);
|
||||||
String uuid = results.getUuid();
|
String uuid = results.getUuid();
|
||||||
ourLog.info("** Search returned UUID: {}", uuid);
|
ourLog.info("** Search returned UUID: {}", uuid);
|
||||||
|
@ -107,10 +108,10 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
|
||||||
assertThat(ids, empty());
|
assertThat(ids, empty());
|
||||||
assertEquals(201, myDatabaseBackedPagingProvider.retrieveResultList(uuid).size().intValue());
|
assertEquals(201, myDatabaseBackedPagingProvider.retrieveResultList(uuid).size().intValue());
|
||||||
|
|
||||||
// Seach with count and dat
|
// Seach with total expicitly requested
|
||||||
params = new SearchParameterMap();
|
params = new SearchParameterMap();
|
||||||
params.add(Patient.SP_NAME, new StringParam("FAM"));
|
params.add(Patient.SP_NAME, new StringParam("FAM"));
|
||||||
params.setSummaryMode(Sets.newHashSet(SummaryEnum.COUNT, SummaryEnum.DATA));
|
params.setSearchTotalMode(SearchTotalModeEnum.ACCURATE);
|
||||||
results = myPatientDao.search(params);
|
results = myPatientDao.search(params);
|
||||||
uuid = results.getUuid();
|
uuid = results.getUuid();
|
||||||
ourLog.info("** Search returned UUID: {}", uuid);
|
ourLog.info("** Search returned UUID: {}", uuid);
|
||||||
|
@ -122,7 +123,7 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
|
||||||
// Seach with count only
|
// Seach with count only
|
||||||
params = new SearchParameterMap();
|
params = new SearchParameterMap();
|
||||||
params.add(Patient.SP_NAME, new StringParam().setMissing(false));
|
params.add(Patient.SP_NAME, new StringParam().setMissing(false));
|
||||||
params.setSummaryMode(Sets.newHashSet(SummaryEnum.COUNT));
|
params.setSummaryMode(SummaryEnum.COUNT);
|
||||||
results = myPatientDao.search(params);
|
results = myPatientDao.search(params);
|
||||||
uuid = results.getUuid();
|
uuid = results.getUuid();
|
||||||
ourLog.info("** Search returned UUID: {}", uuid);
|
ourLog.info("** Search returned UUID: {}", uuid);
|
||||||
|
@ -134,7 +135,7 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFetchCountAndDataForSlowLoading() {
|
public void testFetchTotalAccurateForSlowLoading() {
|
||||||
mySearchCoordinatorSvcImpl.setLoadingThrottleForUnitTests(25);
|
mySearchCoordinatorSvcImpl.setLoadingThrottleForUnitTests(25);
|
||||||
mySearchCoordinatorSvcImpl.setSyncSizeForUnitTests(10);
|
mySearchCoordinatorSvcImpl.setSyncSizeForUnitTests(10);
|
||||||
|
|
||||||
|
@ -143,7 +144,7 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
params.setSort(new SortSpec(Patient.SP_NAME));
|
params.setSort(new SortSpec(Patient.SP_NAME));
|
||||||
params.setCount(5);
|
params.setCount(5);
|
||||||
params.setSummaryMode(Sets.newHashSet(SummaryEnum.COUNT, SummaryEnum.DATA));
|
params.setSearchTotalMode(SearchTotalModeEnum.ACCURATE);
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
IBundleProvider results = myPatientDao.search(params);
|
||||||
String uuid = results.getUuid();
|
String uuid = results.getUuid();
|
||||||
ourLog.info("** Search returned UUID: {}", uuid);
|
ourLog.info("** Search returned UUID: {}", uuid);
|
||||||
|
@ -168,7 +169,8 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
SearchParameterMap params = new SearchParameterMap();
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
params.setSort(new SortSpec(Patient.SP_NAME));
|
params.setSort(new SortSpec(Patient.SP_NAME));
|
||||||
params.setSummaryMode(Sets.newHashSet(SummaryEnum.COUNT, SummaryEnum.DATA));
|
params.setSearchTotalMode(SearchTotalModeEnum.ACCURATE);
|
||||||
|
params.setSummaryMode(SummaryEnum.DATA);
|
||||||
IBundleProvider results = myPatientDao.search(params);
|
IBundleProvider results = myPatientDao.search(params);
|
||||||
String uuid = results.getUuid();
|
String uuid = results.getUuid();
|
||||||
ourLog.info("** Search returned UUID: {}", uuid);
|
ourLog.info("** Search returned UUID: {}", uuid);
|
||||||
|
@ -183,7 +185,8 @@ public class FhirResourceDaoR4SearchOptimizedTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
params = new SearchParameterMap();
|
params = new SearchParameterMap();
|
||||||
params.setSort(new SortSpec(Patient.SP_NAME));
|
params.setSort(new SortSpec(Patient.SP_NAME));
|
||||||
params.setSummaryMode(Sets.newHashSet(SummaryEnum.COUNT, SummaryEnum.DATA));
|
params.setSearchTotalMode(SearchTotalModeEnum.ACCURATE);
|
||||||
|
params.setSummaryMode(SummaryEnum.DATA);
|
||||||
results = myPatientDao.search(params);
|
results = myPatientDao.search(params);
|
||||||
uuid = results.getUuid();
|
uuid = results.getUuid();
|
||||||
ourLog.info("** Search returned UUID: {}", uuid);
|
ourLog.info("** Search returned UUID: {}", uuid);
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.provider.r4;
|
||||||
import ca.uhn.fhir.jpa.config.TestR4Config;
|
import ca.uhn.fhir.jpa.config.TestR4Config;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
||||||
|
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
|
||||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
@ -79,12 +80,12 @@ public class ResourceProviderSummaryModeR4Test extends BaseResourceProviderR4Tes
|
||||||
* Count and data - Should include both a count and the data portions of results
|
* Count and data - Should include both a count and the data portions of results
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSearchWithCountAndData() {
|
public void testSearchWithTotalAccurate() {
|
||||||
Bundle outcome = ourClient
|
Bundle outcome = ourClient
|
||||||
.search()
|
.search()
|
||||||
.forResource(Patient.class)
|
.forResource(Patient.class)
|
||||||
.where(Patient.ACTIVE.exactly().code("true"))
|
.where(Patient.ACTIVE.exactly().code("true"))
|
||||||
.summaryMode(SummaryEnum.COUNT, SummaryEnum.DATA)
|
.totalMode(SearchTotalModeEnum.ACCURATE)
|
||||||
.returnBundle(Bundle.class)
|
.returnBundle(Bundle.class)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,8 @@ public class MethodUtil {
|
||||||
param = new SummaryEnumParameter();
|
param = new SummaryEnumParameter();
|
||||||
} else if (parameterType.equals(PatchTypeEnum.class)) {
|
} else if (parameterType.equals(PatchTypeEnum.class)) {
|
||||||
param = new PatchTypeParameter();
|
param = new PatchTypeParameter();
|
||||||
|
} else if (parameterType.equals(SearchTotalModeEnum.class)) {
|
||||||
|
param = new SearchTotalModeParameter();
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < annotations.length && param == null; i++) {
|
for (int i = 0; i < annotations.length && param == null; i++) {
|
||||||
Annotation nextAnnotation = annotations[i];
|
Annotation nextAnnotation = annotations[i];
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package ca.uhn.fhir.rest.server.method;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Server Framework
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2018 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SearchTotalModeParameter implements IParameter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
|
return getTypeForRequestOrThrowInvalidRequestException(theRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SearchTotalModeEnum getTypeForRequestOrThrowInvalidRequestException(RequestDetails theRequest) {
|
||||||
|
String[] searchTotalModeVal = theRequest.getParameters().get(Constants.PARAM_SEARCH_TOTAL_MODE);
|
||||||
|
if (searchTotalModeVal != null && searchTotalModeVal.length > 0) {
|
||||||
|
return SearchTotalModeEnum.fromCode(searchTotalModeVal[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import ca.uhn.fhir.rest.annotation.*;
|
||||||
import ca.uhn.fhir.rest.param.*;
|
import ca.uhn.fhir.rest.param.*;
|
||||||
import ca.uhn.fhir.rest.api.SortSpec;
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.SearchTotalModeEnum;
|
||||||
|
|
||||||
public class ${className}ResourceProvider extends
|
public class ${className}ResourceProvider extends
|
||||||
## We have specialized base classes for RPs that handle certain resource types. These
|
## We have specialized base classes for RPs that handle certain resource types. These
|
||||||
|
@ -133,7 +134,9 @@ public class ${className}ResourceProvider extends
|
||||||
@ca.uhn.fhir.rest.annotation.Count
|
@ca.uhn.fhir.rest.annotation.Count
|
||||||
Integer theCount,
|
Integer theCount,
|
||||||
|
|
||||||
Set<SummaryEnum> theSummaryMode
|
SummaryEnum theSummaryMode,
|
||||||
|
|
||||||
|
SearchTotalModeEnum theSearchTotalMode
|
||||||
|
|
||||||
) {
|
) {
|
||||||
startRequest(theServletRequest);
|
startRequest(theServletRequest);
|
||||||
|
@ -156,6 +159,7 @@ public class ${className}ResourceProvider extends
|
||||||
paramMap.setSort(theSort);
|
paramMap.setSort(theSort);
|
||||||
paramMap.setCount(theCount);
|
paramMap.setCount(theCount);
|
||||||
paramMap.setSummaryMode(theSummaryMode);
|
paramMap.setSummaryMode(theSummaryMode);
|
||||||
|
paramMap.setSearchTotalMode(theSearchTotalMode);
|
||||||
|
|
||||||
getDao().translateRawParameters(theAdditionalRawParams, paramMap);
|
getDao().translateRawParameters(theAdditionalRawParams, paramMap);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue