Compare commits
20 Commits
4a6b4fafac
...
cab366b6af
Author | SHA1 | Date |
---|---|---|
James Agnew | cab366b6af | |
volodymyr-korzh | fb7571185a | |
Tadgh | 919e2d2405 | |
James Agnew | 123867e86e | |
James Agnew | 2a3dacc1e5 | |
James Agnew | b094163e53 | |
James Agnew | 1468bc1b49 | |
James Agnew | c948ef4707 | |
James Agnew | bea1fbbb1a | |
James Agnew | 4e0ce372f7 | |
James Agnew | 9b730f509f | |
James Agnew | 96b496e967 | |
James Agnew | 3ee3932f68 | |
James Agnew | 9564541e5e | |
James Agnew | e844819114 | |
James Agnew | 94ebe4413f | |
James Agnew | 8a5e2679d5 | |
James Agnew | 6ed919de22 | |
James Agnew | c2ed5f8419 | |
James Agnew | 9143f5995b |
|
@ -60,6 +60,7 @@ public class RuntimeSearchParam {
|
|||
private final List<Component> myComponents;
|
||||
private final IIdType myIdUnqualifiedVersionless;
|
||||
private IPhoneticEncoder myPhoneticEncoder;
|
||||
private boolean myEnabledForSearching = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -166,6 +167,24 @@ public class RuntimeSearchParam {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this search parameter actually enabled for being used in searches (as opposed to only being used for
|
||||
* generating indexes, which might be desired while the search parameter is still being indexed). This
|
||||
* setting defaults to {@literal true} if it isn't set otherwise.
|
||||
*/
|
||||
public boolean isEnabledForSearching() {
|
||||
return myEnabledForSearching;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this search parameter actually enabled for being used in searches (as opposed to only being used for
|
||||
* generating indexes, which might be desired while the search parameter is still being indexed). This
|
||||
* setting defaults to {@literal true} if it isn't set otherwise.
|
||||
*/
|
||||
public void setEnabledForSearching(boolean theEnabledForSearching) {
|
||||
myEnabledForSearching = theEnabledForSearching;
|
||||
}
|
||||
|
||||
public List<Component> getComponents() {
|
||||
return myComponents;
|
||||
}
|
||||
|
@ -361,13 +380,6 @@ public class RuntimeSearchParam {
|
|||
return !myUpliftRefchains.isEmpty();
|
||||
}
|
||||
|
||||
public enum RuntimeSearchParamStatusEnum {
|
||||
ACTIVE,
|
||||
DRAFT,
|
||||
RETIRED,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
/**
|
||||
* This method tests whether a given FHIRPath expression <i>could</i>
|
||||
* possibly apply to the given resource type.
|
||||
|
@ -413,6 +425,13 @@ public class RuntimeSearchParam {
|
|||
return false;
|
||||
}
|
||||
|
||||
public enum RuntimeSearchParamStatusEnum {
|
||||
ACTIVE,
|
||||
DRAFT,
|
||||
RETIRED,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
public static class Component {
|
||||
private final String myExpression;
|
||||
private final String myReference;
|
||||
|
|
|
@ -110,6 +110,12 @@ public class HapiExtensions {
|
|||
|
||||
public static final String EXT_SP_UNIQUE = "http://hapifhir.io/fhir/StructureDefinition/sp-unique";
|
||||
|
||||
/**
|
||||
* URL for extension on a Search Parameter which determines whether it should be enabled for searching for resources
|
||||
*/
|
||||
public static final String EXT_SEARCHPARAM_ENABLED_FOR_SEARCHING =
|
||||
"http://hapifhir.io/fhir/StructureDefinition/searchparameter-enabled-for-searching";
|
||||
|
||||
/**
|
||||
* URL for extension on a Phonetic String SearchParameter indicating that text values should be phonetically indexed with the named encoder
|
||||
*/
|
||||
|
|
|
@ -133,6 +133,7 @@ ca.uhn.fhir.jpa.dao.BaseStorageDao.successfulTimingSuffix=Took {0}ms.
|
|||
ca.uhn.fhir.jpa.dao.BaseStorageDao.deleteResourceNotExisting=Not deleted, resource {0} does not exist.
|
||||
ca.uhn.fhir.jpa.dao.BaseStorageDao.deleteResourceAlreadyDeleted=Not deleted, resource {0} was already deleted.
|
||||
ca.uhn.fhir.jpa.dao.BaseStorageDao.invalidSearchParameter=Unknown search parameter "{0}" for resource type "{1}". Valid search parameters for this search are: {2}
|
||||
ca.uhn.fhir.jpa.dao.BaseStorageDao.invalidSearchParameterNotEnabledForSearch=Search parameter "{0}" for resource type "{1}" is not active for searching. Valid search parameters for this search are: {2}
|
||||
ca.uhn.fhir.jpa.dao.BaseStorageDao.invalidSortParameter=Unknown _sort parameter value "{0}" for resource type "{1}" (Note: sort parameters values must use a valid Search Parameter). Valid values for this search are: {2}
|
||||
ca.uhn.fhir.jpa.dao.BaseStorageDao.invalidSortParameterTooManyChains=Invalid _sort expression, can not chain more than once in a sort expression: {0}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: add
|
||||
issue: 6107
|
||||
title: "A new extension has been created for use on SearchParameter resources in the JPA server. This extension causes
|
||||
a SearchParameter to be indexed, but to not be available for use in searches. This can be set when a new SP is created
|
||||
in order to prevent it from being used before an index has been completed."
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: change
|
||||
issue: 6261
|
||||
title: "Upgrading to Jakarta had caused a problem with the version of java-simple-mail that was in use. This has been updated to be conformant
|
||||
with the Jakarta Mail APIs. Thanks to Thomas Papke(@thopap) for the contribution!"
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 6317
|
||||
title: "Previously, defining a unique combo Search Parameter with the DateTime component and submitting multiple
|
||||
resources with the same dateTime element (e.g. Observation.effectiveDateTime) resulted in duplicate resource creation.
|
||||
This has been fixed."
|
||||
|
|
@ -625,7 +625,8 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor<JpaPid> {
|
|||
resourceToCheck = "Patient";
|
||||
activeSearchParamName = "organization";
|
||||
}
|
||||
return mySearchParamRegistry.getActiveSearchParam(resourceToCheck, activeSearchParamName);
|
||||
return mySearchParamRegistry.getActiveSearchParam(
|
||||
resourceToCheck, activeSearchParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -137,7 +137,8 @@ public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
|
|||
public ExtendedHSearchIndexData extractLuceneIndexData(
|
||||
IBaseResource theResource, ResourceIndexedSearchParams theNewParams) {
|
||||
String resourceType = myFhirContext.getResourceType(theResource);
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(resourceType);
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(
|
||||
resourceType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
ExtendedHSearchIndexExtractor extractor = new ExtendedHSearchIndexExtractor(
|
||||
myStorageSettings, myFhirContext, activeSearchParams, mySearchParamExtractor);
|
||||
return extractor.extract(theResource, theNewParams);
|
||||
|
|
|
@ -92,7 +92,8 @@ public class ExtendedHSearchSearchBuilder {
|
|||
String theResourceType, SearchParameterMap myParams, ISearchParamRegistry theSearchParamRegistry) {
|
||||
boolean canUseHibernate = false;
|
||||
|
||||
ResourceSearchParams resourceActiveSearchParams = theSearchParamRegistry.getActiveSearchParams(theResourceType);
|
||||
ResourceSearchParams resourceActiveSearchParams = theSearchParamRegistry.getActiveSearchParams(
|
||||
theResourceType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
for (String paramName : myParams.keySet()) {
|
||||
// is this parameter supported?
|
||||
if (illegalForHibernateSearch(paramName, resourceActiveSearchParams)) {
|
||||
|
@ -218,7 +219,8 @@ public class ExtendedHSearchSearchBuilder {
|
|||
|
||||
// copy the keys to avoid concurrent modification error
|
||||
ArrayList<String> paramNames = compileParamNames(searchParameterMap);
|
||||
ResourceSearchParams activeSearchParams = searchParamRegistry.getActiveSearchParams(resourceType);
|
||||
ResourceSearchParams activeSearchParams = searchParamRegistry.getActiveSearchParams(
|
||||
resourceType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
for (String nextParam : paramNames) {
|
||||
if (illegalForHibernateSearch(nextParam, activeSearchParams)) {
|
||||
// ignore magic params handled in JPA
|
||||
|
|
|
@ -151,7 +151,8 @@ public class HSearchSortHelperImpl implements IHSearchSortHelper {
|
|||
*/
|
||||
@VisibleForTesting
|
||||
Optional<RestSearchParameterTypeEnum> getParamType(String theResourceTypeName, String theParamName) {
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(theResourceTypeName);
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(
|
||||
theResourceTypeName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
RuntimeSearchParam searchParam = activeSearchParams.get(theParamName);
|
||||
if (searchParam == null) {
|
||||
return Optional.empty();
|
||||
|
|
|
@ -181,7 +181,8 @@ public class GraphQLProviderWithIntrospection extends GraphQLProvider {
|
|||
for (String nextResourceType : theResourceTypes) {
|
||||
StructureDefinition sd = fetchStructureDefinition(nextResourceType);
|
||||
List<SearchParameter> parameters = toR5SearchParams(mySearchParamRegistry
|
||||
.getActiveSearchParams(nextResourceType)
|
||||
.getActiveSearchParams(
|
||||
nextResourceType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.values());
|
||||
myGenerator.generateResource(writer, sd, parameters, theOperations);
|
||||
}
|
||||
|
@ -198,7 +199,8 @@ public class GraphQLProviderWithIntrospection extends GraphQLProvider {
|
|||
}
|
||||
if (theOperations.contains(GraphQLSchemaGenerator.FHIROperationType.SEARCH)) {
|
||||
List<SearchParameter> parameters = toR5SearchParams(mySearchParamRegistry
|
||||
.getActiveSearchParams(nextResourceType)
|
||||
.getActiveSearchParams(
|
||||
nextResourceType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.values());
|
||||
myGenerator.generateListAccessQuery(writer, parameters, nextResourceType);
|
||||
myGenerator.generateConnectionAccessQuery(writer, parameters, nextResourceType);
|
||||
|
|
|
@ -190,11 +190,12 @@ public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.se
|
|||
* global params like _lastUpdated
|
||||
*/
|
||||
ResourceSearchParams searchParams;
|
||||
ResourceSearchParams serverConfigurationActiveSearchParams =
|
||||
myServerConfiguration.getActiveSearchParams(theResourceName);
|
||||
ResourceSearchParams serverConfigurationActiveSearchParams = myServerConfiguration.getActiveSearchParams(
|
||||
theResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (mySearchParamRegistry != null) {
|
||||
searchParams =
|
||||
mySearchParamRegistry.getActiveSearchParams(theResourceName).makeCopy();
|
||||
searchParams = mySearchParamRegistry
|
||||
.getActiveSearchParams(theResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.makeCopy();
|
||||
if (searchParams == null) {
|
||||
return ResourceSearchParams.empty(theResourceName);
|
||||
}
|
||||
|
@ -229,8 +230,8 @@ public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.se
|
|||
if (isBlank(otherResourceType)) {
|
||||
continue;
|
||||
}
|
||||
ResourceSearchParams activeSearchParams =
|
||||
mySearchParamRegistry.getActiveSearchParams(otherResourceType);
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(
|
||||
otherResourceType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
activeSearchParams.values().stream()
|
||||
.filter(t -> isNotBlank(t.getName()))
|
||||
.filter(t -> t.getTargets().contains(resourcename))
|
||||
|
|
|
@ -489,8 +489,13 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc<JpaPid> {
|
|||
}
|
||||
|
||||
if (!Constants.INCLUDE_STAR.equals(paramName)
|
||||
&& mySearchParamRegistry.getActiveSearchParam(paramType, paramName) == null) {
|
||||
List<String> validNames = mySearchParamRegistry.getActiveSearchParams(paramType).values().stream()
|
||||
&& mySearchParamRegistry.getActiveSearchParam(
|
||||
paramType, paramName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
== null) {
|
||||
List<String> validNames = mySearchParamRegistry
|
||||
.getActiveSearchParams(paramType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.values()
|
||||
.stream()
|
||||
.filter(t -> t.getParamType() == RestSearchParameterTypeEnum.REFERENCE)
|
||||
.map(t -> UrlUtil.sanitizeUrlPart(t.getName()))
|
||||
.sorted()
|
||||
|
|
|
@ -315,7 +315,8 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
String targetType = null;
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceName, theParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (theReferenceTargetType != null) {
|
||||
targetType = theReferenceTargetType;
|
||||
} else if (param.getTargets().size() > 1) {
|
||||
|
@ -331,17 +332,20 @@ public class QueryStack {
|
|||
+ "' as this parameter as this parameter does not define a target type. Please specify the target type.");
|
||||
}
|
||||
|
||||
RuntimeSearchParam targetSearchParameter = mySearchParamRegistry.getActiveSearchParam(targetType, theChain);
|
||||
RuntimeSearchParam targetSearchParameter = mySearchParamRegistry.getActiveSearchParam(
|
||||
targetType, theChain, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (targetSearchParameter == null) {
|
||||
Collection<String> validSearchParameterNames =
|
||||
mySearchParamRegistry.getActiveSearchParams(targetType).values().stream()
|
||||
.filter(t -> t.getParamType() == RestSearchParameterTypeEnum.STRING
|
||||
|| t.getParamType() == RestSearchParameterTypeEnum.TOKEN
|
||||
|| t.getParamType() == RestSearchParameterTypeEnum.DATE)
|
||||
.map(RuntimeSearchParam::getName)
|
||||
.sorted()
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
Collection<String> validSearchParameterNames = mySearchParamRegistry
|
||||
.getActiveSearchParams(targetType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.values()
|
||||
.stream()
|
||||
.filter(t -> t.getParamType() == RestSearchParameterTypeEnum.STRING
|
||||
|| t.getParamType() == RestSearchParameterTypeEnum.TOKEN
|
||||
|| t.getParamType() == RestSearchParameterTypeEnum.DATE)
|
||||
.map(RuntimeSearchParam::getName)
|
||||
.sorted()
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
String msg = myFhirContext
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
|
@ -418,6 +422,7 @@ public class QueryStack {
|
|||
return;
|
||||
}
|
||||
}
|
||||
//noinspection fallthrough
|
||||
case NUMBER:
|
||||
case REFERENCE:
|
||||
case COMPOSITE:
|
||||
|
@ -1003,10 +1008,11 @@ public class QueryStack {
|
|||
return createPredicateSource(null, Collections.singletonList(param));
|
||||
}
|
||||
default:
|
||||
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramName);
|
||||
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceName, paramName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (searchParam == null) {
|
||||
Collection<String> validNames =
|
||||
mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName);
|
||||
Collection<String> validNames = mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(
|
||||
theResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
String msg = myFhirContext
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
|
@ -1164,13 +1170,14 @@ public class QueryStack {
|
|||
// Ensure that the name of the search param
|
||||
// (e.g. the `code` in Patient?_has:Observation:subject:code=sys|val)
|
||||
// exists on the target resource type.
|
||||
RuntimeSearchParam owningParameterDef =
|
||||
mySearchParamRegistry.getRuntimeSearchParam(targetResourceType, paramName);
|
||||
RuntimeSearchParam owningParameterDef = mySearchParamRegistry.getRuntimeSearchParam(
|
||||
targetResourceType, paramName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
// Ensure that the name of the back-referenced search param on the target (e.g. the `subject` in
|
||||
// Patient?_has:Observation:subject:code=sys|val)
|
||||
// exists on the target resource, or in the top-level Resource resource.
|
||||
mySearchParamRegistry.getRuntimeSearchParam(targetResourceType, paramReference);
|
||||
mySearchParamRegistry.getRuntimeSearchParam(
|
||||
targetResourceType, paramReference, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
IQueryParameterAnd<?> parsedParam = JpaParamUtil.parseQueryParams(
|
||||
mySearchParamRegistry, myFhirContext, owningParameterDef, paramName, parameters);
|
||||
|
@ -1360,7 +1367,7 @@ public class QueryStack {
|
|||
theRequestPartitionId));
|
||||
} else {
|
||||
List<QuantityParam> quantityParams =
|
||||
theList.stream().map(t -> QuantityParam.toQuantityParam(t)).collect(Collectors.toList());
|
||||
theList.stream().map(QuantityParam::toQuantityParam).collect(Collectors.toList());
|
||||
|
||||
BaseQuantityPredicateBuilder join = null;
|
||||
boolean normalizedSearchEnabled = myStorageSettings
|
||||
|
@ -1368,8 +1375,8 @@ public class QueryStack {
|
|||
.equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED);
|
||||
if (normalizedSearchEnabled) {
|
||||
List<QuantityParam> normalizedQuantityParams = quantityParams.stream()
|
||||
.map(t -> UcumServiceUtil.toCanonicalQuantityOrNull(t))
|
||||
.filter(t -> t != null)
|
||||
.map(UcumServiceUtil::toCanonicalQuantityOrNull)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (normalizedQuantityParams.size() == quantityParams.size()) {
|
||||
|
@ -2455,7 +2462,8 @@ public class QueryStack {
|
|||
RequestDetails theRequest,
|
||||
RequestPartitionId theRequestPartitionId) {
|
||||
List<Condition> andPredicates = new ArrayList<>();
|
||||
RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
|
||||
RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceName, theParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (nextParamDef != null) {
|
||||
|
||||
if (myPartitionSettings.isPartitioningEnabled() && myPartitionSettings.isIncludePartitionInSearchHashes()) {
|
||||
|
@ -2662,15 +2670,33 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
} else {
|
||||
String msg = myFhirContext
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
BaseStorageDao.class,
|
||||
"invalidSearchParameter",
|
||||
theParamName,
|
||||
theResourceName,
|
||||
mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName));
|
||||
throw new InvalidRequestException(Msg.code(1223) + msg);
|
||||
RuntimeSearchParam notEnabledForSearchParam =
|
||||
mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName, null);
|
||||
if (notEnabledForSearchParam == null) {
|
||||
String msg = myFhirContext
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
BaseStorageDao.class,
|
||||
"invalidSearchParameter",
|
||||
theParamName,
|
||||
theResourceName,
|
||||
mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(
|
||||
theResourceName,
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH));
|
||||
throw new InvalidRequestException(Msg.code(1223) + msg);
|
||||
} else {
|
||||
String msg = myFhirContext
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
BaseStorageDao.class,
|
||||
"invalidSearchParameterNotEnabledForSearch",
|
||||
theParamName,
|
||||
theResourceName,
|
||||
mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(
|
||||
theResourceName,
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH));
|
||||
throw new InvalidRequestException(Msg.code(2540) + msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2701,8 +2727,8 @@ public class QueryStack {
|
|||
ReferenceParam param = (ReferenceParam) nextAnd.get(0);
|
||||
if (isNotBlank(param.getChain())) {
|
||||
String fullName = theParamName + "." + param.getChain();
|
||||
RuntimeSearchParam fullChainParam =
|
||||
mySearchParamRegistry.getActiveSearchParam(theResourceName, fullName);
|
||||
RuntimeSearchParam fullChainParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceName, fullName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (fullChainParam != null) {
|
||||
List<IQueryParameterType> swappedParamTypes = nextAnd.stream()
|
||||
.map(t -> newParameterInstance(fullChainParam, null, t.getValueAsQueryToken(myFhirContext)))
|
||||
|
@ -2769,8 +2795,10 @@ public class QueryStack {
|
|||
if (indexOnContainedResources) {
|
||||
return true;
|
||||
}
|
||||
RuntimeSearchParam param =
|
||||
mySearchParamRegistry.getActiveSearchParam(theResourceType, theParameterName);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceType,
|
||||
theParameterName,
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
return param != null && param.hasUpliftRefchain(t);
|
||||
});
|
||||
|
||||
|
@ -3010,7 +3038,8 @@ public class QueryStack {
|
|||
for (String nextTarget : thePreviousSearchParam.getTargets()) {
|
||||
RuntimeSearchParam nextSearchParam = null;
|
||||
if (isBlank(theResourceType) || theResourceType.equals(nextTarget)) {
|
||||
nextSearchParam = mySearchParamRegistry.getActiveSearchParam(nextTarget, nextParamName);
|
||||
nextSearchParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
nextTarget, nextParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
}
|
||||
if (nextSearchParam != null) {
|
||||
searchParamFound = true;
|
||||
|
|
|
@ -651,8 +651,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
|| theParams.getSort() != null
|
||||
|| theParams.keySet().contains(Constants.PARAM_HAS)
|
||||
|| isPotentiallyContainedReferenceParameterExistsAtRoot(theParams)) {
|
||||
List<RuntimeSearchParam> activeComboParams =
|
||||
mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet());
|
||||
List<RuntimeSearchParam> activeComboParams = mySearchParamRegistry.getActiveComboSearchParams(
|
||||
myResourceName, theParams.keySet(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (activeComboParams.isEmpty()) {
|
||||
sqlBuilder.setNeedResourceTableRoot(true);
|
||||
}
|
||||
|
@ -915,8 +915,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
theQueryStack.addSortOnLastUpdated(ascending);
|
||||
|
||||
} else {
|
||||
RuntimeSearchParam param =
|
||||
mySearchParamRegistry.getActiveSearchParam(myResourceName, theSort.getParamName());
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(
|
||||
myResourceName, theSort.getParamName(), ISearchParamRegistry.SearchParamLookupContextEnum.SORT);
|
||||
|
||||
/*
|
||||
* If we have a sort like _sort=subject.name and we have an
|
||||
|
@ -940,8 +940,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
referenceParamTargetType = referenceParam.substring(0, colonIdx);
|
||||
referenceParam = referenceParam.substring(colonIdx + 1);
|
||||
}
|
||||
RuntimeSearchParam outerParam =
|
||||
mySearchParamRegistry.getActiveSearchParam(myResourceName, referenceParam);
|
||||
RuntimeSearchParam outerParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
myResourceName, referenceParam, ISearchParamRegistry.SearchParamLookupContextEnum.SORT);
|
||||
if (outerParam == null) {
|
||||
throwInvalidRequestExceptionForUnknownSortParameter(myResourceName, referenceParam);
|
||||
} else if (outerParam.hasUpliftRefchain(targetParam)) {
|
||||
|
@ -949,8 +949,10 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
if (referenceParamTargetType != null && !referenceParamTargetType.equals(nextTargetType)) {
|
||||
continue;
|
||||
}
|
||||
RuntimeSearchParam innerParam =
|
||||
mySearchParamRegistry.getActiveSearchParam(nextTargetType, targetParam);
|
||||
RuntimeSearchParam innerParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
nextTargetType,
|
||||
targetParam,
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.SORT);
|
||||
if (innerParam != null) {
|
||||
param = innerParam;
|
||||
break;
|
||||
|
@ -984,7 +986,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
}
|
||||
|
||||
if (param == null) {
|
||||
param = mySearchParamRegistry.getActiveSearchParam(myResourceName, paramName);
|
||||
param = mySearchParamRegistry.getActiveSearchParam(
|
||||
myResourceName, paramName, ISearchParamRegistry.SearchParamLookupContextEnum.SORT);
|
||||
}
|
||||
|
||||
if (param == null) {
|
||||
|
@ -1063,8 +1066,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
}
|
||||
|
||||
private void throwInvalidRequestExceptionForUnknownSortParameter(String theResourceName, String theParamName) {
|
||||
Collection<String> validSearchParameterNames =
|
||||
mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName);
|
||||
Collection<String> validSearchParameterNames = mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(
|
||||
theResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SORT);
|
||||
String msg = myContext
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
|
@ -1527,7 +1530,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
|
||||
String paramName = nextInclude.getParamName();
|
||||
if (isNotBlank(paramName)) {
|
||||
param = mySearchParamRegistry.getActiveSearchParam(resType, paramName);
|
||||
param = mySearchParamRegistry.getActiveSearchParam(
|
||||
resType, paramName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
} else {
|
||||
param = null;
|
||||
}
|
||||
|
@ -1845,7 +1849,10 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
// in this context, so let's just assume it could be anything.
|
||||
targetResourceTypes = possibleTypes;
|
||||
} else {
|
||||
for (var next : mySearchParamRegistry.getActiveSearchParams(myResourceName).values().stream()
|
||||
for (var next : mySearchParamRegistry
|
||||
.getActiveSearchParams(myResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.values()
|
||||
.stream()
|
||||
.filter(t -> t.getParamType().equals(RestSearchParameterTypeEnum.REFERENCE))
|
||||
.collect(Collectors.toList())) {
|
||||
|
||||
|
@ -1928,16 +1935,16 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
QueryStack theQueryStack, @Nonnull SearchParameterMap theParams, RequestDetails theRequest) {
|
||||
RuntimeSearchParam comboParam = null;
|
||||
List<String> comboParamNames = null;
|
||||
List<RuntimeSearchParam> exactMatchParams =
|
||||
mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet());
|
||||
List<RuntimeSearchParam> exactMatchParams = mySearchParamRegistry.getActiveComboSearchParams(
|
||||
myResourceName, theParams.keySet(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (!exactMatchParams.isEmpty()) {
|
||||
comboParam = exactMatchParams.get(0);
|
||||
comboParamNames = new ArrayList<>(theParams.keySet());
|
||||
}
|
||||
|
||||
if (comboParam == null) {
|
||||
List<RuntimeSearchParam> candidateComboParams =
|
||||
mySearchParamRegistry.getActiveComboSearchParams(myResourceName);
|
||||
List<RuntimeSearchParam> candidateComboParams = mySearchParamRegistry.getActiveComboSearchParams(
|
||||
myResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
for (RuntimeSearchParam nextCandidate : candidateComboParams) {
|
||||
List<String> nextCandidateParamNames =
|
||||
JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, nextCandidate).stream()
|
||||
|
@ -1972,7 +1979,7 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
* The loop allows us to create multiple combo index joins if there
|
||||
* are multiple AND expressions for the related parameters.
|
||||
*/
|
||||
while (validateParamValuesAreValidForComboParam(theRequest, theParams, comboParamNames)) {
|
||||
while (validateParamValuesAreValidForComboParam(theRequest, theParams, comboParamNames, comboParam)) {
|
||||
applyComboSearchParam(theQueryStack, theParams, theRequest, comboParamNames, comboParam);
|
||||
}
|
||||
}
|
||||
|
@ -2006,8 +2013,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
IQueryParameterType nextOr = nextPermutation.get(paramIndex);
|
||||
String nextOrValue = nextOr.getValueAsQueryToken(myContext);
|
||||
|
||||
RuntimeSearchParam nextParamDef =
|
||||
mySearchParamRegistry.getActiveSearchParam(myResourceName, nextParamName);
|
||||
RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(
|
||||
myResourceName, nextParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (theComboParam.getComboSearchParamType() == ComboSearchParamType.NON_UNIQUE) {
|
||||
if (nextParamDef.getParamType() == RestSearchParameterTypeEnum.STRING) {
|
||||
nextOrValue = StringUtil.normalizeStringForSearchIndexing(nextOrValue);
|
||||
|
@ -2068,7 +2075,10 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
* (e.g. <code>?date=gt2024-02-01</code>), etc.
|
||||
*/
|
||||
private boolean validateParamValuesAreValidForComboParam(
|
||||
RequestDetails theRequest, @Nonnull SearchParameterMap theParams, List<String> theComboParamNames) {
|
||||
RequestDetails theRequest,
|
||||
@Nonnull SearchParameterMap theParams,
|
||||
List<String> theComboParamNames,
|
||||
RuntimeSearchParam theComboParam) {
|
||||
boolean paramValuesAreValidForCombo = true;
|
||||
List<List<IQueryParameterType>> paramOrValues = new ArrayList<>(theComboParamNames.size());
|
||||
|
||||
|
@ -2119,7 +2129,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
|
||||
// Reference params are only eligible for using a composite index if they
|
||||
// are qualified
|
||||
RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(myResourceName, nextParamName);
|
||||
RuntimeSearchParam nextParamDef = mySearchParamRegistry.getActiveSearchParam(
|
||||
myResourceName, nextParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (nextParamDef.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
||||
ReferenceParam param = (ReferenceParam) nextValues.get(0).get(0);
|
||||
if (isBlank(param.getResourceType())) {
|
||||
|
@ -2129,6 +2140,19 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Date params are not eligible for using composite unique index
|
||||
// as index could contain date with different precision (e.g. DAY, SECOND)
|
||||
if (nextParamDef.getParamType() == RestSearchParameterTypeEnum.DATE
|
||||
&& theComboParam.getComboSearchParamType() == ComboSearchParamType.UNIQUE) {
|
||||
ourLog.debug(
|
||||
"Search with params {} is not a candidate for combo searching - "
|
||||
+ "Unique combo search parameter '{}' has DATE type",
|
||||
theComboParamNames,
|
||||
nextParamName);
|
||||
paramValuesAreValidForCombo = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (CartesianProductUtil.calculateCartesianProductSize(paramOrValues) > 500) {
|
||||
|
|
|
@ -466,7 +466,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
|
||||
RuntimeSearchParam param = null;
|
||||
if (!isMeta) {
|
||||
param = mySearchParamRegistry.getActiveSearchParam(nextType, chain);
|
||||
param = mySearchParamRegistry.getActiveSearchParam(
|
||||
nextType, chain, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (param == null) {
|
||||
ourLog.debug("Type {} doesn't have search param {}", nextType, param);
|
||||
continue;
|
||||
|
@ -555,8 +556,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
resourceTypes = determineResourceTypes(Collections.singleton(theResourceName), theParamName);
|
||||
|
||||
if (resourceTypes.isEmpty()) {
|
||||
RuntimeSearchParam searchParamByName =
|
||||
mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
|
||||
RuntimeSearchParam searchParamByName = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceName, theParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (searchParamByName == null) {
|
||||
throw new InternalErrorException(Msg.code(1244) + "Could not find parameter " + theParamName);
|
||||
}
|
||||
|
@ -628,7 +629,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
if (linkIndex == -1) {
|
||||
Set<Class<? extends IBaseResource>> resourceTypes = new HashSet<>();
|
||||
for (String resourceName : theResourceNames) {
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(resourceName, theParamNameChain);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(
|
||||
resourceName, theParamNameChain, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
if (param != null && param.hasTargets()) {
|
||||
Set<String> targetTypes = param.getTargets();
|
||||
|
@ -644,7 +646,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
String paramNameTail = theParamNameChain.substring(linkIndex + 1);
|
||||
Set<String> targetResourceTypeNames = new HashSet<>();
|
||||
for (String resourceName : theResourceNames) {
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(resourceName, paramNameHead);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(
|
||||
resourceName, paramNameHead, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
if (param != null && param.hasTargets()) {
|
||||
targetResourceTypeNames.addAll(param.getTargets());
|
||||
|
@ -656,7 +659,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
|
||||
public List<String> createResourceLinkPaths(
|
||||
String theResourceName, String theParamName, List<String> theParamQualifiers) {
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceName, theParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (param != null) {
|
||||
List<String> path = param.getPathsSplit();
|
||||
|
||||
|
@ -687,7 +691,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
|
|||
? theParamQualifiers.subList(1, theParamQualifiers.size())
|
||||
: List.of();
|
||||
|
||||
param = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramNameHead);
|
||||
param = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceName, paramNameHead, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (param != null) {
|
||||
Set<String> tailPaths = param.getTargets().stream()
|
||||
.filter(t -> isBlank(qualifier) || qualifier.equals(t))
|
||||
|
|
|
@ -441,7 +441,7 @@ public class InstanceReindexServiceImpl implements IInstanceReindexService {
|
|||
private void fillInParamNames(
|
||||
ResourceTable theEntity, Collection<SearchParamPresentEntity> theTarget, String theResourceName) {
|
||||
Map<Long, String> hashes = new HashMap<>();
|
||||
ResourceSearchParams searchParams = mySearchParamRegistry.getActiveSearchParams(theResourceName);
|
||||
ResourceSearchParams searchParams = mySearchParamRegistry.getActiveSearchParams(theResourceName, null);
|
||||
for (RuntimeSearchParam next : searchParams.values()) {
|
||||
hashes.put(
|
||||
SearchParamPresentEntity.calculateHashPresence(
|
||||
|
|
|
@ -423,7 +423,7 @@ public class JpaBulkExportProcessorTest {
|
|||
|
||||
// when
|
||||
RuntimeSearchParam searchParam = new RuntimeSearchParam(new IdType("1"), "", "", "", "", RestSearchParameterTypeEnum.STRING, Collections.singleton(""), Collections.singleton(""), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, Collections.singleton(""));
|
||||
when(mySearchParamRegistry.getActiveSearchParam(any(), any())).thenReturn(searchParam);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(any(), any(), any())).thenReturn(searchParam);
|
||||
// expandAllPatientPidsFromGroup
|
||||
when(myDaoRegistry.getResourceDao(eq("Group")))
|
||||
.thenReturn(groupDao);
|
||||
|
|
|
@ -23,6 +23,8 @@ import java.util.Optional;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -68,13 +70,13 @@ class HSearchSortHelperImplTest {
|
|||
void testGetParamType() {
|
||||
SortSpec sortSpec = new SortSpec();
|
||||
sortSpec.setParamName("_tag");
|
||||
when(mockSearchParamRegistry.getActiveSearchParams("Observation")).thenReturn(mockResourceSearchParams);
|
||||
when(mockSearchParamRegistry.getActiveSearchParams(eq("Observation"), any())).thenReturn(mockResourceSearchParams);
|
||||
when(mockResourceSearchParams.get("the-param-name")).thenReturn(mockRuntimeSearchParam);
|
||||
when(mockRuntimeSearchParam.getParamType()).thenReturn(RestSearchParameterTypeEnum.TOKEN);
|
||||
|
||||
Optional<RestSearchParameterTypeEnum> paramType = tested.getParamType("Observation", "the-param-name");
|
||||
|
||||
verify(mockSearchParamRegistry, times(1)).getActiveSearchParams("Observation");
|
||||
verify(mockSearchParamRegistry, times(1)).getActiveSearchParams(eq("Observation"), any());
|
||||
verify(mockResourceSearchParams, times(1)).get("the-param-name");
|
||||
assertFalse(paramType.isEmpty());
|
||||
}
|
||||
|
|
|
@ -207,7 +207,8 @@ public class HfqlExecutor implements IHfqlExecutor {
|
|||
*/
|
||||
private void massageWhereClauses(HfqlStatement theStatement) {
|
||||
String fromResourceName = theStatement.getFromResourceName();
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(fromResourceName);
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(
|
||||
fromResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
for (HfqlStatement.WhereClause nextWhereClause : theStatement.getWhereClauses()) {
|
||||
|
||||
|
@ -311,7 +312,9 @@ public class HfqlExecutor implements IHfqlExecutor {
|
|||
QualifierDetails qualifiedParamName = QualifierDetails.extractQualifiersFromParameterName(paramName);
|
||||
|
||||
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
statement.getFromResourceName(), qualifiedParamName.getParamName());
|
||||
statement.getFromResourceName(),
|
||||
qualifiedParamName.getParamName(),
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (searchParam == null) {
|
||||
throw newInvalidRequestExceptionUnknownSearchParameter(paramName);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
|||
*/
|
||||
@Entity()
|
||||
@Table(
|
||||
name = "HFJ_IDX_CMP_STRING_UNIQ",
|
||||
name = ResourceIndexedComboStringUnique.HFJ_IDX_CMP_STRING_UNIQ,
|
||||
indexes = {
|
||||
@Index(
|
||||
name = ResourceIndexedComboStringUnique.IDX_IDXCMPSTRUNIQ_STRING,
|
||||
|
@ -75,6 +75,7 @@ public class ResourceIndexedComboStringUnique extends BaseResourceIndexedCombo
|
|||
public static final int MAX_STRING_LENGTH = 500;
|
||||
public static final String IDX_IDXCMPSTRUNIQ_STRING = "IDX_IDXCMPSTRUNIQ_STRING";
|
||||
public static final String IDX_IDXCMPSTRUNIQ_RESOURCE = "IDX_IDXCMPSTRUNIQ_RESOURCE";
|
||||
public static final String HFJ_IDX_CMP_STRING_UNIQ = "HFJ_IDX_CMP_STRING_UNIQ";
|
||||
|
||||
@SequenceGenerator(name = "SEQ_IDXCMPSTRUNIQ_ID", sequenceName = "SEQ_IDXCMPSTRUNIQ_ID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_IDXCMPSTRUNIQ_ID")
|
||||
|
|
|
@ -41,7 +41,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
|
|||
|
||||
@Entity
|
||||
@Table(
|
||||
name = "HFJ_IDX_CMB_TOK_NU",
|
||||
name = ResourceIndexedComboTokenNonUnique.HFJ_IDX_CMB_TOK_NU,
|
||||
indexes = {
|
||||
// TODO: The hash index was added in 7.4.0 - In 7.6.0 we should drop the string index
|
||||
@Index(name = "IDX_IDXCMBTOKNU_STR", columnList = "IDX_STRING", unique = false),
|
||||
|
@ -51,6 +51,8 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
|
|||
public class ResourceIndexedComboTokenNonUnique extends BaseResourceIndexedCombo
|
||||
implements Comparable<ResourceIndexedComboTokenNonUnique>, IResourceIndexComboSearchParameter {
|
||||
|
||||
public static final String HFJ_IDX_CMB_TOK_NU = "HFJ_IDX_CMB_TOK_NU";
|
||||
|
||||
@SequenceGenerator(name = "SEQ_IDXCMBTOKNU_ID", sequenceName = "SEQ_IDXCMBTOKNU_ID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_IDXCMBTOKNU_ID")
|
||||
@Id
|
||||
|
|
|
@ -52,7 +52,7 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
|
|||
@EntityListeners(IndexStorageOptimizationListener.class)
|
||||
@Entity
|
||||
@Table(
|
||||
name = "HFJ_SPIDX_STRING",
|
||||
name = ResourceIndexedSearchParamString.HFJ_SPIDX_STRING,
|
||||
indexes = {
|
||||
/*
|
||||
* Note: We previously had indexes with the following names,
|
||||
|
@ -76,6 +76,7 @@ public class ResourceIndexedSearchParamString extends BaseResourceIndexedSearchP
|
|||
public static final int MAX_LENGTH = 768;
|
||||
public static final int HASH_PREFIX_LENGTH = 1;
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final String HFJ_SPIDX_STRING = "HFJ_SPIDX_STRING";
|
||||
|
||||
@Id
|
||||
@SequenceGenerator(name = "SEQ_SPIDX_STRING", sequenceName = "SEQ_SPIDX_STRING")
|
||||
|
|
|
@ -56,7 +56,7 @@ import static org.apache.commons.lang3.StringUtils.trim;
|
|||
@EntityListeners(IndexStorageOptimizationListener.class)
|
||||
@Entity
|
||||
@Table(
|
||||
name = "HFJ_SPIDX_TOKEN",
|
||||
name = ResourceIndexedSearchParamToken.HFJ_SPIDX_TOKEN,
|
||||
indexes = {
|
||||
/*
|
||||
* Note: We previously had indexes with the following names,
|
||||
|
@ -78,6 +78,7 @@ public class ResourceIndexedSearchParamToken extends BaseResourceIndexedSearchPa
|
|||
public static final int MAX_LENGTH = 200;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final String HFJ_SPIDX_TOKEN = "HFJ_SPIDX_TOKEN";
|
||||
|
||||
@FullTextField
|
||||
@Column(name = "SP_SYSTEM", nullable = true, length = MAX_LENGTH)
|
||||
|
|
|
@ -168,8 +168,10 @@ public class MatchUrlService {
|
|||
} else if (nextParamName.startsWith("_") && !Constants.PARAM_LANGUAGE.equals(nextParamName)) {
|
||||
// ignore these since they aren't search params (e.g. _sort)
|
||||
} else {
|
||||
RuntimeSearchParam paramDef =
|
||||
mySearchParamRegistry.getActiveSearchParam(theResourceDefinition.getName(), nextParamName);
|
||||
RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceDefinition.getName(),
|
||||
nextParamName,
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (paramDef == null) {
|
||||
throw throwUnrecognizedParamException(theMatchUrl, theResourceDefinition, nextParamName);
|
||||
}
|
||||
|
|
|
@ -356,7 +356,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
String componentSpRef = component.getReference();
|
||||
String expression = component.getExpression();
|
||||
|
||||
RuntimeSearchParam componentSp = mySearchParamRegistry.getActiveSearchParamByUrl(componentSpRef);
|
||||
RuntimeSearchParam componentSp = mySearchParamRegistry.getActiveSearchParamByUrl(
|
||||
componentSpRef, ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
Validate.notNull(
|
||||
componentSp,
|
||||
"Misconfigured SP %s - failed to load component %s",
|
||||
|
@ -426,7 +427,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private boolean isNotExtractableCompositeComponent(RuntimeSearchParam.Component c) {
|
||||
RuntimeSearchParam componentSearchParam = mySearchParamRegistry.getActiveSearchParamByUrl(c.getReference());
|
||||
RuntimeSearchParam componentSearchParam = mySearchParamRegistry.getActiveSearchParamByUrl(
|
||||
c.getReference(), ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
return // Does the sub-param link work?
|
||||
componentSearchParam == null
|
||||
||
|
||||
|
@ -450,8 +452,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
public SearchParamSet<ResourceIndexedComboStringUnique> extractSearchParamComboUnique(
|
||||
String theResourceType, ResourceIndexedSearchParams theParams) {
|
||||
SearchParamSet<ResourceIndexedComboStringUnique> retVal = new SearchParamSet<>();
|
||||
List<RuntimeSearchParam> runtimeComboUniqueParams =
|
||||
mySearchParamRegistry.getActiveComboSearchParams(theResourceType, ComboSearchParamType.UNIQUE);
|
||||
List<RuntimeSearchParam> runtimeComboUniqueParams = mySearchParamRegistry.getActiveComboSearchParams(
|
||||
theResourceType, ComboSearchParamType.UNIQUE, ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
|
||||
for (RuntimeSearchParam runtimeParam : runtimeComboUniqueParams) {
|
||||
Set<ResourceIndexedComboStringUnique> comboUniqueParams =
|
||||
|
@ -485,8 +487,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
public SearchParamSet<ResourceIndexedComboTokenNonUnique> extractSearchParamComboNonUnique(
|
||||
String theResourceType, ResourceIndexedSearchParams theParams) {
|
||||
SearchParamSet<ResourceIndexedComboTokenNonUnique> retVal = new SearchParamSet<>();
|
||||
List<RuntimeSearchParam> runtimeComboNonUniqueParams =
|
||||
mySearchParamRegistry.getActiveComboSearchParams(theResourceType, ComboSearchParamType.NON_UNIQUE);
|
||||
List<RuntimeSearchParam> runtimeComboNonUniqueParams = mySearchParamRegistry.getActiveComboSearchParams(
|
||||
theResourceType,
|
||||
ComboSearchParamType.NON_UNIQUE,
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
|
||||
for (RuntimeSearchParam runtimeParam : runtimeComboNonUniqueParams) {
|
||||
Set<ResourceIndexedComboTokenNonUnique> comboNonUniqueParams =
|
||||
|
@ -566,7 +570,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
|
||||
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
|
||||
|
||||
if (nextParamAsClientParam instanceof DateParam) {
|
||||
if (theParam.getComboSearchParamType() == ComboSearchParamType.NON_UNIQUE
|
||||
&& nextParamAsClientParam instanceof DateParam) {
|
||||
DateParam date = (DateParam) nextParamAsClientParam;
|
||||
if (date.getPrecision() != TemporalPrecisionEnum.DAY) {
|
||||
continue;
|
||||
|
@ -575,7 +580,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
|
||||
String value = nextParamAsClientParam.getValueAsQueryToken(myContext);
|
||||
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceType, key);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(
|
||||
theResourceType, key, ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
if (theParam.getComboSearchParamType() == ComboSearchParamType.NON_UNIQUE
|
||||
&& param != null
|
||||
&& param.getParamType() == RestSearchParameterTypeEnum.STRING) {
|
||||
|
@ -989,8 +995,9 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
@VisibleForTesting
|
||||
Collection<RuntimeSearchParam> getSearchParams(IBaseResource theResource) {
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
Collection<RuntimeSearchParam> retVal =
|
||||
mySearchParamRegistry.getActiveSearchParams(def.getName()).values();
|
||||
Collection<RuntimeSearchParam> retVal = mySearchParamRegistry
|
||||
.getActiveSearchParams(def.getName(), ISearchParamRegistry.SearchParamLookupContextEnum.INDEX)
|
||||
.values();
|
||||
List<RuntimeSearchParam> defaultList = Collections.emptyList();
|
||||
retVal = ObjectUtils.defaultIfNull(retVal, defaultList);
|
||||
return retVal;
|
||||
|
|
|
@ -199,8 +199,8 @@ public class SearchParamExtractorService {
|
|||
});
|
||||
|
||||
// Everything else
|
||||
ResourceSearchParams activeSearchParams =
|
||||
mySearchParamRegistry.getActiveSearchParams(theEntity.getResourceType());
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(
|
||||
theEntity.getResourceType(), ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
theNewParams.findMissingSearchParams(myPartitionSettings, myStorageSettings, theEntity, activeSearchParams);
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,8 @@ public class SearchParamExtractorService {
|
|||
retval.put(nextKey, Boolean.TRUE);
|
||||
}
|
||||
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(entity.getResourceType());
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams(
|
||||
entity.getResourceType(), ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
activeSearchParams.getReferenceSearchParamNames().forEach(key -> retval.putIfAbsent(key, Boolean.FALSE));
|
||||
return retval;
|
||||
}
|
||||
|
@ -308,8 +309,10 @@ public class SearchParamExtractorService {
|
|||
@Override
|
||||
public ISearchParamExtractor.ISearchParamFilter getSearchParamFilter(@Nonnull PathAndRef thePathAndRef) {
|
||||
String searchParamName = thePathAndRef.getSearchParamName();
|
||||
RuntimeSearchParam searchParam =
|
||||
mySearchParamRegistry.getActiveSearchParam(theEntity.getResourceType(), searchParamName);
|
||||
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
theEntity.getResourceType(),
|
||||
searchParamName,
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
Set<String> upliftRefchainCodes = searchParam.getUpliftRefchainCodes();
|
||||
if (upliftRefchainCodes.isEmpty()) {
|
||||
return ISearchParamExtractor.NO_PARAMS;
|
||||
|
@ -533,7 +536,9 @@ public class SearchParamExtractorService {
|
|||
}
|
||||
|
||||
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
sourceResourceName, nextPathAndRef.getSearchParamName());
|
||||
sourceResourceName,
|
||||
nextPathAndRef.getSearchParamName(),
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.INDEX);
|
||||
extractResourceLinks(
|
||||
theRequestPartitionId,
|
||||
theExistingParams,
|
||||
|
|
|
@ -250,7 +250,8 @@ public class InMemoryResourceMatcher {
|
|||
}
|
||||
|
||||
String resourceName = theResourceDefinition.getName();
|
||||
RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(resourceName, theParamName);
|
||||
RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(
|
||||
resourceName, theParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
InMemoryMatchResult checkUnsupportedResult =
|
||||
checkForUnsupportedParameters(theParamName, paramDef, theAndOrParams);
|
||||
if (!checkUnsupportedResult.supported()) {
|
||||
|
@ -589,6 +590,10 @@ public class InMemoryResourceMatcher {
|
|||
case NOT:
|
||||
return !theSearchParams.matchParam(
|
||||
theStorageSettings, theResourceName, theParamName, theParamDef, theQueryParam);
|
||||
case ABOVE:
|
||||
case BELOW:
|
||||
case TEXT:
|
||||
case OF_TYPE:
|
||||
default:
|
||||
return theSearchParams.matchParam(
|
||||
theStorageSettings, theResourceName, theParamName, theParamDef, theQueryParam);
|
||||
|
@ -688,9 +693,22 @@ public class InMemoryResourceMatcher {
|
|||
return getValidationSupportOrNull() != null;
|
||||
case NOT:
|
||||
return true;
|
||||
case TEXT:
|
||||
case OF_TYPE:
|
||||
case ABOVE:
|
||||
case BELOW:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case NUMBER:
|
||||
case DATE:
|
||||
case STRING:
|
||||
case REFERENCE:
|
||||
case COMPOSITE:
|
||||
case QUANTITY:
|
||||
case URI:
|
||||
case HAS:
|
||||
case SPECIAL:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -61,9 +61,12 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.rest.server.util.ISearchParamRegistry.isAllowedForContext;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
public class SearchParamRegistryImpl
|
||||
|
@ -76,7 +79,7 @@ public class SearchParamRegistryImpl
|
|||
Collections.unmodifiableSet(Sets.newHashSet("*:url", "Subscription:*", "SearchParameter:*"));
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(SearchParamRegistryImpl.class);
|
||||
private static final int MAX_MANAGED_PARAM_COUNT = 10000;
|
||||
public static final int MAX_MANAGED_PARAM_COUNT = 10000;
|
||||
private static final long REFRESH_INTERVAL = DateUtils.MILLIS_PER_MINUTE;
|
||||
|
||||
private final JpaSearchParamCache myJpaSearchParamCache = new JpaSearchParamCache();
|
||||
|
@ -112,45 +115,55 @@ public class SearchParamRegistryImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
|
||||
public RuntimeSearchParam getActiveSearchParam(
|
||||
String theResourceName, String theParamName, SearchParamLookupContextEnum theContext) {
|
||||
requiresActiveSearchParams();
|
||||
|
||||
// Can still be null in unit test scenarios
|
||||
if (myActiveSearchParams != null) {
|
||||
return myActiveSearchParams.get(theResourceName, theParamName);
|
||||
} else {
|
||||
return null;
|
||||
RuntimeSearchParam param = myActiveSearchParams.get(theResourceName, theParamName);
|
||||
if (param != null) {
|
||||
if (isAllowedForContext(param, theContext)) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ResourceSearchParams getActiveSearchParams(String theResourceName) {
|
||||
public ResourceSearchParams getActiveSearchParams(String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
requiresActiveSearchParams();
|
||||
return getActiveSearchParams().getSearchParamMap(theResourceName);
|
||||
return getActiveSearchParams().getSearchParamMap(theResourceName).toFilteredForContext(theContext);
|
||||
}
|
||||
|
||||
private void requiresActiveSearchParams() {
|
||||
if (myActiveSearchParams == null) {
|
||||
// forced refreshes should not use a cache - we're forcibly refrsching it, after all
|
||||
// forced refreshes should not use a cache - we're forcibly refreshing it, after all
|
||||
myResourceChangeListenerCache.forceRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
return myJpaSearchParamCache.getActiveComboSearchParams(theResourceName);
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
return filteredForContext(myJpaSearchParamCache.getActiveComboSearchParams(theResourceName), theContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, ComboSearchParamType theParamType) {
|
||||
return myJpaSearchParamCache.getActiveComboSearchParams(theResourceName, theParamType);
|
||||
String theResourceName, ComboSearchParamType theParamType, SearchParamLookupContextEnum theContext) {
|
||||
return filteredForContext(
|
||||
myJpaSearchParamCache.getActiveComboSearchParams(theResourceName, theParamType), theContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
return myJpaSearchParamCache.getActiveComboSearchParams(theResourceName, theParamNames);
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, Set<String> theParamNames, SearchParamLookupContextEnum theContext) {
|
||||
return filteredForContext(
|
||||
myJpaSearchParamCache.getActiveComboSearchParams(theResourceName, theParamNames), theContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -160,12 +173,14 @@ public class SearchParamRegistryImpl
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
|
||||
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl, SearchParamLookupContextEnum theContext) {
|
||||
if (myActiveSearchParams != null) {
|
||||
return myActiveSearchParams.getByUrl(theUrl);
|
||||
} else {
|
||||
return null;
|
||||
RuntimeSearchParam param = myActiveSearchParams.getByUrl(theUrl);
|
||||
if (isAllowedForContext(param, theContext)) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -307,7 +322,7 @@ public class SearchParamRegistryImpl
|
|||
ourLog.debug(
|
||||
"Adding search parameter {}.{} to SearchParamRegistry",
|
||||
nextBaseName,
|
||||
StringUtils.defaultString(name, "[composite]"));
|
||||
Objects.toString(name, "[composite]"));
|
||||
retval++;
|
||||
}
|
||||
return retval;
|
||||
|
@ -365,6 +380,11 @@ public class SearchParamRegistryImpl
|
|||
return ReadOnlySearchParamCache.fromRuntimeSearchParamCache(myActiveSearchParams);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setActiveSearchParams(RuntimeSearchParamCache theSearchParams) {
|
||||
myActiveSearchParams = theSearchParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* All SearchParameters with the name "phonetic" encode the normalized index value using this phonetic encoder.
|
||||
*
|
||||
|
@ -451,13 +471,10 @@ public class SearchParamRegistryImpl
|
|||
mySearchParameterCanonicalizer = theSearchParameterCanonicalizerForUnitTest;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public int getMaxManagedParamCountForUnitTests() {
|
||||
return MAX_MANAGED_PARAM_COUNT;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setActiveSearchParams(RuntimeSearchParamCache theSearchParams) {
|
||||
myActiveSearchParams = theSearchParams;
|
||||
private static List<RuntimeSearchParam> filteredForContext(
|
||||
List<RuntimeSearchParam> theActiveComboSearchParams, SearchParamLookupContextEnum theContext) {
|
||||
return theActiveComboSearchParams.stream()
|
||||
.filter(t -> isAllowedForContext(t, theContext))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -469,12 +469,22 @@ public class SearchParameterCanonicalizer {
|
|||
setEncoder(theRuntimeSearchParam, next.getValue());
|
||||
} else if (HapiExtensions.EXTENSION_SEARCHPARAM_UPLIFT_REFCHAIN.equals(nextUrl)) {
|
||||
addUpliftRefchain(theRuntimeSearchParam, next);
|
||||
} else if (HapiExtensions.EXT_SEARCHPARAM_ENABLED_FOR_SEARCHING.equals(nextUrl)) {
|
||||
addEnabledForSearching(theRuntimeSearchParam, next.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addEnabledForSearching(RuntimeSearchParam theRuntimeSearchParam, IBaseDatatype theValue) {
|
||||
if (theValue instanceof IPrimitiveType) {
|
||||
String stringValue = ((IPrimitiveType<?>) theValue).getValueAsString();
|
||||
boolean enabledForSearching = Boolean.parseBoolean(stringValue);
|
||||
theRuntimeSearchParam.setEnabledForSearching(enabledForSearching);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addUpliftRefchain(
|
||||
RuntimeSearchParam theRuntimeSearchParam, IBaseExtension<? extends IBaseExtension, ?> theExtension) {
|
||||
|
|
|
@ -162,7 +162,7 @@ public enum JpaParamUtil {
|
|||
List<RuntimeSearchParam.Component> components = theParamDef.getComponents();
|
||||
for (RuntimeSearchParam.Component next : components) {
|
||||
String url = next.getReference();
|
||||
RuntimeSearchParam componentParam = theSearchParamRegistry.getActiveSearchParamByUrl(url);
|
||||
RuntimeSearchParam componentParam = theSearchParamRegistry.getActiveSearchParamByUrl(url, null);
|
||||
if (componentParam == null) {
|
||||
throw new InternalErrorException(Msg.code(499) + "Can not find SearchParameter: " + url);
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@ public class SearchParamExtractorDstu3Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
|
||||
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -278,7 +278,7 @@ public class SearchParamExtractorDstu3Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ResourceSearchParams getActiveSearchParams(String theResourceName) {
|
||||
public ResourceSearchParams getActiveSearchParams(String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
RuntimeResourceDefinition nextResDef = ourCtx.getResourceDefinition(theResourceName);
|
||||
ResourceSearchParams retval = new ResourceSearchParams(theResourceName);
|
||||
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
|
||||
|
@ -291,23 +291,23 @@ public class SearchParamExtractorDstu3Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
|
||||
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, ComboSearchParamType theParamType) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, ComboSearchParamType theParamType, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException(Msg.code(2210));
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|||
import static ca.uhn.fhir.jpa.searchparam.matcher.InMemoryResourceMatcherR5Test.newRequest;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -59,7 +61,7 @@ public class InMemoryResourceMatcherConfigurationR5Test {
|
|||
@BeforeEach
|
||||
public void before() {
|
||||
RuntimeSearchParam codeSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.code", RestSearchParameterTypeEnum.TOKEN, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "code")).thenReturn(codeSearchParam);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("code"), any())).thenReturn(codeSearchParam);
|
||||
|
||||
myObservation = new Observation();
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
|
|
|
@ -86,13 +86,13 @@ public class InMemoryResourceMatcherR5Test {
|
|||
@BeforeEach
|
||||
public void before() {
|
||||
RuntimeSearchParam dateSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.effective", RestSearchParameterTypeEnum.DATE, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "date")).thenReturn(dateSearchParam);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("date"), any())).thenReturn(dateSearchParam);
|
||||
|
||||
RuntimeSearchParam codeSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.code", RestSearchParameterTypeEnum.TOKEN, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "code")).thenReturn(codeSearchParam);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("code"), any())).thenReturn(codeSearchParam);
|
||||
|
||||
RuntimeSearchParam encSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.encounter", RestSearchParameterTypeEnum.REFERENCE, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "encounter")).thenReturn(encSearchParam);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("encounter"), any())).thenReturn(encSearchParam);
|
||||
|
||||
myObservation = new Observation();
|
||||
myObservation.getMeta().setSource(TEST_SOURCE);
|
||||
|
|
|
@ -138,7 +138,7 @@ public class SearchParamRegistryImplTest {
|
|||
|
||||
@Test
|
||||
void handleInit() {
|
||||
assertEquals(31, mySearchParamRegistry.getActiveSearchParams("Patient").size());
|
||||
assertEquals(31, mySearchParamRegistry.getActiveSearchParams("Patient", null).size());
|
||||
|
||||
IdDt idBad = new IdDt("SearchParameter/bad");
|
||||
when(mySearchParamProvider.read(idBad)).thenThrow(new ResourceNotFoundException("id bad"));
|
||||
|
@ -151,7 +151,7 @@ public class SearchParamRegistryImplTest {
|
|||
idList.add(idBad);
|
||||
idList.add(idGood);
|
||||
mySearchParamRegistry.handleInit(idList);
|
||||
assertEquals(32, mySearchParamRegistry.getActiveSearchParams("Patient").size());
|
||||
assertEquals(32, mySearchParamRegistry.getActiveSearchParams("Patient", null).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -226,7 +226,7 @@ public class SearchParamRegistryImplTest {
|
|||
}
|
||||
|
||||
private void assertPatientSearchParamSize(int theExpectedSize) {
|
||||
assertEquals(theExpectedSize, mySearchParamRegistry.getActiveSearchParams("Patient").size());
|
||||
assertEquals(theExpectedSize, mySearchParamRegistry.getActiveSearchParams("Patient", null).size());
|
||||
}
|
||||
|
||||
private void assertResult(ResourceChangeResult theResult, long theExpectedAdded, long theExpectedUpdated, long theExpectedRemoved) {
|
||||
|
@ -253,19 +253,19 @@ public class SearchParamRegistryImplTest {
|
|||
|
||||
@Test
|
||||
public void testGetActiveUniqueSearchParams_Empty() {
|
||||
assertThat(mySearchParamRegistry.getActiveComboSearchParams("Patient")).isEmpty();
|
||||
assertThat(mySearchParamRegistry.getActiveComboSearchParams("Patient", null)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveSearchParamByUrl_whenSPExists_returnsActiveSp() {
|
||||
RuntimeSearchParam patientLanguageSp = mySearchParamRegistry.getActiveSearchParamByUrl("SearchParameter/Patient-language");
|
||||
RuntimeSearchParam patientLanguageSp = mySearchParamRegistry.getActiveSearchParamByUrl("SearchParameter/Patient-language", null);
|
||||
assertNotNull(patientLanguageSp);
|
||||
assertEquals(patientLanguageSp.getId().getIdPart(), "Patient-language");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveSearchParamByUrl_whenSPNotExist_returnsNull() {
|
||||
RuntimeSearchParam nonExistingSp = mySearchParamRegistry.getActiveSearchParamByUrl("SearchParameter/nonExistingSp");
|
||||
RuntimeSearchParam nonExistingSp = mySearchParamRegistry.getActiveSearchParamByUrl("SearchParameter/nonExistingSp", null);
|
||||
assertNull(nonExistingSp);
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ public class SearchParamRegistryImplTest {
|
|||
|
||||
assertFalse(retried.get());
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams("Patient");
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams("Patient", null);
|
||||
assertTrue(retried.get());
|
||||
assertEquals(ourBuiltInSearchParams.getSearchParamMap("Patient").size(), activeSearchParams.size());
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ public class SearchParamRegistryImplTest {
|
|||
resetDatabaseToOrigSearchParamsPlusNewOneWithStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams("Patient");
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams("Patient", null);
|
||||
|
||||
RuntimeSearchParam converted = activeSearchParams.get("foo");
|
||||
assertNotNull(converted);
|
||||
|
@ -332,7 +332,7 @@ public class SearchParamRegistryImplTest {
|
|||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
RuntimeSearchParam canonicalSp = mySearchParamRegistry.getRuntimeSearchParam("Encounter", "subject");
|
||||
RuntimeSearchParam canonicalSp = mySearchParamRegistry.getRuntimeSearchParam("Encounter", "subject", null);
|
||||
assertEquals("Modified Subject", canonicalSp.getDescription());
|
||||
assertTrue(canonicalSp.hasUpliftRefchain("name1"));
|
||||
assertFalse(canonicalSp.hasUpliftRefchain("name99"));
|
||||
|
|
|
@ -71,7 +71,7 @@ public class SubscriptionLoader extends BaseResourceCacheSynchronizer {
|
|||
protected SearchParameterMap getSearchParameterMap() {
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
|
||||
if (mySearchParamRegistry.getActiveSearchParam("Subscription", "status") != null) {
|
||||
if (mySearchParamRegistry.getActiveSearchParam("Subscription", "status", null) != null) {
|
||||
map.add(
|
||||
Subscription.SP_STATUS,
|
||||
new TokenOrListParam()
|
||||
|
|
|
@ -71,7 +71,7 @@ public class SubscriptionTopicLoader extends BaseResourceCacheSynchronizer {
|
|||
protected SearchParameterMap getSearchParameterMap() {
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
|
||||
if (mySearchParamRegistry.getActiveSearchParam("SubscriptionTopic", "status") != null) {
|
||||
if (mySearchParamRegistry.getActiveSearchParam("SubscriptionTopic", "status", null) != null) {
|
||||
map.add(SubscriptionTopic.SP_STATUS, new TokenParam(null, Enumerations.PublicationStatus.ACTIVE.toCode()));
|
||||
}
|
||||
map.setLoadSynchronousUpTo(SubscriptionConstants.MAX_SUBSCRIPTION_RESULTS);
|
||||
|
|
|
@ -42,7 +42,7 @@ public class MatchUrlServiceTest extends BaseJpaTest {
|
|||
public void testTranslateMatchUrl() {
|
||||
RuntimeResourceDefinition resourceDef = ourCtx.getResourceDefinition(Condition.class);
|
||||
ISearchParamRegistry searchParamRegistry = mock(ISearchParamRegistry.class);
|
||||
when(searchParamRegistry.getActiveSearchParam(any(), eq("patient"))).thenReturn(resourceDef.getSearchParam("patient"));
|
||||
when(searchParamRegistry.getActiveSearchParam(any(), eq("patient"), any())).thenReturn(resourceDef.getSearchParam("patient"));
|
||||
SearchParameterMap match = myMatchUrlService.translateMatchUrl("Condition?patient=304&_lastUpdated=>2011-01-01T11:12:21.0000Z", resourceDef);
|
||||
assertEquals("2011-01-01T11:12:21.0000Z", match.getLastUpdated().getLowerBound().getValueAsString());
|
||||
assertEquals(ReferenceParam.class, match.get("patient").get(0).get(0).getClass());
|
||||
|
|
|
@ -135,10 +135,10 @@ public abstract class BasePartitioningR4Test extends BaseJpaR4SystemTest {
|
|||
addCreateDefaultPartition();
|
||||
addReadDefaultPartition(); // one for search param validation
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-birthdate");
|
||||
sp.setType(Enumerations.SearchParamType.DATE);
|
||||
sp.setCode("birthdate");
|
||||
sp.setExpression("Patient.birthDate");
|
||||
sp.setId("SearchParameter/patient-gender");
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setCode("gender");
|
||||
sp.setExpression("Patient.gender");
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
@ -156,13 +156,13 @@ public abstract class BasePartitioningR4Test extends BaseJpaR4SystemTest {
|
|||
|
||||
addCreateDefaultPartition();
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-birthdate-unique");
|
||||
sp.setId("SearchParameter/patient-gender-family-unique");
|
||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-birthdate");
|
||||
.setDefinition("SearchParameter/patient-gender");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-family");
|
||||
|
|
|
@ -76,7 +76,7 @@ public class ChainingR4SearchTest extends BaseJpaR4Test {
|
|||
msgHeader.setEvent(new Coding("http://foo", "bar", "blah"));
|
||||
inputBundle.addEntry().setResource(msgHeader);
|
||||
|
||||
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Bundle", "message");
|
||||
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Bundle", "message", null);
|
||||
assertEquals("Bundle.entry[0].resource", sp.getPath());
|
||||
assertThat(sp.getBase()).containsExactly("Bundle");
|
||||
assertEquals(RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, sp.getStatus());
|
||||
|
|
|
@ -12,11 +12,12 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
|||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
|
||||
import ca.uhn.fhir.jpa.test.util.ComboSearchParameterTestHelper;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.DateAndListParam;
|
||||
import ca.uhn.fhir.rest.param.DateOrListParam;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
|
@ -33,6 +34,7 @@ import org.hl7.fhir.r4.model.DateType;
|
|||
import org.hl7.fhir.r4.model.Encounter;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r4.model.HumanName;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
import org.hl7.fhir.r4.model.Organization;
|
||||
|
@ -42,6 +44,7 @@ import org.hl7.fhir.r4.model.Reference;
|
|||
import org.hl7.fhir.r4.model.SearchParameter;
|
||||
import org.hl7.fhir.r4.model.ServiceRequest;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
@ -69,6 +72,12 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
|
||||
@Autowired
|
||||
private IJobCoordinator myJobCoordinator;
|
||||
private ComboSearchParameterTestHelper myComboSearchParameterTestHelper;
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() {
|
||||
myComboSearchParameterTestHelper = new ComboSearchParameterTestHelper(mySearchParameterDao, mySearchParamRegistry);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void purgeUniqueIndexes() {
|
||||
|
@ -76,6 +85,11 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
}
|
||||
|
||||
private void createUniqueBirthdateAndGenderSps() {
|
||||
myComboSearchParameterTestHelper.createBirthdateAndGenderSps(true);
|
||||
myMessages.clear();
|
||||
}
|
||||
|
||||
private void createUniqueGenderFamilyComboSp() {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-gender");
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
|
@ -86,16 +100,16 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-birthdate");
|
||||
sp.setType(Enumerations.SearchParamType.DATE);
|
||||
sp.setCode("birthdate");
|
||||
sp.setExpression("Patient.birthDate");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.setId("SearchParameter/patient-family");
|
||||
sp.setType(Enumerations.SearchParamType.STRING);
|
||||
sp.setCode("family");
|
||||
sp.setExpression("Patient.name.family");
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-gender-birthdate");
|
||||
sp.setId("SearchParameter/patient-gender-family");
|
||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
|
@ -104,7 +118,7 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
.setDefinition("SearchParameter/patient-gender");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-birthdate");
|
||||
.setDefinition("SearchParameter/patient-family");
|
||||
sp.addExtension()
|
||||
.setUrl(HapiExtensions.EXT_SP_UNIQUE)
|
||||
.setValue(new BooleanType(true));
|
||||
|
@ -276,6 +290,45 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
mySearchParamRegistry.forceRefresh();
|
||||
}
|
||||
|
||||
private void createUniqueObservationDateCode() {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/obs-effective");
|
||||
sp.setType(Enumerations.SearchParamType.DATE);
|
||||
sp.setCode("date");
|
||||
sp.setExpression("Observation.effective");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Observation");
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/obs-code");
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setCode("code");
|
||||
sp.setExpression("Observation.code");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Observation");
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/observation-date-code");
|
||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Observation");
|
||||
sp.setExpression("Observation.code");
|
||||
sp.addComponent()
|
||||
.setExpression("Observation")
|
||||
.setDefinition("SearchParameter/obs-effective");
|
||||
sp.addComponent()
|
||||
.setExpression("Observation")
|
||||
.setDefinition("SearchParameter/obs-code");
|
||||
sp.addExtension()
|
||||
.setUrl(HapiExtensions.EXT_SP_UNIQUE)
|
||||
.setValue(new BooleanType(true));
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
}
|
||||
|
||||
private void createUniqueObservationSubjectDateCode() {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/obs-subject");
|
||||
|
@ -471,11 +524,11 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
public void testDoubleMatchingOnAnd_Search_TwoAndOrValues() {
|
||||
myStorageSettings.setUniqueIndexesCheckedBeforeSave(false);
|
||||
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
createUniqueGenderFamilyComboSp();
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||
pt1.getName().add(new HumanName().setFamily("Family1"));
|
||||
String id1 = myPatientDao.create(pt1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
// Two OR values on the same resource - Currently composite SPs don't work for this
|
||||
|
@ -484,17 +537,22 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
sp.setLoadSynchronous(true);
|
||||
sp.add(Patient.SP_GENDER,
|
||||
new TokenAndListParam()
|
||||
.addAnd(new TokenParam("http://hl7.org/fhir/administrative-gender","male"), new TokenParam( "http://hl7.org/fhir/administrative-gender","female"))
|
||||
.addAnd(new TokenParam("http://hl7.org/fhir/administrative-gender","male"),
|
||||
new TokenParam( "http://hl7.org/fhir/administrative-gender","female"))
|
||||
);
|
||||
sp.add(Patient.SP_BIRTHDATE,
|
||||
new DateAndListParam()
|
||||
.addAnd(new DateParam("2011-01-01"), new DateParam( "2011-02-02"))
|
||||
sp.add(Patient.SP_FAMILY,
|
||||
new StringOrListParam()
|
||||
.addOr(new StringParam("Family1")).addOr(new StringParam("Family2"))
|
||||
);
|
||||
IBundleProvider outcome = myPatientDao.search(sp, mySrd);
|
||||
myCaptureQueriesListener.logFirstSelectQueryForCurrentThread();
|
||||
assertThat(toUnqualifiedVersionlessIdValues(outcome)).containsExactlyInAnyOrder(id1);
|
||||
String unformattedSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, false);
|
||||
assertEquals("SELECT t0.RES_ID FROM HFJ_IDX_CMP_STRING_UNIQ t0 WHERE (t0.IDX_STRING IN ('Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cfemale','Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale','Patient?birthdate=2011-02-02&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cfemale','Patient?birthdate=2011-02-02&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale') )", unformattedSql);
|
||||
assertEquals("SELECT t0.RES_ID FROM HFJ_IDX_CMP_STRING_UNIQ t0 WHERE (t0.IDX_STRING IN (" +
|
||||
"'Patient?family=Family1&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cfemale'," +
|
||||
"'Patient?family=Family1&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale'," +
|
||||
"'Patient?family=Family2&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cfemale'," +
|
||||
"'Patient?family=Family2&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale') )", unformattedSql);
|
||||
}
|
||||
|
||||
|
||||
|
@ -774,7 +832,7 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
myStorageSettings.setSchedulingDisabled(true);
|
||||
myStorageSettings.setReindexThreadCount(1);
|
||||
|
||||
List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation");
|
||||
List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation", null);
|
||||
assertThat(uniqueSearchParams).isEmpty();
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
|
@ -803,7 +861,7 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
|
||||
createUniqueObservationSubjectDateCode();
|
||||
|
||||
uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation");
|
||||
uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation", null);
|
||||
assertThat(uniqueSearchParams).hasSize(1);
|
||||
assertThat(uniqueSearchParams.get(0).getComponents()).hasSize(3);
|
||||
|
||||
|
@ -820,7 +878,7 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
myResourceIndexedComboStringUniqueDao.deleteAll();
|
||||
});
|
||||
|
||||
assertThat(mySearchParamRegistry.getActiveComboSearchParams("Observation")).hasSize(1);
|
||||
assertThat(mySearchParamRegistry.getActiveComboSearchParams("Observation", null)).hasSize(1);
|
||||
|
||||
executeReindex();
|
||||
|
||||
|
@ -1167,16 +1225,16 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
@Test
|
||||
public void testOrQuery() {
|
||||
myStorageSettings.setAdvancedHSearchIndexing(false);
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
createUniqueGenderFamilyComboSp();
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||
pt1.getName().add(new HumanName().setFamily("Family1"));
|
||||
IIdType id1 = myPatientDao.create(pt1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt2.setBirthDateElement(new DateType("2011-01-02"));
|
||||
pt2.getName().add(new HumanName().setFamily("Family2"));
|
||||
IIdType id2 = myPatientDao.create(pt2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
@ -1184,16 +1242,21 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(100);
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
params.add("birthdate", new DateOrListParam().addOr(new DateParam("2011-01-01")).addOr(new DateParam("2011-01-02")));
|
||||
params.add("family", new StringOrListParam()
|
||||
.addOr(new StringParam("Family1")).addOr(new StringParam("Family2")));
|
||||
myCaptureQueriesListener.clear();
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
myCaptureQueriesListener.logFirstSelectQueryForCurrentThread();
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).containsExactlyInAnyOrder(id1.getValue(), id2.getValue());
|
||||
|
||||
assertThat(myCaptureQueriesListener.getSelectQueries().get(0).getSql(true, false))
|
||||
.contains("SELECT t0.RES_ID FROM HFJ_IDX_CMP_STRING_UNIQ t0 WHERE (t0.IDX_STRING IN ('Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale','Patient?birthdate=2011-01-02&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale') )");
|
||||
.contains("SELECT t0.RES_ID FROM HFJ_IDX_CMP_STRING_UNIQ t0 WHERE (t0.IDX_STRING IN " +
|
||||
"('Patient?family=Family1&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale'," +
|
||||
"'Patient?family=Family2&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale') )");
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: [Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale, Patient?birthdate=2011-01-02&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale]");
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: " +
|
||||
"[Patient?family=Family1&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale, " +
|
||||
"Patient?family=Family2&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale]");
|
||||
myMessages.clear();
|
||||
|
||||
}
|
||||
|
@ -1201,16 +1264,16 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
@Test
|
||||
public void testSearchSynchronousUsingUniqueComposite() {
|
||||
myStorageSettings.setAdvancedHSearchIndexing(false);
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
createUniqueGenderFamilyComboSp();
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||
pt1.getName().add(new HumanName().setFamily("Family1"));
|
||||
IIdType id1 = myPatientDao.create(pt1, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt2.setBirthDateElement(new DateType("2011-01-02"));
|
||||
pt2.getName().add(new HumanName().setFamily("Family2"));
|
||||
myPatientDao.create(pt2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
|
@ -1218,13 +1281,14 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(100);
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
params.add("birthdate", new DateParam("2011-01-01"));
|
||||
params.add("family", new StringParam("Family1"));
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
myCaptureQueriesListener.logFirstSelectQueryForCurrentThread();
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).containsExactlyInAnyOrder(id1.getValue());
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale");
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: " +
|
||||
"Patient?family=Family1&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale");
|
||||
myMessages.clear();
|
||||
|
||||
}
|
||||
|
@ -1232,33 +1296,34 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
|
||||
@Test
|
||||
public void testSearchUsingUniqueComposite() {
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
createUniqueGenderFamilyComboSp();
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||
pt1.getName().add(new HumanName().setFamily("Family1"));
|
||||
String id1 = myPatientDao.create(pt1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt2.setBirthDateElement(new DateType("2011-01-02"));
|
||||
pt2.getName().add(new HumanName().setFamily("Family2"));
|
||||
myPatientDao.create(pt2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
myMessages.clear();
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
params.add("birthdate", new DateParam("2011-01-01"));
|
||||
params.add("family", new StringParam("Family1"));
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
String searchId = results.getUuid();
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).containsExactlyInAnyOrder(id1);
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale");
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: " +
|
||||
"Patient?family=Family1&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale");
|
||||
myMessages.clear();
|
||||
|
||||
// Other order
|
||||
myMessages.clear();
|
||||
params = new SearchParameterMap();
|
||||
params.add("birthdate", new DateParam("2011-01-01"));
|
||||
params.add("family", new StringParam("Family1"));
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
results = myPatientDao.search(params, mySrd);
|
||||
assertEquals(searchId, results.getUuid());
|
||||
|
@ -1272,16 +1337,17 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
myMessages.clear();
|
||||
params = new SearchParameterMap();
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
params.add("birthdate", new DateParam("2011-01-03"));
|
||||
params.add("family", new StringParam("Family3"));
|
||||
results = myPatientDao.search(params, mySrd);
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).isEmpty();
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: Patient?birthdate=2011-01-03&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale");
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: " +
|
||||
"Patient?family=Family3&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale");
|
||||
myMessages.clear();
|
||||
|
||||
myMessages.clear();
|
||||
params = new SearchParameterMap();
|
||||
params.add("birthdate", new DateParam("2011-01-03"));
|
||||
params.add("family", new StringParam("Family3"));
|
||||
results = myPatientDao.search(params, mySrd);
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).isEmpty();
|
||||
// STANDARD QUERY
|
||||
|
@ -1653,7 +1719,7 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
@Test
|
||||
public void testDetectUniqueSearchParams() {
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
List<RuntimeSearchParam> params = mySearchParamRegistry.getActiveComboSearchParams("Patient");
|
||||
List<RuntimeSearchParam> params = mySearchParamRegistry.getActiveComboSearchParams("Patient", null);
|
||||
|
||||
assertThat(params).hasSize(1);
|
||||
assertEquals(ComboSearchParamType.UNIQUE, params.get(0).getComboSearchParamType());
|
||||
|
@ -1666,7 +1732,7 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateUniqueValuesAreRejected() {
|
||||
public void testDuplicateUniqueValuesWithDateAreRejected() {
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
|
@ -1699,13 +1765,75 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceOneWithAnother() {
|
||||
myStorageSettings.setAdvancedHSearchIndexing(false);
|
||||
public void testDuplicateUniqueValuesWithDateTimeAreRejected() {
|
||||
createUniqueObservationDateCode();
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getCode().addCoding().setSystem("foo").setCode("bar");
|
||||
obs.setEffective(new DateTimeType("2017-10-10T00:00:00"));
|
||||
myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
try {
|
||||
myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless();
|
||||
fail();
|
||||
} catch (ResourceVersionConflictException e) {
|
||||
assertThat(e.getMessage())
|
||||
.contains("new unique index created by SearchParameter/observation-date-code");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUniqueComboSearchWithDateNotUsingUniqueIndex() {
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||
String pId = myPatientDao.create(pt1, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(100);
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
params.add("birthdate", new DateParam("2011-01-01"));
|
||||
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).containsExactlyInAnyOrder(pId);
|
||||
myCaptureQueriesListener.logFirstSelectQueryForCurrentThread();
|
||||
String unformattedSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, false);
|
||||
assertThat(unformattedSql).doesNotContain("HFJ_IDX_CMP_STRING_UNIQ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUniqueComboSearchWithDateTimeNotUsingUniqueIndex() {
|
||||
createUniqueObservationDateCode();
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getCode().addCoding().setSystem("foo").setCode("bar");
|
||||
obs.setEffective(new DateTimeType("2017-10-10T00:00:00"));
|
||||
String obsId = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(100);
|
||||
params.add("code", new TokenParam("foo", "bar"));
|
||||
params.add("date", new DateParam("2017-10-10T00:00:00"));
|
||||
|
||||
IBundleProvider results = myObservationDao.search(params, mySrd);
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).containsExactlyInAnyOrder(obsId);
|
||||
myCaptureQueriesListener.logFirstSelectQueryForCurrentThread();
|
||||
String unformattedSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, false);
|
||||
assertThat(unformattedSql).doesNotContain("HFJ_IDX_CMP_STRING_UNIQ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceOneWithAnother() {
|
||||
myStorageSettings.setAdvancedHSearchIndexing(false);
|
||||
createUniqueGenderFamilyComboSp();
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt1.getName().add(new HumanName().setFamily("Family1"));
|
||||
IIdType id1 = myPatientDao.create(pt1, mySrd).getId().toUnqualified();
|
||||
assertNotNull(id1);
|
||||
|
||||
|
@ -1714,27 +1842,28 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
|
|||
pt1 = new Patient();
|
||||
pt1.setId(id1);
|
||||
pt1.setGender(Enumerations.AdministrativeGender.FEMALE);
|
||||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||
pt1.getName().add(new HumanName().setFamily("Family1"));
|
||||
id1 = myPatientDao.update(pt1, mySrd).getId().toUnqualified();
|
||||
assertNotNull(id1);
|
||||
assertEquals("2", id1.getVersionIdPart());
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt2.setBirthDateElement(new DateType("2011-01-01"));
|
||||
pt2.getName().add(new HumanName().setFamily("Family1"));
|
||||
IIdType id2 = myPatientDao.create(pt2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
myMessages.clear();
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
params.add("birthdate", new DateParam("2011-01-01"));
|
||||
params.add("family", new StringParam("Family1"));
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
String searchId = results.getUuid();
|
||||
assertThat(searchId).isNotBlank();
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results)).containsExactlyInAnyOrder(id2.getValue());
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale");
|
||||
assertThat(myMessages.toString()).contains("Using UNIQUE index(es) for query for search: " +
|
||||
"Patient?family=Family1&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale");
|
||||
myMessages.clear();
|
||||
|
||||
}
|
||||
|
|
|
@ -254,9 +254,9 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
|
|||
// check the 2 parameters are different
|
||||
// when fetched from the system
|
||||
RuntimeSearchParam paramdefault = mySearchParamRegistry.getActiveSearchParam("Patient",
|
||||
"fuzzydefault");
|
||||
"fuzzydefault", null);
|
||||
RuntimeSearchParam parammodified = mySearchParamRegistry.getActiveSearchParam("Patient",
|
||||
"fuzzymodified");
|
||||
"fuzzymodified", null);
|
||||
|
||||
// verify the encoders are different!
|
||||
assertThat(parammodified).isNotEqualTo(paramdefault);
|
||||
|
@ -594,7 +594,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
|
|||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Patient", "family");
|
||||
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Patient", "family", null);
|
||||
assertEquals(RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, sp.getStatus());
|
||||
}
|
||||
|
||||
|
|
|
@ -413,7 +413,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
p.getMeta().addTag("http://system", "code", "diisplay");
|
||||
p.addName().setFamily("FAM");
|
||||
p.addIdentifier().setSystem("system").setValue("value");
|
||||
p.setBirthDateElement(new DateType("2020-01-01"));
|
||||
p.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
p.getManagingOrganization().setReferenceElement(orgId);
|
||||
Long patientId = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
|
@ -502,7 +502,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
p.getMeta().addTag("http://system", "code", "diisplay");
|
||||
p.addName().setFamily("FAM");
|
||||
p.addIdentifier().setSystem("system").setValue("value");
|
||||
p.setBirthDate(new Date());
|
||||
p.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
p.getManagingOrganization().setReferenceElement(orgId);
|
||||
Long patientId = myPatientDao.create(p, mySrd).getId().getIdPartAsLong();
|
||||
|
||||
|
@ -679,7 +679,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
p.getMeta().addTag("http://system", "code", "display");
|
||||
p.addName().setFamily("FAM");
|
||||
p.addIdentifier().setSystem("system").setValue("value");
|
||||
p.setBirthDate(new Date());
|
||||
p.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
p.getManagingOrganization().setReference(org.getId());
|
||||
input.addEntry()
|
||||
.setFullUrl(p.getId())
|
||||
|
@ -2541,14 +2541,14 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
public void testSearch_UniqueParam_SearchAllPartitions() {
|
||||
createUniqueComboSp();
|
||||
|
||||
IIdType id = createPatient(withPartition(1), withBirthdate("2020-01-01"), withFamily("FAM"));
|
||||
IIdType id = createPatient(withPartition(1), withGender("male"), withFamily("FAM"));
|
||||
|
||||
addReadAllPartitions();
|
||||
|
||||
myCaptureQueriesListener.clear();
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add(Patient.SP_FAMILY, new StringParam("FAM"));
|
||||
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
|
||||
map.add(Patient.SP_GENDER, new TokenParam(null, "male"));
|
||||
map.setLoadSynchronous(true);
|
||||
IBundleProvider results = myPatientDao.search(map, mySrd);
|
||||
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
|
||||
|
@ -2558,7 +2558,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
|
||||
ourLog.info("Search SQL:\n{}", searchSql);
|
||||
assertThat(searchSql).doesNotContain("PARTITION_ID");
|
||||
assertThat(searchSql).containsOnlyOnce("IDX_STRING = 'Patient?birthdate=2020-01-01&family=FAM'");
|
||||
assertThat(searchSql).containsOnlyOnce("IDX_STRING = 'Patient?family=FAM&gender=male'");
|
||||
}
|
||||
|
||||
|
||||
|
@ -2566,13 +2566,13 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
public void testSearch_UniqueParam_SearchOnePartition() {
|
||||
createUniqueComboSp();
|
||||
|
||||
IIdType id = createPatient(withPartition(1), withBirthdate("2020-01-01"), withFamily("FAM"));
|
||||
IIdType id = createPatient(withPartition(1), withGender("male"), withFamily("FAM"));
|
||||
|
||||
addReadPartition(1);
|
||||
myCaptureQueriesListener.clear();
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add(Patient.SP_FAMILY, new StringParam("FAM"));
|
||||
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
|
||||
map.add(Patient.SP_GENDER, new TokenParam(null, "male"));
|
||||
map.setLoadSynchronous(true);
|
||||
IBundleProvider results = myPatientDao.search(map, mySrd);
|
||||
List<IIdType> ids = toUnqualifiedVersionlessIds(results);
|
||||
|
@ -2582,13 +2582,13 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
String searchSql = myCaptureQueriesListener.getSelectQueriesForCurrentThread().get(0).getSql(true, true);
|
||||
ourLog.info("Search SQL:\n{}", searchSql);
|
||||
assertThat(searchSql).containsOnlyOnce( "PARTITION_ID = '1'");
|
||||
assertThat(searchSql).containsOnlyOnce("IDX_STRING = 'Patient?birthdate=2020-01-01&family=FAM'");
|
||||
assertThat(searchSql).containsOnlyOnce("IDX_STRING = 'Patient?family=FAM&gender=male'");
|
||||
|
||||
// Same query, different partition
|
||||
addReadPartition(2);
|
||||
myCaptureQueriesListener.clear();
|
||||
map = new SearchParameterMap();
|
||||
map.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-01"));
|
||||
map.add(Patient.SP_GENDER, new TokenParam(null, "male"));
|
||||
map.setLoadSynchronous(true);
|
||||
results = myPatientDao.search(map, mySrd);
|
||||
ids = toUnqualifiedVersionlessIds(results);
|
||||
|
@ -2661,7 +2661,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
public void testSearch_RefParam_TargetPid_SearchOnePartition() {
|
||||
createUniqueComboSp();
|
||||
|
||||
IIdType patientId = createPatient(withPartition(myPartitionId), withBirthdate("2020-01-01"));
|
||||
IIdType patientId = createPatient(withPartition(myPartitionId), withGender("male"));
|
||||
IIdType observationId = createObservation(withPartition(myPartitionId), withSubject(patientId));
|
||||
|
||||
addReadPartition(myPartitionId);
|
||||
|
@ -2698,7 +2698,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
public void testSearch_RefParam_TargetPid_SearchDefaultPartition() {
|
||||
createUniqueComboSp();
|
||||
|
||||
IIdType patientId = createPatient(withPartition(null), withBirthdate("2020-01-01"));
|
||||
IIdType patientId = createPatient(withPartition(null), withGender("male"));
|
||||
IIdType observationId = createObservation(withPartition(null), withSubject(patientId));
|
||||
|
||||
addReadDefaultPartition();
|
||||
|
@ -2735,7 +2735,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
public void testSearch_RefParam_TargetForcedId_SearchOnePartition() {
|
||||
createUniqueComboSp();
|
||||
|
||||
IIdType patientId = createPatient(withPartition(myPartitionId), withId("ONE"), withBirthdate("2020-01-01"));
|
||||
IIdType patientId = createPatient(withPartition(myPartitionId), withId("ONE"), withGender("male"));
|
||||
IIdType observationId = createObservation(withPartition(myPartitionId), withSubject(patientId));
|
||||
|
||||
addReadPartition(myPartitionId);
|
||||
|
@ -2805,7 +2805,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
public void testSearch_RefParam_TargetForcedId_SearchDefaultPartition() {
|
||||
createUniqueComboSp();
|
||||
|
||||
IIdType patientId = createPatient(withPartition(null), withId("ONE"), withBirthdate("2020-01-01"));
|
||||
IIdType patientId = createPatient(withPartition(null), withId("ONE"), withGender("male"));
|
||||
IIdType observationId = createObservation(withPartition(null), withSubject(patientId));
|
||||
|
||||
addReadDefaultPartition();
|
||||
|
|
|
@ -133,7 +133,7 @@ public class SearchParamExtractorR4Test implements ITestDataBuilder {
|
|||
|
||||
@Test
|
||||
public void testTokenText_DisabledInSearchParam_Coding() {
|
||||
RuntimeSearchParam existingCodeSp = mySearchParamRegistry.getActiveSearchParams("Observation").get("code");
|
||||
RuntimeSearchParam existingCodeSp = mySearchParamRegistry.getActiveSearchParams("Observation", null).get("code");
|
||||
RuntimeSearchParam codeSearchParam = new RuntimeSearchParam(existingCodeSp);
|
||||
codeSearchParam.addExtension(HapiExtensions.EXT_SEARCHPARAM_TOKEN_SUPPRESS_TEXT_INDEXING, new Extension(HapiExtensions.EXT_SEARCHPARAM_TOKEN_SUPPRESS_TEXT_INDEXING, new BooleanType(true)));
|
||||
mySearchParamRegistry.addSearchParam(codeSearchParam);
|
||||
|
@ -186,7 +186,7 @@ public class SearchParamExtractorR4Test implements ITestDataBuilder {
|
|||
StorageSettings storageSettings = new StorageSettings();
|
||||
storageSettings.setSuppressStringIndexingInTokens(true);
|
||||
|
||||
RuntimeSearchParam existingCodeSp = mySearchParamRegistry.getActiveSearchParams("Observation").get("code");
|
||||
RuntimeSearchParam existingCodeSp = mySearchParamRegistry.getActiveSearchParams("Observation", null).get("code");
|
||||
RuntimeSearchParam codeSearchParam = new RuntimeSearchParam(existingCodeSp);
|
||||
codeSearchParam.addExtension(HapiExtensions.EXT_SEARCHPARAM_TOKEN_SUPPRESS_TEXT_INDEXING, new Extension(HapiExtensions.EXT_SEARCHPARAM_TOKEN_SUPPRESS_TEXT_INDEXING, new BooleanType(false)));
|
||||
mySearchParamRegistry.addSearchParam(codeSearchParam);
|
||||
|
@ -220,7 +220,7 @@ public class SearchParamExtractorR4Test implements ITestDataBuilder {
|
|||
enc.addLocation().setLocation(new Reference("Location/123"));
|
||||
|
||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new StorageSettings(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Encounter", "location");
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Encounter", "location", null);
|
||||
assertNotNull(param);
|
||||
ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(enc, false);
|
||||
assertThat(links).hasSize(1);
|
||||
|
@ -235,7 +235,7 @@ public class SearchParamExtractorR4Test implements ITestDataBuilder {
|
|||
consent.setSource(new Reference().setReference("Consent/999"));
|
||||
|
||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new StorageSettings(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Consent", Consent.SP_SOURCE_REFERENCE);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Consent", Consent.SP_SOURCE_REFERENCE, null);
|
||||
assertNotNull(param);
|
||||
ISearchParamExtractor.SearchParamSet<PathAndRef> links = extractor.extractResourceLinks(consent, false);
|
||||
assertThat(links).hasSize(1);
|
||||
|
@ -250,7 +250,7 @@ public class SearchParamExtractorR4Test implements ITestDataBuilder {
|
|||
p.addIdentifier().setSystem("sys").setValue("val");
|
||||
|
||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new StorageSettings(), new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Patient", Patient.SP_IDENTIFIER);
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Patient", Patient.SP_IDENTIFIER, null);
|
||||
assertNotNull(param);
|
||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> params = extractor.extractSearchParamTokens(p, param);
|
||||
assertThat(params).hasSize(1);
|
||||
|
@ -325,7 +325,7 @@ public class SearchParamExtractorR4Test implements ITestDataBuilder {
|
|||
.setCode(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("code1")))
|
||||
.setValue(new Quantity().setSystem(UcumServiceUtil.UCUM_CODESYSTEM_URL).setCode("cm").setValue(200));
|
||||
|
||||
RuntimeSearchParam existingCodeSp = mySearchParamRegistry.getActiveSearchParams("Observation").get("component-value-quantity");
|
||||
RuntimeSearchParam existingCodeSp = mySearchParamRegistry.getActiveSearchParams("Observation", null).get("component-value-quantity");
|
||||
|
||||
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(storageSettings, new PartitionSettings(), ourCtx, mySearchParamRegistry);
|
||||
List<String> list = extractor.extractParamValuesAsStrings(existingCodeSp, o1);
|
||||
|
@ -363,8 +363,8 @@ public class SearchParamExtractorR4Test implements ITestDataBuilder {
|
|||
.stream()
|
||||
.map(t->(ResourceIndexedSearchParamToken)t)
|
||||
.collect(Collectors.toList());
|
||||
list.forEach(t->t.calculateHashes());
|
||||
ourLog.info("Found tokens:\n * {}", list.stream().map(t->t.toString()).collect(Collectors.joining("\n * ")));
|
||||
list.forEach(ResourceIndexedSearchParamToken::calculateHashes);
|
||||
ourLog.info("Found tokens:\n * {}", list.stream().map(ResourceIndexedSearchParamToken::toString).collect(Collectors.joining("\n * ")));
|
||||
|
||||
assertThat(list).containsExactlyInAnyOrder(new ResourceIndexedSearchParamToken(new PartitionSettings(), "Patient", "deceased", null, "false"), new ResourceIndexedSearchParamToken(new PartitionSettings(), "Patient", "identifier", "http://foo1", "bar1"), new ResourceIndexedSearchParamToken(new PartitionSettings(), "Patient", "identifier", "http://foo2", "bar2"), new ResourceIndexedSearchParamToken(new PartitionSettings(), "Patient", "identifier:of-type", "http://terminology.hl7.org/CodeSystem/v2-0203", "MR|bar1"), new ResourceIndexedSearchParamToken(new PartitionSettings(), "Patient", "identifier:of-type", "http://terminology.hl7.org/CodeSystem/v2-0203", "MR|bar2"));
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv
|
|||
|
||||
myBatch2JobHelper.awaitJobCompletion(jobId.getValue());
|
||||
|
||||
ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation").getSearchParamNames());
|
||||
ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation", null).getSearchParamNames());
|
||||
logAllTokenIndexes();
|
||||
|
||||
|
||||
|
@ -196,7 +196,7 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv
|
|||
|
||||
myBatch2JobHelper.awaitJobCompletion(jobId.getValue());
|
||||
|
||||
ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation").getSearchParamNames());
|
||||
ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation", null).getSearchParamNames());
|
||||
logAllTokenIndexes();
|
||||
|
||||
runInTransaction(() -> {
|
||||
|
@ -224,7 +224,7 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv
|
|||
doCreateResource(reindexTestHelper.buildObservationWithAlleleExtension(Observation.ObservationStatus.CANCELLED));
|
||||
|
||||
reindexTestHelper.createAlleleSearchParameter();
|
||||
ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation").getSearchParamNames());
|
||||
ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation", null).getSearchParamNames());
|
||||
|
||||
// The searchparam value is on the observation, but it hasn't been indexed yet
|
||||
myTenantClientInterceptor.setTenantId(TENANT_A);
|
||||
|
|
|
@ -403,7 +403,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
|
|||
mySearchParameterDao.create(fooSp, mySrd);
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
assertNotNull(mySearchParamRegistry.getActiveSearchParam("Patient", "foo"));
|
||||
assertNotNull(mySearchParamRegistry.getActiveSearchParam("Patient", "foo", null));
|
||||
|
||||
Patient pat = new Patient();
|
||||
pat.setGender(AdministrativeGender.MALE);
|
||||
|
|
|
@ -353,7 +353,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
IFhirResourceDao<SearchParameter> searchParameterDao = myDaoRegistry.getResourceDao(SearchParameter.class);
|
||||
searchParameterDao.create(searchParameter, (RequestDetails) null);
|
||||
|
||||
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Organization", "_profile");
|
||||
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Organization", "_profile", null);
|
||||
assertNotNull(sp);
|
||||
|
||||
IFhirResourceDao<Organization> organizationDao = myDaoRegistry.getResourceDao(Organization.class);
|
||||
|
|
|
@ -104,7 +104,7 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test implements IValueSet
|
|||
|
||||
@Test
|
||||
public void testValueSetUrlSP() {
|
||||
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("ValueSet", "url");
|
||||
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("ValueSet", "url", null);
|
||||
assertEquals("url", sp.getName());
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ public class UpliftedRefchainsAndChainedSortingR5Test extends BaseJpaR5Test {
|
|||
public void testCreate_BundleWithComposition_UsingSimpleUplift() {
|
||||
// Setup
|
||||
|
||||
RuntimeSearchParam subjectSp = mySearchParamRegistry.getRuntimeSearchParam("Bundle", "composition");
|
||||
RuntimeSearchParam subjectSp = mySearchParamRegistry.getRuntimeSearchParam("Bundle", "composition", null);
|
||||
SearchParameter sp = new SearchParameter();
|
||||
Extension upliftRefChain = sp.addExtension().setUrl(HapiExtensions.EXTENSION_SEARCHPARAM_UPLIFT_REFCHAIN);
|
||||
upliftRefChain.addExtension(HapiExtensions.EXTENSION_SEARCHPARAM_UPLIFT_REFCHAIN_PARAM_CODE, new CodeType("type"));
|
||||
|
@ -1058,7 +1058,7 @@ public class UpliftedRefchainsAndChainedSortingR5Test extends BaseJpaR5Test {
|
|||
}
|
||||
|
||||
private void createSearchParam_EncounterSubject_WithUpliftOnName() {
|
||||
RuntimeSearchParam subjectSp = mySearchParamRegistry.getRuntimeSearchParam("Encounter", "subject");
|
||||
RuntimeSearchParam subjectSp = mySearchParamRegistry.getRuntimeSearchParam("Encounter", "subject", null);
|
||||
SearchParameter sp = new SearchParameter();
|
||||
Extension upliftRefChain = sp.addExtension().setUrl(HapiExtensions.EXTENSION_SEARCHPARAM_UPLIFT_REFCHAIN);
|
||||
upliftRefChain.addExtension(HapiExtensions.EXTENSION_SEARCHPARAM_UPLIFT_REFCHAIN_PARAM_CODE, new CodeType("name"));
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
package ca.uhn.fhir.jpa.provider.r5;
|
||||
|
||||
import ca.uhn.fhir.batch2.jobs.reindex.ReindexAppCtx;
|
||||
import ca.uhn.fhir.batch2.jobs.reindex.ReindexJobParameters;
|
||||
import ca.uhn.fhir.batch2.model.JobInstanceStartRequest;
|
||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||
import ca.uhn.fhir.jpa.batch.models.Batch2JobStartResponse;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.test.Batch2JobHelper;
|
||||
import ca.uhn.fhir.jpa.test.util.ComboSearchParameterTestHelper;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.hl7.fhir.r5.model.BooleanType;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.SearchParameter;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.util.HapiExtensions.EXT_SEARCHPARAM_ENABLED_FOR_SEARCHING;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Named.named;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
public class SearchParameterDisabledForQueryingR5Test extends BaseResourceProviderR5Test {
|
||||
|
||||
@Autowired(required = false)
|
||||
protected Batch2JobHelper myBatch2JobHelper;
|
||||
private ComboSearchParameterTestHelper myComboSearchParameterTestHelper;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
myStorageSettings.setMarkResourcesForReindexingUponSearchParameterChange(false);
|
||||
myComboSearchParameterTestHelper = new ComboSearchParameterTestHelper(mySearchParameterDao, mySearchParamRegistry);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void afterEach() {
|
||||
JpaStorageSettings defaults = new JpaStorageSettings();
|
||||
myStorageSettings.setMarkResourcesForReindexingUponSearchParameterChange(defaults.isMarkResourcesForReindexingUponSearchParameterChange());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("standardSearchParameters")
|
||||
void testIndexAndSearch(TestParameters theParameters) {
|
||||
// Setup
|
||||
createPatient(withId("A"), withFamily("SIMPSON"), withGiven("HOMER"));
|
||||
|
||||
SearchParameter sp = theParameters.mySearchParameter;
|
||||
ourLog.info(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(sp));
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
// Test
|
||||
reindexAllPatientsAndWaitForCompletion();
|
||||
|
||||
// Verify
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedSearchParamString> indexes = myResourceIndexedSearchParamStringDao
|
||||
.findAll()
|
||||
.stream()
|
||||
.filter(t -> t.getParamName().equals(sp.getCode()))
|
||||
.toList();
|
||||
assertEquals(1, indexes.size());
|
||||
assertEquals(theParameters.myStringIndexValue, indexes.get(0).getValueNormalized());
|
||||
});
|
||||
|
||||
// Test
|
||||
try {
|
||||
Bundle outcome = myClient
|
||||
.search()
|
||||
.forResource("Patient")
|
||||
.where(new StringClientParam(sp.getCode()).matches().value(theParameters.myStringIndexValue))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
if (theParameters.myExpectedErrorCode == null) {
|
||||
assertEquals(1, outcome.getEntry().size());
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
} catch (InvalidRequestException e) {
|
||||
if (theParameters.myExpectedErrorCode != null) {
|
||||
String expectedErrorMessage = "HAPI-" + theParameters.myExpectedErrorCode + ": Search parameter \"" + sp.getCode() + "\" for resource type \"Patient\" is not active for searching";
|
||||
assertThat(e.getMessage()).contains(expectedErrorMessage);
|
||||
|
||||
String expectedValidParams = "Valid search parameters for this search are: [_id, _lastUpdated, _text, active, address, address-city, address-country, address-postalcode, address-state, address-use, birthdate, death-date, deceased, email, family, gender, general-practitioner, given, identifier, language, link, name, organization, part-agree, phone, phonetic, telecom]";
|
||||
if (theParameters.mySearchParameter.getCode().equals("family")) {
|
||||
expectedValidParams = expectedErrorMessage.replace(", family", "");
|
||||
}
|
||||
assertThat(e.getMessage()).contains(expectedValidParams);
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("standardSearchParameters")
|
||||
void testCapabilityStatement(TestParameters theParameters) {
|
||||
// Setup
|
||||
SearchParameter sp = theParameters.mySearchParameter;
|
||||
mySearchParameterDao.update(sp, mySrd);
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
// Test
|
||||
CapabilityStatement cs = myClient.capabilities().ofType(CapabilityStatement.class).execute();
|
||||
|
||||
// Verify
|
||||
CapabilityStatement.CapabilityStatementRestResourceComponent patient = cs.getRestFirstRep().getResource().stream().filter(t -> t.getType().equals("Patient")).findFirst().orElseThrow();
|
||||
Set<String> searchParamNames = patient.getSearchParam().stream().map(CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent::getName).collect(Collectors.toSet());
|
||||
if (theParameters.myEnabledForSearching == Boolean.FALSE) {
|
||||
assertThat(searchParamNames).doesNotContain(theParameters.mySearchParameter.getCode());
|
||||
} else {
|
||||
assertThat(searchParamNames).contains(theParameters.mySearchParameter.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
// theEnabledForSearching, theUnique
|
||||
" true , true",
|
||||
" false , true",
|
||||
" , true",
|
||||
" true , false",
|
||||
" false , false",
|
||||
" , false"
|
||||
})
|
||||
public void testComboUniqueSearchParameter(Boolean theEnabledForSearching, boolean theUnique) {
|
||||
myComboSearchParameterTestHelper.createBirthdateAndGenderSps(theUnique, t -> {
|
||||
if (theEnabledForSearching != null) {
|
||||
t.addExtension(EXT_SEARCHPARAM_ENABLED_FOR_SEARCHING, new BooleanType(theEnabledForSearching));
|
||||
}
|
||||
});
|
||||
|
||||
createPatient(withId("A"), withBirthdate("2020-01-02"), withGender("male"));
|
||||
// createPatient(withId("B"), withBirthdate("2020-01-02"), withGender("female"));
|
||||
|
||||
logAllDateIndexes();
|
||||
logAllTokenIndexes();
|
||||
logAllUniqueIndexes();
|
||||
|
||||
// Test
|
||||
SearchParameterMap map = SearchParameterMap
|
||||
.newSynchronous()
|
||||
.add(Patient.SP_BIRTHDATE, new DateParam("2020-01-02"))
|
||||
.add(Patient.SP_GENDER, new TokenParam( "male"));
|
||||
myCaptureQueriesListener.clear();
|
||||
IBundleProvider outcome = myPatientDao.search(map, mySrd);
|
||||
myCaptureQueriesListener.logSelectQueries();
|
||||
|
||||
// Verify
|
||||
assertThat(toUnqualifiedVersionlessIdValues(outcome)).containsExactly("Patient/A");
|
||||
String sql = myCaptureQueriesListener.getSelectQueries().get(0).getSql(true, true);
|
||||
|
||||
if (theEnabledForSearching == Boolean.FALSE) {
|
||||
assertThat(sql).contains(ResourceIndexedSearchParamToken.HFJ_SPIDX_TOKEN);
|
||||
assertThat(sql).doesNotContain(ResourceIndexedComboStringUnique.HFJ_IDX_CMP_STRING_UNIQ);
|
||||
assertThat(sql).doesNotContain(ResourceIndexedComboTokenNonUnique.HFJ_IDX_CMB_TOK_NU);
|
||||
} else {
|
||||
assertThat(sql).doesNotContain(ResourceIndexedSearchParamToken.HFJ_SPIDX_TOKEN);
|
||||
assertThat(sql).containsAnyOf(ResourceIndexedComboStringUnique.HFJ_IDX_CMP_STRING_UNIQ, ResourceIndexedComboTokenNonUnique.HFJ_IDX_CMB_TOK_NU);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void reindexAllPatientsAndWaitForCompletion() {
|
||||
ReindexJobParameters parameters = new ReindexJobParameters();
|
||||
parameters.addUrl("Patient?");
|
||||
|
||||
JobInstanceStartRequest startRequest = new JobInstanceStartRequest();
|
||||
startRequest.setJobDefinitionId(ReindexAppCtx.JOB_REINDEX);
|
||||
startRequest.setParameters(parameters);
|
||||
Batch2JobStartResponse res = myJobCoordinator.startInstance(mySrd, startRequest);
|
||||
myBatch2JobHelper.awaitJobCompletion(res);
|
||||
}
|
||||
|
||||
private static List<Arguments> standardSearchParameters() {
|
||||
return List.of(
|
||||
arguments(named("Custom/EnabledTrue", new TestParameters(createSearchParameterCustom(true), "SIMPSONHOMER", null))),
|
||||
arguments(named("Custom/EnabledFalse", new TestParameters(createSearchParameterCustom(false), "SIMPSONHOMER", 2539))),
|
||||
arguments(named("Custom/EnabledNull", new TestParameters(createSearchParameterCustom(null), "SIMPSONHOMER", null))),
|
||||
arguments(named("BuiltIn/EnabledTrue", new TestParameters(createSearchParameterBuiltIn(true), "SIMPSON", null))),
|
||||
arguments(named("BuiltIn/EnabledFalse", new TestParameters(createSearchParameterBuiltIn(false), "SIMPSON", 2540))),
|
||||
arguments(named("BuiltIn/EnabledNull", new TestParameters(createSearchParameterBuiltIn(null), "SIMPSON", null)))
|
||||
);
|
||||
}
|
||||
|
||||
private static @Nonnull SearchParameter createSearchParameterBuiltIn(Boolean theEnabledForSearching) {
|
||||
SearchParameter retVal = createSearchParameter(theEnabledForSearching, "family", "Patient.name.family");
|
||||
retVal.setId("individual-family");
|
||||
retVal.setUrl("http://hl7.org/fhir/SearchParameter/individual-family");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private static @Nonnull SearchParameter createSearchParameterCustom(Boolean theEnabledForSearching) {
|
||||
return createSearchParameter(theEnabledForSearching, "names", "Patient.name.family + Patient.name.given");
|
||||
}
|
||||
|
||||
private static SearchParameter createSearchParameter(Boolean theEnabledForSearching, String code, String expression) {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
if (theEnabledForSearching != null) {
|
||||
sp.addExtension(EXT_SEARCHPARAM_ENABLED_FOR_SEARCHING, new BooleanType(theEnabledForSearching));
|
||||
}
|
||||
sp.setId(code);
|
||||
sp.setName(code);
|
||||
sp.setCode(code);
|
||||
sp.setType(Enumerations.SearchParamType.STRING);
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.setExpression(expression);
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
|
||||
return sp;
|
||||
}
|
||||
|
||||
private static class TestParameters {
|
||||
private final SearchParameter mySearchParameter;
|
||||
private final String myStringIndexValue;
|
||||
private final Boolean myEnabledForSearching;
|
||||
private final Integer myExpectedErrorCode;
|
||||
|
||||
private TestParameters(SearchParameter theSearchParameter, String theStringIndexValue, Integer theExpectedErrorCode) {
|
||||
mySearchParameter = theSearchParameter;
|
||||
myStringIndexValue = theStringIndexValue;
|
||||
myExpectedErrorCode = theExpectedErrorCode;
|
||||
|
||||
Extension ext = mySearchParameter.getExtensionByUrl(EXT_SEARCHPARAM_ENABLED_FOR_SEARCHING);
|
||||
if (ext != null) {
|
||||
myEnabledForSearching = ext.getValueBooleanType().booleanValue();
|
||||
} else {
|
||||
myEnabledForSearching = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package ca.uhn.fhir.jpa.test.util;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r5.model.BooleanType;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
import org.hl7.fhir.r5.model.SearchParameter;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class ComboSearchParameterTestHelper {
|
||||
|
||||
|
||||
private final IFhirResourceDao mySearchParameterDao;
|
||||
private final VersionCanonicalizer myVersionCanonicalizer;
|
||||
private final ISearchParamRegistry mySearchParamRegistry;
|
||||
|
||||
public ComboSearchParameterTestHelper(IFhirResourceDao<?> theSearchParameterDao, ISearchParamRegistry theSearchParamRegistry) {
|
||||
mySearchParameterDao = theSearchParameterDao;
|
||||
mySearchParamRegistry = theSearchParamRegistry;
|
||||
|
||||
FhirContext context = mySearchParameterDao.getContext();
|
||||
myVersionCanonicalizer = new VersionCanonicalizer(context);
|
||||
|
||||
assertEquals("SearchParameter", context.getResourceType(mySearchParameterDao.getResourceType()));
|
||||
}
|
||||
|
||||
|
||||
public void createBirthdateAndGenderSps(boolean theUnique, ISearchParamCustomizer... theSearchParamCustomizer) {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-gender");
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setCode("gender");
|
||||
sp.setExpression("Patient.gender");
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
|
||||
mySearchParameterDao.update(fromCanonoical(sp), new SystemRequestDetails());
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-birthdate");
|
||||
sp.setType(Enumerations.SearchParamType.DATE);
|
||||
sp.setCode("birthdate");
|
||||
sp.setExpression("Patient.birthDate");
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
|
||||
mySearchParameterDao.update(fromCanonoical(sp), new SystemRequestDetails());
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-gender-birthdate");
|
||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
||||
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-gender");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-birthdate");
|
||||
sp.addExtension()
|
||||
.setUrl(HapiExtensions.EXT_SP_UNIQUE)
|
||||
.setValue(new BooleanType(true));
|
||||
for (var next : theSearchParamCustomizer) {
|
||||
next.accept(sp);
|
||||
}
|
||||
|
||||
mySearchParameterDao.update(fromCanonoical(sp), new SystemRequestDetails());
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
}
|
||||
|
||||
private IBaseResource fromCanonoical(SearchParameter theSearchParameter) {
|
||||
return myVersionCanonicalizer.searchParameterFromCanonical(theSearchParameter);
|
||||
}
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ISearchParamCustomizer {
|
||||
|
||||
void accept(SearchParameter theSearchParameter);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@ import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
|
|||
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.server.util.FhirContextSearchParamRegistry;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.rest.server.util.ResourceSearchParams;
|
||||
import ca.uhn.fhir.test.utilities.ITestDataBuilder;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
|
@ -51,7 +52,7 @@ class ExtendedHSearchIndexExtractorTest implements ITestDataBuilder.WithSupport
|
|||
extractedParams.myCompositeParams.add(composite);
|
||||
|
||||
// run: now translate to HSearch
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams("Observation");
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams("Observation", ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
ExtendedHSearchIndexExtractor extractor = new ExtendedHSearchIndexExtractor(
|
||||
myJpaStorageSettings, myFhirContext, activeSearchParams, mySearchParamExtractor);
|
||||
ExtendedHSearchIndexData indexData = extractor.extract(new Observation(), extractedParams);
|
||||
|
@ -74,7 +75,7 @@ class ExtendedHSearchIndexExtractorTest implements ITestDataBuilder.WithSupport
|
|||
searchParams.myQuantityParams.add(searchParamQuantity);
|
||||
|
||||
// run: now translate to HSearch
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams("Patient");
|
||||
ResourceSearchParams activeSearchParams = mySearchParamRegistry.getActiveSearchParams("Patient", ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
ExtendedHSearchIndexExtractor extractor = new ExtendedHSearchIndexExtractor(
|
||||
myJpaStorageSettings, myFhirContext, activeSearchParams, mySearchParamExtractor);
|
||||
ExtendedHSearchIndexData indexData = extractor.extract(new SearchParameter(), searchParams);
|
||||
|
|
|
@ -40,6 +40,7 @@ import static org.hl7.fhir.r5.model.Enumerations.SearchParamType.URI;
|
|||
import static org.hl7.fhir.r5.model.Enumerations.VersionIndependentResourceTypesAll.OBSERVATION;
|
||||
import static org.hl7.fhir.r5.model.Enumerations.VersionIndependentResourceTypesAll.PATIENT;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
|
||||
|
@ -78,7 +79,7 @@ public class SearchParameterDaoValidatorTest {
|
|||
private void createAndMockSearchParameter(Enumerations.SearchParamType theType, String theDefinition, String theCodeValue, String theExpression) {
|
||||
SearchParameter observationCodeSp = createSearchParameter(theType, theDefinition, theCodeValue, theExpression);
|
||||
RuntimeSearchParam observationCodeRuntimeSearchParam = mySearchParameterCanonicalizer.canonicalizeSearchParameter(observationCodeSp);
|
||||
lenient().when(mySearchParamRegistry.getActiveSearchParamByUrl(eq(theDefinition))).thenReturn(observationCodeRuntimeSearchParam);
|
||||
lenient().when(mySearchParamRegistry.getActiveSearchParamByUrl(eq(theDefinition), any())).thenReturn(observationCodeRuntimeSearchParam);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -34,7 +34,9 @@ import java.util.UUID;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyCollection;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -111,7 +113,7 @@ public class ResourceLinkPredicateBuilderTest {
|
|||
String resourceType = "Bundle";
|
||||
RuntimeSearchParam mockSearchParam = mock(RuntimeSearchParam.class);
|
||||
when(mockSearchParam.getPathsSplit()).thenReturn(List.of("Patient.given", "Bundle.composition.subject", "Bundle.type"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam(resourceType, paramName)).thenReturn(mockSearchParam);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq(resourceType), eq(paramName), any())).thenReturn(mockSearchParam);
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of());
|
||||
assertThat(result).containsExactlyInAnyOrder("Bundle.composition.subject", "Bundle.type");
|
||||
}
|
||||
|
@ -128,14 +130,14 @@ public class ResourceLinkPredicateBuilderTest {
|
|||
public void createResourceLinkPaths_withChainAndSearchParameterFoundNoQualifiers_returnsPath() {
|
||||
String paramName = "subject.identifier";
|
||||
String resourceType = "Observation";
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject.identifier")).thenReturn(null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("subject.identifier"), any())).thenReturn(null);
|
||||
RuntimeSearchParam observationSubjectSP = mock(RuntimeSearchParam.class);
|
||||
when(observationSubjectSP.getPathsSplit()).thenReturn(List.of("Observation.subject"));
|
||||
when(observationSubjectSP.getTargets()).thenReturn(Set.of("Patient"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject")).thenReturn(observationSubjectSP);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("subject"), any())).thenReturn(observationSubjectSP);
|
||||
RuntimeSearchParam patientIdentifierSP = mock(RuntimeSearchParam.class);
|
||||
when(patientIdentifierSP.getPathsSplit()).thenReturn(List.of("Patient.identifier"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Patient", "identifier")).thenReturn(patientIdentifierSP);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Patient"),eq( "identifier"), any())).thenReturn(patientIdentifierSP);
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of());
|
||||
assertThat(result).containsExactlyInAnyOrder("Observation.subject.identifier");
|
||||
}
|
||||
|
@ -145,23 +147,23 @@ public class ResourceLinkPredicateBuilderTest {
|
|||
String paramName = "subject.managingOrganization.identifier";
|
||||
String resourceType = "Observation";
|
||||
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject.managingOrganization.identifier")).thenReturn(null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("subject.managingOrganization.identifier"), any())).thenReturn(null);
|
||||
|
||||
RuntimeSearchParam observationSubjectSP = mock(RuntimeSearchParam.class);
|
||||
when(observationSubjectSP.getPathsSplit()).thenReturn(List.of("Observation.subject"));
|
||||
when(observationSubjectSP.getTargets()).thenReturn(Set.of("Patient"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject")).thenReturn(observationSubjectSP);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("subject"), any())).thenReturn(observationSubjectSP);
|
||||
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Patient", "managingOrganization.identifier")).thenReturn(null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Patient"), eq("managingOrganization.identifier"), any())).thenReturn(null);
|
||||
|
||||
RuntimeSearchParam organizationSP = mock(RuntimeSearchParam.class);
|
||||
when(organizationSP.getPathsSplit()).thenReturn(List.of("Patient.managingOrganization"));
|
||||
when(organizationSP.getTargets()).thenReturn(Set.of("Organization"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Patient", "managingOrganization")).thenReturn(organizationSP);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Patient"), eq("managingOrganization"), any())).thenReturn(organizationSP);
|
||||
|
||||
RuntimeSearchParam organizationIdentifierSP = mock(RuntimeSearchParam.class);
|
||||
when(organizationIdentifierSP.getPathsSplit()).thenReturn(List.of("Organization.identifier"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Organization", "identifier")).thenReturn(organizationIdentifierSP);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Organization"), eq("identifier"), any())).thenReturn(organizationIdentifierSP);
|
||||
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of("Patient", "Organization"));
|
||||
assertThat(result).containsExactlyInAnyOrder("Observation.subject.managingOrganization.identifier");
|
||||
|
@ -171,11 +173,11 @@ public class ResourceLinkPredicateBuilderTest {
|
|||
public void createResourceLinkPaths_withChainAndSearchParameterFoundWithNonMatchingQualifier_returnsEmpty() {
|
||||
String paramName = "subject.identifier";
|
||||
String resourceType = "Observation";
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject.identifier")).thenReturn(null);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("subject.identifier"), any())).thenReturn(null);
|
||||
RuntimeSearchParam observationSubjectSP = mock(RuntimeSearchParam.class);
|
||||
when(observationSubjectSP.getPathsSplit()).thenReturn(List.of("Observation.subject"));
|
||||
when(observationSubjectSP.getTargets()).thenReturn(Set.of("Patient"));
|
||||
when(mySearchParamRegistry.getActiveSearchParam("Observation", "subject")).thenReturn(observationSubjectSP);
|
||||
when(mySearchParamRegistry.getActiveSearchParam(eq("Observation"), eq("subject"), any())).thenReturn(observationSubjectSP);
|
||||
List<String> result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of("Group"));
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ public class MdmRuleValidator implements IMdmRuleValidator {
|
|||
mySearchParamRetriever = theSearchParamRetriever;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(MdmRulesJson theMdmRules) {
|
||||
validateMdmTypes(theMdmRules);
|
||||
validateSearchParams(theMdmRules);
|
||||
|
@ -127,7 +128,9 @@ public class MdmRuleValidator implements IMdmRuleValidator {
|
|||
}
|
||||
|
||||
public void validateTypeHasIdentifier(String theResourceType) {
|
||||
if (mySearchParamRetriever.getActiveSearchParam(theResourceType, "identifier") == null) {
|
||||
if (mySearchParamRetriever.getActiveSearchParam(
|
||||
theResourceType, "identifier", ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
== null) {
|
||||
throw new ConfigurationException(
|
||||
Msg.code(1510) + "Resource Type " + theResourceType
|
||||
+ " is not supported, as it does not have an 'identifier' field, which is necessary for MDM workflow.");
|
||||
|
@ -162,7 +165,9 @@ public class MdmRuleValidator implements IMdmRuleValidator {
|
|||
|
||||
private void validateResourceSearchParam(String theFieldName, String theResourceType, String theSearchParam) {
|
||||
String searchParam = SearchParameterUtil.stripModifier(theSearchParam);
|
||||
if (mySearchParamRetriever.getActiveSearchParam(theResourceType, searchParam) == null) {
|
||||
if (mySearchParamRetriever.getActiveSearchParam(
|
||||
theResourceType, searchParam, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
== null) {
|
||||
throw new ConfigurationException(Msg.code(1511) + "Error in " + theFieldName + ": " + theResourceType
|
||||
+ " does not have a search parameter called '" + theSearchParam + "'");
|
||||
}
|
||||
|
|
|
@ -67,7 +67,8 @@ public class MdmSearchParamSvc {
|
|||
public List<String> getValueFromResourceForSearchParam(IBaseResource theResource, String theSearchParam) {
|
||||
String resourceType = myFhirContext.getResourceType(theResource);
|
||||
String searchParam = SearchParameterUtil.stripModifier(theSearchParam);
|
||||
RuntimeSearchParam activeSearchParam = mySearchParamRegistry.getActiveSearchParam(resourceType, searchParam);
|
||||
RuntimeSearchParam activeSearchParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
resourceType, searchParam, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
return mySearchParamExtractorService.extractParamValuesAsStrings(activeSearchParam, theResource);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,19 +16,23 @@ import java.io.IOException;
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class MdmRuleValidatorTest extends BaseR4Test {
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Practitioner", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Medication", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("AllergyIntolerance", "identifier")).thenReturn(null);
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Organization", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Organization", "active")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
super.before();
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Practitioner"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Medication"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("AllergyIntolerance"), eq("identifier"), any())).thenReturn(null);
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Organization"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Organization"), eq("active"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -15,6 +15,8 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -30,13 +32,14 @@ public class CustomResourceMatcherR4Test extends BaseR4Test {
|
|||
private static Patient ourHenryJohn;
|
||||
private static Patient ourHenryJOHN;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
super.before();
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Practitioner", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Medication", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("AllergyIntolerance", "identifier")).thenReturn(null);
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Practitioner"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Medication"),eq( "identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("AllergyIntolerance"), eq("identifier"), any())).thenReturn(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -14,6 +14,8 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -26,9 +28,9 @@ public class FhirPathResourceMatcherR4Test extends BaseMdmRulesR4Test {
|
|||
@BeforeEach
|
||||
public void before() {
|
||||
super.before();
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "birthdate")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "active")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("birthdate"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("active"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
|
||||
{
|
||||
myLeft = new Patient();
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -26,11 +28,11 @@ public class MdmResourceMatcherSvcLoggingTest extends BaseMdmRulesR4Test {
|
|||
public void before() {
|
||||
super.before();
|
||||
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "birthdate")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Practitioner", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Medication", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "active")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("birthdate"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Practitioner"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Medication"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("active"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
|
||||
myMdmResourceMatcherSvc = buildMatcher(buildActiveBirthdateIdRules());
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ import org.hl7.fhir.r4.model.Patient;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -20,11 +22,11 @@ public class MdmResourceMatcherSvcR4Test extends BaseMdmRulesR4Test {
|
|||
public void before() {
|
||||
super.before();
|
||||
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "birthdate")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Practitioner", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Medication", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "active")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("birthdate"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Practitioner"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Medication"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("active"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
|
||||
myMdmResourceMatcherSvc = buildMatcher(buildActiveBirthdateIdRules());
|
||||
|
||||
|
|
|
@ -47,11 +47,11 @@ public class ResourceMatcherR4Test extends BaseMdmRulesR4Test {
|
|||
public void before() {
|
||||
super.before();
|
||||
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "birthdate")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Practitioner", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Medication", "identifier")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "active")).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("birthdate"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Practitioner"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Medication"), eq("identifier"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("active"), any())).thenReturn(mock(RuntimeSearchParam.class));
|
||||
|
||||
{
|
||||
myLeft = new Patient();
|
||||
|
|
|
@ -22,6 +22,8 @@ import static ca.uhn.fhir.mdm.api.MdmConstants.HAPI_ENTERPRISE_IDENTIFIER_SYSTEM
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
|
@ -41,9 +43,11 @@ public class EIDHelperR4Test extends BaseR4Test {
|
|||
|
||||
private EIDHelper myEidHelper;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier"))
|
||||
super.before();
|
||||
when(mySearchParamRetriever.getActiveSearchParam(eq("Patient"), eq("identifier"), any()))
|
||||
.thenReturn(new RuntimeSearchParam(null, null, "identifier", "Description", "identifier", RestSearchParameterTypeEnum.STRING, new HashSet<>(), new HashSet<>(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null));
|
||||
|
||||
myMdmSettings = new MdmSettings(new MdmRuleValidator(ourFhirContext, mySearchParamRetriever)) {
|
||||
|
|
|
@ -420,12 +420,14 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
|
||||
return getActiveSearchParams(theResourceName).get(theParamName);
|
||||
public RuntimeSearchParam getActiveSearchParam(
|
||||
String theResourceName, String theParamName, SearchParamLookupContextEnum theContext) {
|
||||
return getActiveSearchParams(theResourceName, theContext).get(theParamName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceSearchParams getActiveSearchParams(@Nonnull String theResourceName) {
|
||||
public ResourceSearchParams getActiveSearchParams(
|
||||
@Nonnull String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
Validate.notBlank(theResourceName, "theResourceName must not be null or blank");
|
||||
|
||||
ResourceSearchParams retval = new ResourceSearchParams(theResourceName);
|
||||
|
@ -442,7 +444,7 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
|
||||
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException(Msg.code(286));
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,8 @@ public class SearchPreferHandlingInterceptor {
|
|||
}
|
||||
}
|
||||
|
||||
RuntimeSearchParam activeSearchParam = searchParamRetriever.getActiveSearchParam(resourceName, paramName);
|
||||
RuntimeSearchParam activeSearchParam = searchParamRetriever.getActiveSearchParam(
|
||||
resourceName, paramName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (activeSearchParam == null) {
|
||||
|
||||
if (theHandling == PreferHandlingEnum.LENIENT) {
|
||||
|
@ -144,11 +145,14 @@ public class SearchPreferHandlingInterceptor {
|
|||
} else {
|
||||
|
||||
// Strict handling
|
||||
List<String> allowedParams =
|
||||
searchParamRetriever.getActiveSearchParams(resourceName).getSearchParamNames().stream()
|
||||
.sorted()
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
List<String> allowedParams = searchParamRetriever
|
||||
.getActiveSearchParams(
|
||||
resourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.getSearchParamNames()
|
||||
.stream()
|
||||
.sorted()
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
HapiLocalizer localizer = theRequestDetails.getFhirContext().getLocalizer();
|
||||
String msg = localizer.getMessage(
|
||||
"ca.uhn.fhir.jpa.dao.BaseStorageDao.invalidSearchParameter",
|
||||
|
|
|
@ -318,6 +318,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
|||
case UPDATE:
|
||||
terser.setElement(resource, "conditionalUpdate", "true");
|
||||
break;
|
||||
case UPDATE_REWRITE_HISTORY:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
|
@ -401,12 +402,13 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
|||
*/
|
||||
ResourceSearchParams searchParams;
|
||||
ISearchParamRegistry searchParamRegistry;
|
||||
ResourceSearchParams serverConfigurationActiveSearchParams =
|
||||
serverConfiguration.getActiveSearchParams(resourceName);
|
||||
ResourceSearchParams serverConfigurationActiveSearchParams = serverConfiguration.getActiveSearchParams(
|
||||
resourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
if (mySearchParamRegistry != null) {
|
||||
searchParamRegistry = mySearchParamRegistry;
|
||||
searchParams = mySearchParamRegistry
|
||||
.getActiveSearchParams(resourceName)
|
||||
.getActiveSearchParams(
|
||||
resourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.makeCopy();
|
||||
for (String nextBuiltInSpName : serverConfigurationActiveSearchParams.getSearchParamNames()) {
|
||||
if (nextBuiltInSpName.startsWith("_")
|
||||
|
@ -465,7 +467,8 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
|||
}
|
||||
|
||||
for (RuntimeSearchParam t : searchParamRegistry
|
||||
.getActiveSearchParams(nextResourceName)
|
||||
.getActiveSearchParams(
|
||||
nextResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH)
|
||||
.values()) {
|
||||
if (t.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
||||
if (isNotBlank(t.getName())) {
|
||||
|
|
|
@ -35,6 +35,8 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static ca.uhn.fhir.rest.server.util.ISearchParamRegistry.isAllowedForContext;
|
||||
|
||||
public class FhirContextSearchParamRegistry implements ISearchParamRegistry {
|
||||
|
||||
private final List<RuntimeSearchParam> myExtraSearchParams = new ArrayList<>();
|
||||
|
@ -54,20 +56,25 @@ public class FhirContextSearchParamRegistry implements ISearchParamRegistry {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
|
||||
return getActiveSearchParams(theResourceName).get(theParamName);
|
||||
public RuntimeSearchParam getActiveSearchParam(
|
||||
String theResourceName, String theParamName, SearchParamLookupContextEnum theContext) {
|
||||
return getActiveSearchParams(theResourceName, theContext).get(theParamName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceSearchParams getActiveSearchParams(String theResourceName) {
|
||||
public ResourceSearchParams getActiveSearchParams(String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
ResourceSearchParams retval = new ResourceSearchParams(theResourceName);
|
||||
RuntimeResourceDefinition nextResDef = myCtx.getResourceDefinition(theResourceName);
|
||||
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
|
||||
retval.put(nextSp.getName(), nextSp);
|
||||
if (isAllowedForContext(nextSp, theContext)) {
|
||||
retval.put(nextSp.getName(), nextSp);
|
||||
}
|
||||
}
|
||||
|
||||
for (RuntimeSearchParam next : myExtraSearchParams) {
|
||||
retval.put(next.getName(), next);
|
||||
if (isAllowedForContext(next, theContext)) {
|
||||
retval.put(next.getName(), next);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -78,29 +85,31 @@ public class FhirContextSearchParamRegistry implements ISearchParamRegistry {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, Set<String> theParamNames, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException(Msg.code(2066));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
|
||||
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl, SearchParamLookupContextEnum theContext) {
|
||||
// simple implementation for test support
|
||||
return myCtx.getResourceTypes().stream()
|
||||
.flatMap(type -> getActiveSearchParams(type).values().stream())
|
||||
.flatMap(type -> getActiveSearchParams(type, theContext).values().stream())
|
||||
.filter(rsp -> theUrl.equals(rsp.getUri()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException(Msg.code(2068));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, ComboSearchParamType theParamType) {
|
||||
String theResourceName, ComboSearchParamType theParamType, SearchParamLookupContextEnum theContext) {
|
||||
throw new UnsupportedOperationException(Msg.code(2209));
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
|
|||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import jakarta.annotation.Nullable;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -50,14 +51,18 @@ public interface ISearchParamRegistry {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param theContext The context to return active search params for, or {@literal null} to return any active search params
|
||||
* @return Returns {@literal null} if no match
|
||||
*/
|
||||
RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName);
|
||||
RuntimeSearchParam getActiveSearchParam(
|
||||
String theResourceName, String theParamName, @Nullable SearchParamLookupContextEnum theContext);
|
||||
|
||||
/**
|
||||
* @param theContext The context to return active search params for, or {@literal null} to return any active search params
|
||||
* @return Returns all active search params for the given resource
|
||||
*/
|
||||
ResourceSearchParams getActiveSearchParams(String theResourceName);
|
||||
ResourceSearchParams getActiveSearchParams(
|
||||
String theResourceName, @Nullable SearchParamLookupContextEnum theContext);
|
||||
|
||||
/**
|
||||
* Request that the cache be refreshed now, in the current thread
|
||||
|
@ -77,13 +82,17 @@ public interface ISearchParamRegistry {
|
|||
*/
|
||||
default void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) {}
|
||||
|
||||
default List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
/**
|
||||
* @param theContext The context to return active search params for, or {@literal null} to return any active search params
|
||||
*/
|
||||
default List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// TODO ND remove default implementation
|
||||
default List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, ComboSearchParamType theParamType) {
|
||||
String theResourceName, ComboSearchParamType theParamType, SearchParamLookupContextEnum theContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
@ -92,7 +101,11 @@ public interface ISearchParamRegistry {
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
default List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
/**
|
||||
* @param theContext The context to return active search params for, or {@literal null} to return any active search params
|
||||
*/
|
||||
default List<RuntimeSearchParam> getActiveComboSearchParams(
|
||||
String theResourceName, Set<String> theParamNames, SearchParamLookupContextEnum theContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
@ -100,10 +113,13 @@ public interface ISearchParamRegistry {
|
|||
* Returns a collection containing all of the valid active search parameters. This method is intended for
|
||||
* creating error messages for users as opposed to actual search processing. It will include meta parameters
|
||||
* such as <code>_id</code> and <code>_lastUpdated</code>.
|
||||
*
|
||||
* @param theContext The context to return active search params for, or {@literal null} to return any active search params
|
||||
*/
|
||||
default Collection<String> getValidSearchParameterNamesIncludingMeta(String theResourceName) {
|
||||
default Collection<String> getValidSearchParameterNamesIncludingMeta(
|
||||
String theResourceName, SearchParamLookupContextEnum theContext) {
|
||||
TreeSet<String> retval;
|
||||
ResourceSearchParams activeSearchParams = getActiveSearchParams(theResourceName);
|
||||
ResourceSearchParams activeSearchParams = getActiveSearchParams(theResourceName, theContext);
|
||||
if (activeSearchParams == null) {
|
||||
retval = new TreeSet<>();
|
||||
} else {
|
||||
|
@ -117,23 +133,25 @@ public interface ISearchParamRegistry {
|
|||
/**
|
||||
* Fetch a SearchParameter by URL
|
||||
*
|
||||
* @param theContext The context to return active search params for, or {@literal null} to return any active search params
|
||||
* @return Returns <code>null</code> if it can't be found
|
||||
*/
|
||||
@Nullable
|
||||
RuntimeSearchParam getActiveSearchParamByUrl(String theUrl);
|
||||
RuntimeSearchParam getActiveSearchParamByUrl(String theUrl, SearchParamLookupContextEnum theContext);
|
||||
|
||||
/**
|
||||
* Find a search param for a resource. First, check the resource itself, then check the top-level `Resource` resource.
|
||||
*
|
||||
* @param theResourceType the resource type.
|
||||
* @param theParamName the search parameter name.
|
||||
*
|
||||
* @param theContext The context to return active search params for, or {@literal null} to return any active search params
|
||||
* @return the {@link RuntimeSearchParam} that is found.
|
||||
*/
|
||||
default RuntimeSearchParam getRuntimeSearchParam(String theResourceType, String theParamName) {
|
||||
RuntimeSearchParam availableSearchParamDef = getActiveSearchParam(theResourceType, theParamName);
|
||||
default RuntimeSearchParam getRuntimeSearchParam(
|
||||
String theResourceType, String theParamName, SearchParamLookupContextEnum theContext) {
|
||||
RuntimeSearchParam availableSearchParamDef = getActiveSearchParam(theResourceType, theParamName, theContext);
|
||||
if (availableSearchParamDef == null) {
|
||||
availableSearchParamDef = getActiveSearchParam("Resource", theParamName);
|
||||
availableSearchParamDef = getActiveSearchParam("Resource", theParamName, theContext);
|
||||
}
|
||||
if (availableSearchParamDef == null) {
|
||||
throw new InvalidRequestException(
|
||||
|
@ -145,17 +163,54 @@ public interface ISearchParamRegistry {
|
|||
/**
|
||||
* Get all the search params for a resource. First, check the resource itself, then check the top-level `Resource` resource and combine the two.
|
||||
*
|
||||
* @param theContext The context to return active search params for, or {@literal null} to return any active search params
|
||||
* @param theResourceType the resource type.
|
||||
*
|
||||
* @return the {@link ResourceSearchParams} that has all the search params.
|
||||
*/
|
||||
default ResourceSearchParams getRuntimeSearchParams(String theResourceType) {
|
||||
default ResourceSearchParams getRuntimeSearchParams(
|
||||
String theResourceType, SearchParamLookupContextEnum theContext) {
|
||||
ResourceSearchParams availableSearchParams =
|
||||
getActiveSearchParams(theResourceType).makeCopy();
|
||||
ResourceSearchParams resourceSearchParams = getActiveSearchParams("Resource");
|
||||
getActiveSearchParams(theResourceType, theContext).makeCopy();
|
||||
ResourceSearchParams resourceSearchParams = getActiveSearchParams("Resource", theContext);
|
||||
resourceSearchParams
|
||||
.getSearchParamNames()
|
||||
.forEach(param -> availableSearchParams.addSearchParamIfAbsent(param, resourceSearchParams.get(param)));
|
||||
return availableSearchParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the context for looking up individual search parameters or lists of search parameters.
|
||||
* These can be thought of as filter criteria - Most search parameters generally apply to all
|
||||
* context, but some may be explicitly defined to only work for some.
|
||||
*
|
||||
* @since 7.6.0
|
||||
*/
|
||||
enum SearchParamLookupContextEnum {
|
||||
/**
|
||||
* Search parameter should be used when indexing a resource that is being persisted
|
||||
*/
|
||||
INDEX,
|
||||
/**
|
||||
* Search parameter should be used for searching. This includes explicit searches such as
|
||||
* standard REST FHIR searches, but also includes resolving match URLs, subscription criteria,
|
||||
* etc.
|
||||
*/
|
||||
SEARCH,
|
||||
/**
|
||||
* Search parameter should be used for sorting via the {@literal _sort} parameter.
|
||||
*/
|
||||
SORT
|
||||
}
|
||||
|
||||
static boolean isAllowedForContext(
|
||||
@Nonnull RuntimeSearchParam theSearchParam, @Nullable SearchParamLookupContextEnum theContext) {
|
||||
/*
|
||||
* I'm thinking that a future enhancement might be to allow a SearchParameter to declare that it
|
||||
* is supported for searching or for sorting or for both - But for now these are one and the same.
|
||||
*/
|
||||
if (theContext == SearchParamLookupContextEnum.SEARCH || theContext == SearchParamLookupContextEnum.SORT) {
|
||||
return theSearchParam.isEnabledForSearching();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,13 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static ca.uhn.fhir.rest.server.util.ISearchParamRegistry.isAllowedForContext;
|
||||
|
||||
public class ResourceSearchParams {
|
||||
private final String myResourceName;
|
||||
private final Map<String, RuntimeSearchParam> myMap;
|
||||
private final Map<ISearchParamRegistry.SearchParamLookupContextEnum, ResourceSearchParams> myContextToParams =
|
||||
new HashMap<>();
|
||||
|
||||
public ResourceSearchParams(String theResourceName) {
|
||||
myResourceName = theResourceName;
|
||||
|
@ -48,6 +52,32 @@ public class ResourceSearchParams {
|
|||
return myMap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a filtered view of this {@link ResourceSearchParams} instance if
|
||||
* any parameters are not valid for the given {@literal theContext}.
|
||||
*/
|
||||
public ResourceSearchParams toFilteredForContext(ISearchParamRegistry.SearchParamLookupContextEnum theContext) {
|
||||
if (theContext == null) {
|
||||
return this;
|
||||
}
|
||||
synchronized (this) {
|
||||
ResourceSearchParams retVal = myContextToParams.get(theContext);
|
||||
if (retVal == null) {
|
||||
Map<String, RuntimeSearchParam> filteredMap = new HashMap<>(myMap.size());
|
||||
for (var nextEntry : myMap.entrySet()) {
|
||||
String key = nextEntry.getKey();
|
||||
RuntimeSearchParam nextParam = nextEntry.getValue();
|
||||
if (isAllowedForContext(nextParam, theContext)) {
|
||||
filteredMap.put(key, nextParam);
|
||||
}
|
||||
}
|
||||
retVal = new ResourceSearchParams(myResourceName, filteredMap);
|
||||
myContextToParams.put(theContext, retVal);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
public static ResourceSearchParams empty(String theResourceName) {
|
||||
return new ResourceSearchParams(theResourceName, Collections.emptyMap());
|
||||
}
|
||||
|
@ -57,6 +87,7 @@ public class ResourceSearchParams {
|
|||
}
|
||||
|
||||
public void remove(String theName) {
|
||||
myContextToParams.clear();
|
||||
myMap.remove(theName);
|
||||
}
|
||||
|
||||
|
@ -69,10 +100,12 @@ public class ResourceSearchParams {
|
|||
}
|
||||
|
||||
public RuntimeSearchParam put(String theName, RuntimeSearchParam theSearchParam) {
|
||||
myContextToParams.clear();
|
||||
return myMap.put(theName, theSearchParam);
|
||||
}
|
||||
|
||||
public void addSearchParamIfAbsent(String theParamName, RuntimeSearchParam theRuntimeSearchParam) {
|
||||
myContextToParams.clear();
|
||||
myMap.putIfAbsent(theParamName, theRuntimeSearchParam);
|
||||
}
|
||||
|
||||
|
|
|
@ -519,29 +519,46 @@ public abstract class BaseStorageDao {
|
|||
return;
|
||||
}
|
||||
|
||||
ResourceSearchParams searchParams = mySearchParamRegistry.getActiveSearchParams(getResourceName());
|
||||
ResourceSearchParams searchParams = mySearchParamRegistry.getActiveSearchParams(
|
||||
getResourceName(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
Set<String> paramNames = theSource.keySet();
|
||||
for (String nextParamName : paramNames) {
|
||||
QualifierDetails qualifiedParamName = QualifierDetails.extractQualifiersFromParameterName(nextParamName);
|
||||
RuntimeSearchParam param = searchParams.get(qualifiedParamName.getParamName());
|
||||
if (param == null) {
|
||||
Collection<String> validNames =
|
||||
mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(getResourceName());
|
||||
String msg = getContext()
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
BaseStorageDao.class,
|
||||
"invalidSearchParameter",
|
||||
qualifiedParamName.getParamName(),
|
||||
getResourceName(),
|
||||
validNames);
|
||||
throw new InvalidRequestException(Msg.code(524) + msg);
|
||||
Collection<String> validNames = mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(
|
||||
getResourceName(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
RuntimeSearchParam notEnabledForSearchParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
getResourceName(), qualifiedParamName.getParamName(), null);
|
||||
if (notEnabledForSearchParam != null) {
|
||||
String msg = getContext()
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
BaseStorageDao.class,
|
||||
"invalidSearchParameterNotEnabledForSearch",
|
||||
qualifiedParamName.getParamName(),
|
||||
getResourceName(),
|
||||
validNames);
|
||||
throw new InvalidRequestException(Msg.code(2539) + msg);
|
||||
} else {
|
||||
String msg = getContext()
|
||||
.getLocalizer()
|
||||
.getMessageSanitized(
|
||||
BaseStorageDao.class,
|
||||
"invalidSearchParameter",
|
||||
qualifiedParamName.getParamName(),
|
||||
getResourceName(),
|
||||
validNames);
|
||||
throw new InvalidRequestException(Msg.code(524) + msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Should not be null since the check above would have caught it
|
||||
RuntimeSearchParam paramDef =
|
||||
mySearchParamRegistry.getActiveSearchParam(getResourceName(), qualifiedParamName.getParamName());
|
||||
RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(
|
||||
getResourceName(),
|
||||
qualifiedParamName.getParamName(),
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
for (String nextValue : theSource.get(nextParamName)) {
|
||||
QualifiedParamList qualifiedParam = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(
|
||||
|
|
|
@ -105,8 +105,10 @@ public class DaoResourceLinkResolver<T extends IResourcePersistentId> implements
|
|||
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(resourceType);
|
||||
Class<? extends IBaseResource> type = resourceDef.getImplementingClass();
|
||||
|
||||
RuntimeSearchParam searchParam =
|
||||
mySearchParamRegistry.getActiveSearchParam(theSourceResourceName, thePathAndRef.getSearchParamName());
|
||||
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(
|
||||
theSourceResourceName,
|
||||
thePathAndRef.getSearchParamName(),
|
||||
ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
T persistentId = null;
|
||||
if (theTransactionDetails != null) {
|
||||
|
|
|
@ -74,7 +74,7 @@ public class SearchParameterDaoValidator {
|
|||
for (IPrimitiveType<?> nextBaseType : searchParameter.getBase()) {
|
||||
String nextBase = nextBaseType.getValueAsString();
|
||||
RuntimeSearchParam existingSearchParam =
|
||||
mySearchParamRegistry.getActiveSearchParam(nextBase, searchParameter.getCode());
|
||||
mySearchParamRegistry.getActiveSearchParam(nextBase, searchParameter.getCode(), null);
|
||||
if (existingSearchParam != null) {
|
||||
boolean isBuiltIn = existingSearchParam.getId() == null;
|
||||
isBuiltIn |= existingSearchParam.getUri().startsWith("http://hl7.org/fhir/SearchParameter/");
|
||||
|
@ -221,7 +221,7 @@ public class SearchParameterDaoValidator {
|
|||
.filter(SearchParameter.SearchParameterComponentComponent::hasDefinition)
|
||||
.map(SearchParameter.SearchParameterComponentComponent::getDefinition)
|
||||
.filter(Objects::nonNull)
|
||||
.map(mySearchParamRegistry::getActiveSearchParamByUrl)
|
||||
.map((String url) -> mySearchParamRegistry.getActiveSearchParamByUrl(url, null))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(theRuntimeSp -> validateComponentSpTypeAgainstWhiteList(
|
||||
theRuntimeSp, getAllowedSearchParameterTypes(theSearchParameter)));
|
||||
|
|
|
@ -130,7 +130,8 @@ public class DaoRegistryGraphQLStorageServices implements IGraphQLStorageService
|
|||
RuntimeResourceDefinition typeDef = fhirContext.getResourceDefinition(theType);
|
||||
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
ResourceSearchParams searchParams = mySearchParamRegistry.getRuntimeSearchParams(typeDef.getName());
|
||||
ResourceSearchParams searchParams = mySearchParamRegistry.getRuntimeSearchParams(
|
||||
typeDef.getName(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
|
||||
|
||||
for (Argument nextArgument : resourceSearchParam) {
|
||||
|
||||
|
|
Loading…
Reference in New Issue