Improve search param extraction flexibility (#6030)
* Allow extractor to extract values for Resource-level parameters also * Rename flag * spotless * Allow setting test-specific resource provider * Add tests * Move common mockings to setup --------- Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>
This commit is contained in:
parent
7b68c4d91d
commit
0c642b6113
|
@ -171,6 +171,9 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
private BaseRuntimeChildDefinition myCodeableReferenceConcept;
|
||||
private BaseRuntimeChildDefinition myCodeableReferenceReference;
|
||||
|
||||
// allow extraction of Resource-level search param values
|
||||
private boolean myExtractResourceLevelParams = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -186,9 +189,9 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
PartitionSettings thePartitionSettings,
|
||||
FhirContext theCtx,
|
||||
ISearchParamRegistry theSearchParamRegistry) {
|
||||
Validate.notNull(theStorageSettings);
|
||||
Validate.notNull(theCtx);
|
||||
Validate.notNull(theSearchParamRegistry);
|
||||
Objects.requireNonNull(theStorageSettings);
|
||||
Objects.requireNonNull(theCtx);
|
||||
Objects.requireNonNull(theSearchParamRegistry);
|
||||
|
||||
myStorageSettings = theStorageSettings;
|
||||
myContext = theCtx;
|
||||
|
@ -972,7 +975,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
mySearchParamRegistry = theSearchParamRegistry;
|
||||
}
|
||||
|
||||
private Collection<RuntimeSearchParam> getSearchParams(IBaseResource theResource) {
|
||||
@VisibleForTesting
|
||||
Collection<RuntimeSearchParam> getSearchParams(IBaseResource theResource) {
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
Collection<RuntimeSearchParam> retVal =
|
||||
mySearchParamRegistry.getActiveSearchParams(def.getName()).values();
|
||||
|
@ -1317,7 +1321,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
List<IPrimitiveType<Date>> values = extractValuesAsFhirDates(myTimingEventValueChild, theValue);
|
||||
|
||||
TreeSet<Date> dates = new TreeSet<>();
|
||||
TreeSet<String> dateStrings = new TreeSet<>();
|
||||
String firstValue = null;
|
||||
String finalValue = null;
|
||||
for (IPrimitiveType<Date> nextEvent : values) {
|
||||
|
@ -1397,7 +1400,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addNumber_Range(
|
||||
String theResourceType,
|
||||
Set<ResourceIndexedSearchParamNumber> theParams,
|
||||
|
@ -1612,7 +1614,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
// See the method javadoc for an explanation of this
|
||||
if (RuntimeSearchParamHelper.isResourceLevel(nextSpDef)) {
|
||||
if (!myExtractResourceLevelParams && RuntimeSearchParamHelper.isResourceLevel(nextSpDef)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1805,16 +1807,11 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
|
||||
public boolean shouldAttemptToSplitPath(String thePath) {
|
||||
if (getContext().getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R4)) {
|
||||
if (thePath.contains("|")) {
|
||||
return true;
|
||||
}
|
||||
return thePath.contains("|");
|
||||
} else {
|
||||
// DSTU 3 and below used "or" as well as "|"
|
||||
if (thePath.contains("|") || thePath.contains(" or ")) {
|
||||
return true;
|
||||
}
|
||||
return thePath.contains("|") || thePath.contains(" or ");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1830,10 +1827,9 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
*/
|
||||
private String[] splitOutOfParensOrs(String thePaths) {
|
||||
List<String> topLevelOrExpressions = splitOutOfParensToken(thePaths, " or ");
|
||||
List<String> retVal = topLevelOrExpressions.stream()
|
||||
return topLevelOrExpressions.stream()
|
||||
.flatMap(s -> splitOutOfParensToken(s, " |").stream())
|
||||
.collect(Collectors.toList());
|
||||
return retVal.toArray(new String[retVal.size()]);
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
private List<String> splitOutOfParensToken(String thePath, String theToken) {
|
||||
|
@ -2018,8 +2014,9 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
List<? extends IBase> get() throws FHIRException;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@FunctionalInterface
|
||||
private interface IExtractor<T> {
|
||||
interface IExtractor<T> {
|
||||
|
||||
void extract(
|
||||
SearchParamSet<T> theParams,
|
||||
|
@ -2052,7 +2049,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
.findFirst();
|
||||
|
||||
// if the SP doesn't care, use the system default.
|
||||
if (!noSuppressForSearchParam.isPresent()) {
|
||||
if (noSuppressForSearchParam.isEmpty()) {
|
||||
return !theStorageSettings.isSuppressStringIndexingInTokens();
|
||||
// If the SP does care, use its value.
|
||||
} else {
|
||||
|
@ -2427,7 +2424,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
// DSTU2 only
|
||||
if (value instanceof BoundCodeDt) {
|
||||
BoundCodeDt boundCode = (BoundCodeDt) value;
|
||||
Enum valueAsEnum = boundCode.getValueAsEnum();
|
||||
Enum<?> valueAsEnum = boundCode.getValueAsEnum();
|
||||
String system = null;
|
||||
if (valueAsEnum != null) {
|
||||
//noinspection unchecked
|
||||
|
@ -2535,4 +2532,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
myExtractor1.extract(theParams, theSearchParam, theValue, thePath, theWantLocalReferences);
|
||||
}
|
||||
}
|
||||
|
||||
public void setExtractResourceLevelParams(boolean theExtractResourceLevelParams) {
|
||||
myExtractResourceLevelParams = theExtractResourceLevelParams;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
|
||||
import ca.uhn.fhir.jpa.model.entity.StorageSettings;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import static ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService.handleWarnings;
|
||||
|
||||
public class SearchParamExtractionUtil {
|
||||
|
||||
private final FhirContext myFhirContext;
|
||||
private final StorageSettings myStorageSettings;
|
||||
private final ISearchParamExtractor mySearchParamExtractor;
|
||||
private final IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
|
||||
public SearchParamExtractionUtil(
|
||||
FhirContext theFhirContext,
|
||||
StorageSettings theStorageSettings,
|
||||
ISearchParamExtractor theSearchParamExtractor,
|
||||
IInterceptorBroadcaster theInterceptorBroadcaster) {
|
||||
myFhirContext = theFhirContext;
|
||||
myStorageSettings = theStorageSettings;
|
||||
mySearchParamExtractor = theSearchParamExtractor;
|
||||
myInterceptorBroadcaster = theInterceptorBroadcaster;
|
||||
}
|
||||
|
||||
public void extractSearchIndexParameters(
|
||||
RequestDetails theRequestDetails,
|
||||
ResourceIndexedSearchParams theParams,
|
||||
IBaseResource theResource,
|
||||
@Nonnull ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
|
||||
// Strings
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> strings =
|
||||
extractSearchParamStrings(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, strings);
|
||||
theParams.myStringParams.addAll(strings);
|
||||
|
||||
// Numbers
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> numbers =
|
||||
extractSearchParamNumber(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, numbers);
|
||||
theParams.myNumberParams.addAll(numbers);
|
||||
|
||||
// Quantities
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> quantities =
|
||||
extractSearchParamQuantity(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantities);
|
||||
theParams.myQuantityParams.addAll(quantities);
|
||||
|
||||
if (myStorageSettings
|
||||
.getNormalizedQuantitySearchLevel()
|
||||
.equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED)
|
||||
|| myStorageSettings
|
||||
.getNormalizedQuantitySearchLevel()
|
||||
.equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED)) {
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantityNormalized> quantitiesNormalized =
|
||||
extractSearchParamQuantityNormalized(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantitiesNormalized);
|
||||
theParams.myQuantityNormalizedParams.addAll(quantitiesNormalized);
|
||||
}
|
||||
|
||||
// Dates
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> dates =
|
||||
extractSearchParamDates(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, dates);
|
||||
theParams.myDateParams.addAll(dates);
|
||||
|
||||
// URIs
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> uris =
|
||||
extractSearchParamUri(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, uris);
|
||||
theParams.myUriParams.addAll(uris);
|
||||
|
||||
// Tokens (can result in both Token and String, as we index the display name for
|
||||
// the types: Coding, CodeableConcept)
|
||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> tokens =
|
||||
extractSearchParamTokens(theResource, theSearchParamFilter);
|
||||
for (BaseResourceIndexedSearchParam next : tokens) {
|
||||
if (next instanceof ResourceIndexedSearchParamToken) {
|
||||
theParams.myTokenParams.add((ResourceIndexedSearchParamToken) next);
|
||||
} else if (next instanceof ResourceIndexedSearchParamCoords) {
|
||||
theParams.myCoordsParams.add((ResourceIndexedSearchParamCoords) next);
|
||||
} else {
|
||||
theParams.myStringParams.add((ResourceIndexedSearchParamString) next);
|
||||
}
|
||||
}
|
||||
|
||||
// Composites
|
||||
// dst2 composites use stuff like value[x] , and we don't support them.
|
||||
if (myFhirContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamComposite> composites =
|
||||
extractSearchParamComposites(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, composites);
|
||||
theParams.myCompositeParams.addAll(composites);
|
||||
}
|
||||
|
||||
// Specials
|
||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> specials =
|
||||
extractSearchParamSpecial(theResource, theSearchParamFilter);
|
||||
for (BaseResourceIndexedSearchParam next : specials) {
|
||||
if (next instanceof ResourceIndexedSearchParamCoords) {
|
||||
theParams.myCoordsParams.add((ResourceIndexedSearchParamCoords) next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> extractSearchParamDates(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamDates(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamNumber(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamQuantity(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantityNormalized>
|
||||
extractSearchParamQuantityNormalized(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamQuantityNormalized(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> extractSearchParamStrings(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamStrings(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamTokens(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamSpecial(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamSpecial(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> extractSearchParamUri(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamUri(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamComposite> extractSearchParamComposites(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamComposites(theResource, theSearchParamFilter);
|
||||
}
|
||||
}
|
|
@ -20,7 +20,6 @@
|
|||
package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
|
@ -34,17 +33,9 @@ import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
|||
import ca.uhn.fhir.jpa.model.entity.BasePartitionable;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.IResourceIndexComboSearchParameter;
|
||||
import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.SearchParamPresentEntity;
|
||||
|
@ -107,6 +98,8 @@ public class SearchParamExtractorService {
|
|||
@Autowired(required = false)
|
||||
private IResourceLinkResolver myResourceLinkResolver;
|
||||
|
||||
private SearchParamExtractionUtil mySearchParamExtractionUtil;
|
||||
|
||||
@VisibleForTesting
|
||||
public void setSearchParamExtractor(ISearchParamExtractor theSearchParamExtractor) {
|
||||
mySearchParamExtractor = theSearchParamExtractor;
|
||||
|
@ -150,7 +143,8 @@ public class SearchParamExtractorService {
|
|||
@Nonnull ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
// All search parameter types except Reference
|
||||
ResourceIndexedSearchParams normalParams = ResourceIndexedSearchParams.withSets();
|
||||
extractSearchIndexParameters(theRequestDetails, normalParams, theResource, theSearchParamFilter);
|
||||
getExtractionUtil()
|
||||
.extractSearchIndexParameters(theRequestDetails, normalParams, theResource, theSearchParamFilter);
|
||||
mergeParams(normalParams, theNewParams);
|
||||
|
||||
boolean indexOnContainedResources = myStorageSettings.isIndexOnContainedResources();
|
||||
|
@ -234,6 +228,14 @@ public class SearchParamExtractorService {
|
|||
theNewParams.setUpdatedTime(theTransactionDetails.getTransactionDate());
|
||||
}
|
||||
|
||||
private SearchParamExtractionUtil getExtractionUtil() {
|
||||
if (mySearchParamExtractionUtil == null) {
|
||||
mySearchParamExtractionUtil = new SearchParamExtractionUtil(
|
||||
myContext, myStorageSettings, mySearchParamExtractor, myInterceptorBroadcaster);
|
||||
}
|
||||
return mySearchParamExtractionUtil;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Map<String, Boolean> getReferenceSearchParamPresenceMap(
|
||||
ResourceTable entity, ResourceIndexedSearchParams newParams) {
|
||||
|
@ -430,7 +432,8 @@ public class SearchParamExtractorService {
|
|||
ResourceIndexedSearchParams currParams = ResourceIndexedSearchParams.withSets();
|
||||
|
||||
// 3.3 create indexes for the current contained resource
|
||||
extractSearchIndexParameters(theRequestDetails, currParams, targetResource, searchParamsToIndex);
|
||||
getExtractionUtil()
|
||||
.extractSearchIndexParameters(theRequestDetails, currParams, targetResource, searchParamsToIndex);
|
||||
|
||||
// 3.4 recurse to process any other contained resources referenced by this one
|
||||
// Recursing is currently only allowed for contained resources and not
|
||||
|
@ -490,87 +493,6 @@ public class SearchParamExtractorService {
|
|||
theTargetParams.myCompositeParams.addAll(theSrcParams.myCompositeParams);
|
||||
}
|
||||
|
||||
void extractSearchIndexParameters(
|
||||
RequestDetails theRequestDetails,
|
||||
ResourceIndexedSearchParams theParams,
|
||||
IBaseResource theResource,
|
||||
@Nonnull ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
|
||||
// Strings
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> strings =
|
||||
extractSearchParamStrings(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, strings);
|
||||
theParams.myStringParams.addAll(strings);
|
||||
|
||||
// Numbers
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> numbers =
|
||||
extractSearchParamNumber(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, numbers);
|
||||
theParams.myNumberParams.addAll(numbers);
|
||||
|
||||
// Quantities
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> quantities =
|
||||
extractSearchParamQuantity(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantities);
|
||||
theParams.myQuantityParams.addAll(quantities);
|
||||
|
||||
if (myStorageSettings
|
||||
.getNormalizedQuantitySearchLevel()
|
||||
.equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED)
|
||||
|| myStorageSettings
|
||||
.getNormalizedQuantitySearchLevel()
|
||||
.equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED)) {
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantityNormalized> quantitiesNormalized =
|
||||
extractSearchParamQuantityNormalized(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantitiesNormalized);
|
||||
theParams.myQuantityNormalizedParams.addAll(quantitiesNormalized);
|
||||
}
|
||||
|
||||
// Dates
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> dates =
|
||||
extractSearchParamDates(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, dates);
|
||||
theParams.myDateParams.addAll(dates);
|
||||
|
||||
// URIs
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> uris =
|
||||
extractSearchParamUri(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, uris);
|
||||
theParams.myUriParams.addAll(uris);
|
||||
|
||||
// Tokens (can result in both Token and String, as we index the display name for
|
||||
// the types: Coding, CodeableConcept)
|
||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> tokens =
|
||||
extractSearchParamTokens(theResource, theSearchParamFilter);
|
||||
for (BaseResourceIndexedSearchParam next : tokens) {
|
||||
if (next instanceof ResourceIndexedSearchParamToken) {
|
||||
theParams.myTokenParams.add((ResourceIndexedSearchParamToken) next);
|
||||
} else if (next instanceof ResourceIndexedSearchParamCoords) {
|
||||
theParams.myCoordsParams.add((ResourceIndexedSearchParamCoords) next);
|
||||
} else {
|
||||
theParams.myStringParams.add((ResourceIndexedSearchParamString) next);
|
||||
}
|
||||
}
|
||||
|
||||
// Composites
|
||||
// dst2 composites use stuff like value[x] , and we don't support them.
|
||||
if (myContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamComposite> composites =
|
||||
extractSearchParamComposites(theResource, theSearchParamFilter);
|
||||
handleWarnings(theRequestDetails, myInterceptorBroadcaster, composites);
|
||||
theParams.myCompositeParams.addAll(composites);
|
||||
}
|
||||
|
||||
// Specials
|
||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> specials =
|
||||
extractSearchParamSpecial(theResource, theSearchParamFilter);
|
||||
for (BaseResourceIndexedSearchParam next : specials) {
|
||||
if (next instanceof ResourceIndexedSearchParamCoords) {
|
||||
theParams.myCoordsParams.add((ResourceIndexedSearchParamCoords) next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void populateResourceTables(ResourceIndexedSearchParams theParams, ResourceTable theEntity) {
|
||||
|
||||
populateResourceTable(theParams.myNumberParams, theEntity);
|
||||
|
@ -643,7 +565,7 @@ public class SearchParamExtractorService {
|
|||
}
|
||||
}
|
||||
|
||||
theEntity.setHasLinks(theNewParams.myLinks.size() > 0);
|
||||
theEntity.setHasLinks(!theNewParams.myLinks.isEmpty());
|
||||
}
|
||||
|
||||
private void extractResourceLinks(
|
||||
|
@ -1100,52 +1022,6 @@ public class SearchParamExtractorService {
|
|||
}
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> extractSearchParamDates(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamDates(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamNumber(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamQuantity(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantityNormalized>
|
||||
extractSearchParamQuantityNormalized(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamQuantityNormalized(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> extractSearchParamStrings(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamStrings(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamTokens(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamSpecial(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamSpecial(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> extractSearchParamUri(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamUri(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamComposite> extractSearchParamComposites(
|
||||
IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
|
||||
return mySearchParamExtractor.extractSearchParamComposites(theResource, theSearchParamFilter);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setInterceptorBroadcasterForUnitTest(IInterceptorBroadcaster theInterceptorBroadcaster) {
|
||||
myInterceptorBroadcaster = theInterceptorBroadcaster;
|
||||
|
|
|
@ -1,18 +1,87 @@
|
|||
package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.StorageSettings;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class BaseSearchParamExtractorTest {
|
||||
|
||||
@Test
|
||||
public void testSplitPathsR4() {
|
||||
void testSplitPathsR4() {
|
||||
List<String> tokens = Arrays.asList(BaseSearchParamExtractor.splitPathsR4(" aaa | bbb + '|' | ccc ddd "));
|
||||
assertThat(tokens).containsExactly("aaa", "bbb + '|'", "ccc ddd");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ExtractResourceLevelParams {
|
||||
|
||||
@Spy
|
||||
BaseSearchParamExtractor myExtractor;
|
||||
|
||||
@Mock
|
||||
IBaseResource myResource;
|
||||
|
||||
@Mock
|
||||
RestSearchParameterTypeEnum mySearchParamType;
|
||||
|
||||
@Mock
|
||||
ISearchParamExtractor.ISearchParamFilter mySearchParamFilter;
|
||||
|
||||
@Mock
|
||||
RuntimeSearchParam myRuntimeSearchParam;
|
||||
|
||||
@Mock
|
||||
StorageSettings myStorageSettings;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
myExtractor.setStorageSettings(myStorageSettings);
|
||||
doReturn(List.of(myRuntimeSearchParam)).when(myExtractor).getSearchParams(myResource);
|
||||
when(mySearchParamFilter.filterSearchParams(any())).thenReturn(List.of(myRuntimeSearchParam));
|
||||
when(myRuntimeSearchParam.getParamType()).thenReturn(mySearchParamType);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhenSet_resourceLevelParamsAreExtracted() {
|
||||
myExtractor.setExtractResourceLevelParams(true);
|
||||
doNothing().when(myExtractor).extractSearchParam(any(), any(), any(), any(), eq(false));
|
||||
|
||||
// execute
|
||||
myExtractor.extractSearchParams(myResource, null, mySearchParamType, false, mySearchParamFilter);
|
||||
|
||||
verify(myExtractor).extractSearchParam(any(), any(), any(), any(), eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhenNotSet_resourceLevelParamsAreNotExtracted() {
|
||||
when(myRuntimeSearchParam.getPath()).thenReturn("Resource.something");
|
||||
|
||||
// execute
|
||||
myExtractor.extractSearchParams(myResource, null, mySearchParamType, false, mySearchParamFilter);
|
||||
|
||||
verify(myExtractor, never()).extractSearchParam(any(), any(), any(), any(), eq(false));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,6 +208,10 @@ public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEa
|
|||
return myRestServer.getPatientResourceProvider();
|
||||
}
|
||||
|
||||
public void setPatientResourceProvider(HashMapResourceProvider<Patient> theResourceProvider) {
|
||||
myRestServer.setPatientResourceProvider(theResourceProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMapResourceProvider<ConceptMap> getConceptMapResourceProvider() {
|
||||
return myRestServer.getConceptMapResourceProvider();
|
||||
|
@ -387,6 +391,14 @@ public class RestServerR4Helper extends BaseRestServerHelper implements BeforeEa
|
|||
return myObservationResourceProvider;
|
||||
}
|
||||
|
||||
public void setPatientResourceProvider(HashMapResourceProvider<Patient> theResourceProvider) {
|
||||
myPatientResourceProvider.getStoredResources().forEach(theResourceProvider::store);
|
||||
|
||||
unregisterProvider(myPatientResourceProvider);
|
||||
registerProvider(theResourceProvider);
|
||||
myPatientResourceProvider = theResourceProvider;
|
||||
}
|
||||
|
||||
public void setObservationResourceProvider(HashMapResourceProvider<Observation> theResourceProvider) {
|
||||
myObservationResourceProvider.getStoredResources().forEach(theResourceProvider::store);
|
||||
|
||||
|
|
Loading…
Reference in New Issue