Compare commits

...

3 Commits

Author SHA1 Message Date
Martha Mitran 2f5ca902df
Merge 5afe7223bb into 96e1c2a5db 2024-11-07 11:04:18 -05:00
James Agnew 96e1c2a5db
Add extension for disabling search params (#6107)
* Combo permutations

* Work on combo

* Add tests

* Add changelog

* Spotless

* Test fix

* Drop label

* Add tests

* Spotles

* Work on disable code

* Cleanup

* CLeanup

* Cleanup

* Add changelog

* Test cleanup

* Review comments

* Spotless

* Compile fix

* Version bump

* Test fix

* Test fixes
2024-11-07 09:11:19 -05:00
Martha 5afe7223bb Add failing test. 2024-10-18 15:00:41 -07:00
151 changed files with 1229 additions and 417 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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;

View File

@ -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
*/

View File

@ -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}

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-bom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>HAPI FHIR BOM</name>
@ -12,7 +12,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -0,0 +1,7 @@
---
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. See
[Introducing Search Parameters on Existing Data](https://smilecdr.com/docs/fhir_standard/fhir_search_custom_search_parameters.html) for more information."

View File

@ -238,3 +238,7 @@ In order to improve sorting performance when chained sorts are needed, an [Uplif
# _include and _revinclude order
By default, all _revincludes will be performed first and then all _includes are performed afterwards. However, if any _revinclude parameters are modified with :iterate (or :recurse for earlier versions of FHIR) then all _include parameters will be evaluated first.
# Custom Search Parameters
HAPI FHIR has the ability to index and use custom search parameters, including parameters which enforce uniqueness, parametrs which index combinations of parameters, and parameters which are indexed but not used for searches until they are ready. See [Custom Search Parameters](https://smilecdr.com/docs/fhir_standard/fhir_search_custom_search_parameters.html) for more information.

View File

@ -11,7 +11,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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);
}
/**

View File

@ -1,3 +1,22 @@
/*-
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.jpa.dao.data.ITagDefinitionDao;

View File

@ -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);

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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))

View File

@ -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()

View File

@ -318,7 +318,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) {
@ -334,17 +335,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(
@ -1007,10 +1011,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(
@ -1168,13 +1173,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);
@ -1364,7 +1370,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
@ -1372,8 +1378,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()) {
@ -2494,7 +2500,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()) {
@ -2701,15 +2708,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, ISearchParamRegistry.SearchParamLookupContextEnum.ALL);
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);
}
}
}
}
@ -2740,8 +2765,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)))
@ -2808,8 +2833,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);
});
@ -3049,7 +3076,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;

View File

@ -655,8 +655,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);
}
@ -928,8 +928,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
@ -953,8 +953,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)) {
@ -962,8 +962,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;
@ -997,7 +999,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) {
@ -1076,8 +1079,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(
@ -1540,7 +1543,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;
}
@ -1879,7 +1883,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())) {
@ -1962,16 +1969,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()
@ -2040,8 +2047,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);
@ -2156,7 +2163,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())) {

View File

@ -20,6 +20,7 @@
package ca.uhn.fhir.jpa.search.builder.predicate;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
import ca.uhn.fhir.jpa.util.QueryParameterUtils;
import com.healthmarketscience.sqlbuilder.Condition;
@ -35,7 +36,9 @@ public class ComboUniqueSearchParameterPredicateBuilder extends BaseSearchParamP
* Constructor
*/
public ComboUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_IDX_CMP_STRING_UNIQ"));
super(
theSearchSqlBuilder,
theSearchSqlBuilder.addTable(ResourceIndexedComboStringUnique.HFJ_IDX_CMP_STRING_UNIQ));
myColumnString = getTable().addColumn("IDX_STRING");
}

View File

@ -497,7 +497,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;
@ -586,8 +587,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);
}
@ -659,7 +660,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();
@ -675,7 +677,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());
@ -687,7 +690,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();
@ -718,7 +722,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))
@ -832,8 +837,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im
subquery.addFromTable(getTable());
String resourceType = theParams.getResourceTablePredicateBuilder().getResourceType();
RuntimeSearchParam paramDefinition =
mySearchParamRegistry.getRuntimeSearchParam(resourceType, theParams.getParamName());
RuntimeSearchParam paramDefinition = mySearchParamRegistry.getRuntimeSearchParam(
resourceType, theParams.getParamName(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
List<String> pathList = paramDefinition.getPathsSplitForResourceType(resourceType);
Condition subQueryCondition = ComboCondition.and(

View File

@ -158,7 +158,7 @@ public class InstanceReindexServiceImpl implements IInstanceReindexService {
return myVersionCanonicalizer.parametersFromCanonical(retValCanonical);
}
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"rawtypes"})
@Nonnull
private Parameters reindexInTransaction(RequestDetails theRequestDetails, IIdType theResourceId) {
StopWatch sw = new StopWatch();
@ -441,7 +441,8 @@ 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, ISearchParamRegistry.SearchParamLookupContextEnum.ALL);
for (RuntimeSearchParam next : searchParams.values()) {
hashes.put(
SearchParamPresentEntity.calculateHashPresence(

View File

@ -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);

View File

@ -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());
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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);
}

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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";
@GenericGenerator(
name = "SEQ_IDXCMPSTRUNIQ_ID",

View File

@ -41,7 +41,7 @@ import org.hibernate.annotations.GenericGenerator;
@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.hibernate.annotations.GenericGenerator;
public class ResourceIndexedComboTokenNonUnique extends BaseResourceIndexedCombo
implements Comparable<ResourceIndexedComboTokenNonUnique>, IResourceIndexComboSearchParameter {
public static final String HFJ_IDX_CMB_TOK_NU = "HFJ_IDX_CMB_TOK_NU";
@GenericGenerator(
name = "SEQ_IDXCMBTOKNU_ID",
type = ca.uhn.fhir.jpa.model.dialect.HapiSequenceStyleGenerator.class)

View File

@ -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
@GenericGenerator(name = "SEQ_SPIDX_STRING", type = ca.uhn.fhir.jpa.model.dialect.HapiSequenceStyleGenerator.class)

View File

@ -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)

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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);
}

View File

@ -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 =
@ -576,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) {
@ -990,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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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,62 @@ public class SearchParamRegistryImpl
}
@Override
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
public RuntimeSearchParam getActiveSearchParam(
@Nonnull String theResourceName,
@Nonnull String theParamName,
@Nonnull 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(
@Nonnull String theResourceName, @Nonnull 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(
@Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) {
return filteredForContext(myJpaSearchParamCache.getActiveComboSearchParams(theResourceName), theContext);
}
@Override
public List<RuntimeSearchParam> getActiveComboSearchParams(
String theResourceName, ComboSearchParamType theParamType) {
return myJpaSearchParamCache.getActiveComboSearchParams(theResourceName, theParamType);
@Nonnull String theResourceName,
@Nonnull ComboSearchParamType theParamType,
@Nonnull 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(
@Nonnull String theResourceName,
@Nonnull Set<String> theParamNames,
@Nonnull SearchParamLookupContextEnum theContext) {
return filteredForContext(
myJpaSearchParamCache.getActiveComboSearchParams(theResourceName, theParamNames), theContext);
}
@Override
@ -160,16 +180,20 @@ public class SearchParamRegistryImpl
@Nullable
@Override
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
public RuntimeSearchParam getActiveSearchParamByUrl(
@Nonnull String theUrl, @Nonnull 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
public Optional<RuntimeSearchParam> getActiveComboSearchParamById(String theResourceName, IIdType theId) {
public Optional<RuntimeSearchParam> getActiveComboSearchParamById(
@Nonnull String theResourceName, @Nonnull IIdType theId) {
return myJpaSearchParamCache.getActiveComboSearchParamById(theResourceName, theId);
}
@ -307,7 +331,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 +389,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 +480,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());
}
}

View File

@ -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) {

View File

@ -162,7 +162,8 @@ 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, ISearchParamRegistry.SearchParamLookupContextEnum.ALL);
if (componentParam == null) {
throw new InternalErrorException(Msg.code(499) + "Can not find SearchParameter: " + url);
}

View File

@ -27,6 +27,7 @@ import ca.uhn.fhir.util.StringUtil;
import ca.uhn.fhir.util.TestUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import org.hl7.fhir.dstu3.model.Duration;
import org.hl7.fhir.dstu3.model.Encounter;
@ -263,7 +264,7 @@ public class SearchParamExtractorDstu3Test {
}
@Override
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
public RuntimeSearchParam getActiveSearchParam(@Nonnull String theResourceName, @Nonnull String theParamName, @Nonnull SearchParamLookupContextEnum theContext) {
throw new UnsupportedOperationException();
}
@ -278,7 +279,7 @@ public class SearchParamExtractorDstu3Test {
}
@Override
public ResourceSearchParams getActiveSearchParams(String theResourceName) {
public ResourceSearchParams getActiveSearchParams(@Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) {
RuntimeResourceDefinition nextResDef = ourCtx.getResourceDefinition(theResourceName);
ResourceSearchParams retval = new ResourceSearchParams(theResourceName);
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
@ -291,28 +292,28 @@ public class SearchParamExtractorDstu3Test {
}
@Override
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
public List<RuntimeSearchParam> getActiveComboSearchParams(@Nonnull String theResourceName, @Nonnull Set<String> theParamNames, @Nonnull SearchParamLookupContextEnum theContext) {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
public RuntimeSearchParam getActiveSearchParamByUrl(@Nonnull String theUrl, @Nonnull SearchParamLookupContextEnum theContext) {
throw new UnsupportedOperationException();
}
@Override
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
public List<RuntimeSearchParam> getActiveComboSearchParams(@Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) {
throw new UnsupportedOperationException();
}
@Override
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, ComboSearchParamType theParamType) {
public List<RuntimeSearchParam> getActiveComboSearchParams(@Nonnull String theResourceName, @Nonnull ComboSearchParamType theParamType, @Nonnull SearchParamLookupContextEnum theContext) {
throw new UnsupportedOperationException(Msg.code(2210));
}
@Override
public Optional<RuntimeSearchParam> getActiveComboSearchParamById(String theResourceName, IIdType theId) {
public Optional<RuntimeSearchParam> getActiveComboSearchParamById(@Nonnull String theResourceName, @Nonnull IIdType theId) {
throw new UnsupportedOperationException(Msg.code(2212));
}

View File

@ -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();

View File

@ -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);

View File

@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.searchparam.registry;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.rest.server.util.FhirContextSearchParamRegistry;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
@ -28,7 +29,7 @@ class FhirContextSearchParamRegistryTest {
SP_RES_SECURITY + ", Resource.meta.security"
})
void testResourceLevelSearchParamsAreRegistered(String theSearchParamName, String theSearchParamPath) {
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Patient", theSearchParamName);
RuntimeSearchParam sp = mySearchParamRegistry.getActiveSearchParam("Patient", theSearchParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH);
assertThat(sp)
.as("path is null for search parameter: '%s'", theSearchParamName)

View File

@ -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"));

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -71,7 +71,9 @@ public class SubscriptionLoader extends BaseResourceCacheSynchronizer {
protected SearchParameterMap getSearchParameterMap() {
SearchParameterMap map = new SearchParameterMap();
if (mySearchParamRegistry.getActiveSearchParam("Subscription", "status") != null) {
if (mySearchParamRegistry.getActiveSearchParam(
"Subscription", "status", ISearchParamRegistry.SearchParamLookupContextEnum.ALL)
!= null) {
map.add(
Subscription.SP_STATUS,
new TokenOrListParam()

View File

@ -71,7 +71,9 @@ public class SubscriptionTopicLoader extends BaseResourceCacheSynchronizer {
protected SearchParameterMap getSearchParameterMap() {
SearchParameterMap map = new SearchParameterMap();
if (mySearchParamRegistry.getActiveSearchParam("SubscriptionTopic", "status") != null) {
if (mySearchParamRegistry.getActiveSearchParam(
"SubscriptionTopic", "status", ISearchParamRegistry.SearchParamLookupContextEnum.ALL)
!= null) {
map.add(SubscriptionTopic.SP_STATUS, new TokenParam(null, Enumerations.PublicationStatus.ACTIVE.toCode()));
}
map.setLoadSynchronousUpTo(SubscriptionConstants.MAX_SUBSCRIPTION_RESULTS);

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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());

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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());

View File

@ -12,6 +12,7 @@ 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.DateParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
@ -43,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;
@ -71,6 +73,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() {
@ -78,42 +86,7 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
}
private void createUniqueBirthdateAndGenderSps() {
SearchParameter sp = new SearchParameter();
sp.setId("SearchParameter/patient-gender");
sp.setType(Enumerations.SearchParamType.TOKEN);
sp.setCode("gender");
sp.setExpression("Patient.gender");
sp.setStatus(PublicationStatus.ACTIVE);
sp.addBase("Patient");
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.addBase("Patient");
mySearchParameterDao.update(sp, mySrd);
sp = new SearchParameter();
sp.setId("SearchParameter/patient-gender-birthdate");
sp.setType(Enumerations.SearchParamType.COMPOSITE);
sp.setStatus(PublicationStatus.ACTIVE);
sp.addBase("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));
mySearchParameterDao.update(sp, mySrd);
mySearchParamRegistry.forceRefresh();
myComboSearchParameterTestHelper.createBirthdateAndGenderSps(true);
myMessages.clear();
}
@ -860,7 +833,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();
@ -889,7 +862,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);
@ -906,7 +879,7 @@ public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test
myResourceIndexedComboStringUniqueDao.deleteAll();
});
assertThat(mySearchParamRegistry.getActiveComboSearchParams("Observation")).hasSize(1);
assertThat(mySearchParamRegistry.getActiveComboSearchParams("Observation", null)).hasSize(1);
executeReindex();
@ -1747,7 +1720,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());

View File

@ -253,9 +253,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);
@ -593,7 +593,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());
}

View File

@ -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"));

View File

@ -23,6 +23,7 @@ import org.hl7.fhir.r4.model.Parameters;
import org.hl7.fhir.r4.model.StringType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -121,6 +122,35 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv
}
@Test
public void testExpungeOperation() {
// Create patients
createPatient(withTenant(TENANT_A));
createPatient(withTenant(TENANT_B));
createPatient(withTenant(DEFAULT_PARTITION_NAME));
// validate setup
assertEquals(1, getAllPatientsInTenant(TENANT_A).getTotal());
assertEquals(1, getAllPatientsInTenant(TENANT_B).getTotal());
assertEquals(1, getAllPatientsInTenant(DEFAULT_PARTITION_NAME).getTotal());
Parameters input = new Parameters();
input.addParameter(ProviderConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_EVERYTHING, true);
myTenantClientInterceptor.setTenantId(TENANT_B);
// execute
myClient.operation()
.onServer()
.named(ProviderConstants.OPERATION_EXPUNGE)
.withParameters(input)
.execute();
// validate only the patients in TENANT_B are removed
assertEquals(1, getAllPatientsInTenant(TENANT_A).getTotal());
assertEquals(0, getAllPatientsInTenant(TENANT_B).getTotal());
assertEquals(1, getAllPatientsInTenant(DEFAULT_PARTITION_NAME).getTotal());
}
@Test
public void testReindexEverything() {
ReindexTestHelper reindexTestHelper = new ReindexTestHelper(myFhirContext, myDaoRegistry, mySearchParamRegistry);
@ -159,7 +189,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 +226,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 +254,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);

View File

@ -402,7 +402,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);

View File

@ -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);

View File

@ -117,7 +117,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());
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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"));

View File

@ -0,0 +1,259 @@
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.jobs.reindex.ReindexUtils;
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.StringParam;
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, _profile, _security, _tag, _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.createFamilyAndGenderSps(theUnique, t -> {
if (theEnabledForSearching != null) {
t.addExtension(EXT_SEARCHPARAM_ENABLED_FOR_SEARCHING, new BooleanType(theEnabledForSearching));
}
});
createPatient(withId("A"), withFamily("simpson"), withGender("male"));
logAllDateIndexes();
logAllTokenIndexes();
logAllUniqueIndexes();
// Test
SearchParameterMap map = SearchParameterMap
.newSynchronous()
.add(Patient.SP_FAMILY, new StringParam("simpson"))
.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(ReindexUtils.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;
}
}
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -0,0 +1,150 @@
/*-
* #%L
* HAPI FHIR JPA Server Test Utilities
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
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(theUnique));
for (var next : theSearchParamCustomizer) {
next.accept(sp);
}
mySearchParameterDao.update(fromCanonoical(sp), new SystemRequestDetails());
mySearchParamRegistry.forceRefresh();
}
public void createFamilyAndGenderSps(boolean theUnique, ISearchParamCustomizer... theSearchParamCustomizer) {
SearchParameter sp = new SearchParameter();
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(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
mySearchParameterDao.update(fromCanonoical(sp), new SystemRequestDetails());
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-family-gender");
sp.setType(Enumerations.SearchParamType.COMPOSITE);
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
sp.addBase(Enumerations.VersionIndependentResourceTypesAll.PATIENT);
sp.addComponent()
.setExpression("Patient")
.setDefinition("SearchParameter/patient-family");
sp.addComponent()
.setExpression("Patient")
.setDefinition("SearchParameter/patient-gender");
sp.addExtension()
.setUrl(HapiExtensions.EXT_SP_UNIQUE)
.setValue(new BooleanType(theUnique));
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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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();
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -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 + "'");
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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());

View File

@ -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());

View File

@ -25,6 +25,8 @@ import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
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;
@ -47,11 +49,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();

View File

@ -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)) {

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.7.0-SNAPSHOT</version>
<version>7.7.1-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -420,12 +420,16 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
}
@Override
public RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) {
return getActiveSearchParams(theResourceName).get(theParamName);
public RuntimeSearchParam getActiveSearchParam(
@Nonnull String theResourceName,
@Nonnull String theParamName,
@Nonnull SearchParamLookupContextEnum theContext) {
return getActiveSearchParams(theResourceName, theContext).get(theParamName);
}
@Override
public ResourceSearchParams getActiveSearchParams(@Nonnull String theResourceName) {
public ResourceSearchParams getActiveSearchParams(
@Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) {
Validate.notBlank(theResourceName, "theResourceName must not be null or blank");
ResourceSearchParams retval = new ResourceSearchParams(theResourceName);
@ -442,7 +446,8 @@ public class RestfulServerConfiguration implements ISearchParamRegistry {
@Nullable
@Override
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
public RuntimeSearchParam getActiveSearchParamByUrl(
@Nonnull String theUrl, @Nonnull SearchParamLookupContextEnum theContext) {
throw new UnsupportedOperationException(Msg.code(286));
}

Some files were not shown because too many files have changed in this diff Show More