diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index adc4307d0b8..8a7ab69ef74 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index 32a04f879bc..e3e75528d96 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index 08bfd91e17e..fb2a1d3c197 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeSearchParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeSearchParam.java index 38afad702c0..51b28adb95d 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeSearchParam.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeSearchParam.java @@ -60,6 +60,7 @@ public class RuntimeSearchParam { private final List 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 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 could * 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; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/HapiExtensions.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/HapiExtensions.java index 4ad9769b85c..93e5086cd95 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/HapiExtensions.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/HapiExtensions.java @@ -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 */ diff --git a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties index 662ce8daf21..f338fc8fa1c 100644 --- a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties +++ b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties @@ -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} diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml index 5b0c4f74da7..f84468e2165 100644 --- a/hapi-fhir-bom/pom.xml +++ b/hapi-fhir-bom/pom.xml @@ -4,7 +4,7 @@ 4.0.0 ca.uhn.hapi.fhir hapi-fhir-bom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT pom HAPI FHIR BOM @@ -12,7 +12,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml index 292a0af82c2..353b114f18e 100644 --- a/hapi-fhir-checkstyle/pom.xml +++ b/hapi-fhir-checkstyle/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml index 4b6cca470e4..589897efb9f 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml index 3f69ebc987c..a9dbf70d316 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-fhir-cli - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml index 9c312e2d959..3287f127671 100644 --- a/hapi-fhir-cli/pom.xml +++ b/hapi-fhir-cli/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml index f4559fc07b9..c6506eef5dc 100644 --- a/hapi-fhir-client-okhttp/pom.xml +++ b/hapi-fhir-client-okhttp/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml index 62a1b45daa0..c57a637e0b8 100644 --- a/hapi-fhir-client/pom.xml +++ b/hapi-fhir-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml index db6a70c7c4c..687eb136551 100644 --- a/hapi-fhir-converter/pom.xml +++ b/hapi-fhir-converter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml index edefba3826d..1792251512d 100644 --- a/hapi-fhir-dist/pom.xml +++ b/hapi-fhir-dist/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml index cb525bd5e8a..c6c4888fa1f 100644 --- a/hapi-fhir-docs/pom.xml +++ b/hapi-fhir-docs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_8_0/6107-allow-sp-disabling.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_8_0/6107-allow-sp-disabling.yaml new file mode 100644 index 00000000000..b8f603a05e4 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_8_0/6107-allow-sp-disabling.yaml @@ -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." diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/search.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/search.md index e760b4a3dab..ecafafea17b 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/search.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/search.md @@ -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. diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml index 6784d443f29..dd6295cfefb 100644 --- a/hapi-fhir-jacoco/pom.xml +++ b/hapi-fhir-jacoco/pom.xml @@ -11,7 +11,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml index ee6ce35e23f..f3c636e9344 100644 --- a/hapi-fhir-jaxrsserver-base/pom.xml +++ b/hapi-fhir-jaxrsserver-base/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml index 6d805b31a8b..5863d68f932 100644 --- a/hapi-fhir-jpa/pom.xml +++ b/hapi-fhir-jpa/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index 2365d4d326f..4bb53595eef 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java index 440ed7c27af..fca9611aed2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java @@ -625,7 +625,8 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor { resourceToCheck = "Patient"; activeSearchParamName = "organization"; } - return mySearchParamRegistry.getActiveSearchParam(resourceToCheck, activeSearchParamName); + return mySearchParamRegistry.getActiveSearchParam( + resourceToCheck, activeSearchParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); } /** diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/CacheTagDefinitionDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/CacheTagDefinitionDao.java index 5f7d7d4b435..342a1e3402b 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/CacheTagDefinitionDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/CacheTagDefinitionDao.java @@ -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; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FulltextSearchSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FulltextSearchSvcImpl.java index 5c45b2ca875..0bccd1b6c67 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FulltextSearchSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FulltextSearchSvcImpl.java @@ -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); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/search/ExtendedHSearchSearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/search/ExtendedHSearchSearchBuilder.java index dc5cc4d70b2..79029f95585 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/search/ExtendedHSearchSearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/search/ExtendedHSearchSearchBuilder.java @@ -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 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 diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/search/HSearchSortHelperImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/search/HSearchSortHelperImpl.java index e3ba26a504b..cf00f237321 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/search/HSearchSortHelperImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/search/HSearchSortHelperImpl.java @@ -151,7 +151,8 @@ public class HSearchSortHelperImpl implements IHSearchSortHelper { */ @VisibleForTesting Optional 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(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/graphql/GraphQLProviderWithIntrospection.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/graphql/GraphQLProviderWithIntrospection.java index 965914cf85a..1d08ddbc41d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/graphql/GraphQLProviderWithIntrospection.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/graphql/GraphQLProviderWithIntrospection.java @@ -181,7 +181,8 @@ public class GraphQLProviderWithIntrospection extends GraphQLProvider { for (String nextResourceType : theResourceTypes) { StructureDefinition sd = fetchStructureDefinition(nextResourceType); List 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 parameters = toR5SearchParams(mySearchParamRegistry - .getActiveSearchParams(nextResourceType) + .getActiveSearchParams( + nextResourceType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH) .values()); myGenerator.generateListAccessQuery(writer, parameters, nextResourceType); myGenerator.generateConnectionAccessQuery(writer, parameters, nextResourceType); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaConformanceProviderDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaConformanceProviderDstu3.java index 0ab99892e74..ff94791e033 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaConformanceProviderDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/JpaConformanceProviderDstu3.java @@ -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)) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java index f73b69a3c2d..477999b3d3e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java @@ -489,8 +489,13 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { } if (!Constants.INCLUDE_STAR.equals(paramName) - && mySearchParamRegistry.getActiveSearchParam(paramType, paramName) == null) { - List validNames = mySearchParamRegistry.getActiveSearchParams(paramType).values().stream() + && mySearchParamRegistry.getActiveSearchParam( + paramType, paramName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH) + == null) { + List validNames = mySearchParamRegistry + .getActiveSearchParams(paramType, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH) + .values() + .stream() .filter(t -> t.getParamType() == RestSearchParameterTypeEnum.REFERENCE) .map(t -> UrlUtil.sanitizeUrlPart(t.getName())) .sorted() diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/QueryStack.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/QueryStack.java index 948b96c5de6..5eadee42cb1 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/QueryStack.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/QueryStack.java @@ -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 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 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 validNames = - mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName); + Collection 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 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 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 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 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; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java index 9a28921f1ae..a7e9ebc32f9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/SearchBuilder.java @@ -655,8 +655,8 @@ public class SearchBuilder implements ISearchBuilder { || theParams.getSort() != null || theParams.keySet().contains(Constants.PARAM_HAS) || isPotentiallyContainedReferenceParameterExistsAtRoot(theParams)) { - List activeComboParams = - mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet()); + List activeComboParams = mySearchParamRegistry.getActiveComboSearchParams( + myResourceName, theParams.keySet(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); if (activeComboParams.isEmpty()) { sqlBuilder.setNeedResourceTableRoot(true); } @@ -928,8 +928,8 @@ public class SearchBuilder implements ISearchBuilder { 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 { 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 { 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 { } 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 { } private void throwInvalidRequestExceptionForUnknownSortParameter(String theResourceName, String theParamName) { - Collection validSearchParameterNames = - mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName); + Collection validSearchParameterNames = mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta( + theResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SORT); String msg = myContext .getLocalizer() .getMessageSanitized( @@ -1540,7 +1543,8 @@ public class SearchBuilder implements ISearchBuilder { 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 { // 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 { QueryStack theQueryStack, @Nonnull SearchParameterMap theParams, RequestDetails theRequest) { RuntimeSearchParam comboParam = null; List comboParamNames = null; - List exactMatchParams = - mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet()); + List 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 candidateComboParams = - mySearchParamRegistry.getActiveComboSearchParams(myResourceName); + List candidateComboParams = mySearchParamRegistry.getActiveComboSearchParams( + myResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); for (RuntimeSearchParam nextCandidate : candidateComboParams) { List nextCandidateParamNames = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, nextCandidate).stream() @@ -2040,8 +2047,8 @@ public class SearchBuilder implements ISearchBuilder { 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 { // 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())) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ComboUniqueSearchParameterPredicateBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ComboUniqueSearchParameterPredicateBuilder.java index cd3ccf6104f..09ae5ad82b3 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ComboUniqueSearchParameterPredicateBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ComboUniqueSearchParameterPredicateBuilder.java @@ -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"); } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilder.java index 9d45df2f662..5196028423d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilder.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilder.java @@ -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> 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 targetTypes = param.getTargets(); @@ -675,7 +677,8 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder im String paramNameTail = theParamNameChain.substring(linkIndex + 1); Set 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 createResourceLinkPaths( String theResourceName, String theParamName, List theParamQualifiers) { - RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName); + RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam( + theResourceName, theParamName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); if (param != null) { List 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 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 pathList = paramDefinition.getPathsSplitForResourceType(resourceType); Condition subQueryCondition = ComboCondition.and( diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/InstanceReindexServiceImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/InstanceReindexServiceImpl.java index aeb8b9e31cd..5061b260fa4 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/InstanceReindexServiceImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/InstanceReindexServiceImpl.java @@ -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 theTarget, String theResourceName) { Map 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( diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessorTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessorTest.java index fdf3f3d6743..d5900c83e02 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessorTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessorTest.java @@ -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); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/search/HSearchSortHelperImplTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/search/HSearchSortHelperImplTest.java index caf4a912907..313381c6be5 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/search/HSearchSortHelperImplTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/search/HSearchSortHelperImplTest.java @@ -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 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()); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/util/QueryParameterUtilsTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/util/QueryParameterUtilsTest.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml index 3dc183581d8..e3d755adf00 100644 --- a/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-elastic-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-hfql/pom.xml b/hapi-fhir-jpaserver-hfql/pom.xml index f05a97423e0..77d09613e90 100644 --- a/hapi-fhir-jpaserver-hfql/pom.xml +++ b/hapi-fhir-jpaserver-hfql/pom.xml @@ -3,7 +3,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-hfql/src/main/java/ca/uhn/fhir/jpa/fql/executor/HfqlExecutor.java b/hapi-fhir-jpaserver-hfql/src/main/java/ca/uhn/fhir/jpa/fql/executor/HfqlExecutor.java index c85581c3115..2063b3f9108 100644 --- a/hapi-fhir-jpaserver-hfql/src/main/java/ca/uhn/fhir/jpa/fql/executor/HfqlExecutor.java +++ b/hapi-fhir-jpaserver-hfql/src/main/java/ca/uhn/fhir/jpa/fql/executor/HfqlExecutor.java @@ -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); } diff --git a/hapi-fhir-jpaserver-ips/pom.xml b/hapi-fhir-jpaserver-ips/pom.xml index 6fc20716e2d..0582c13b819 100644 --- a/hapi-fhir-jpaserver-ips/pom.xml +++ b/hapi-fhir-jpaserver-ips/pom.xml @@ -3,7 +3,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-mdm/pom.xml b/hapi-fhir-jpaserver-mdm/pom.xml index e1af147e86e..a5b249461e3 100644 --- a/hapi-fhir-jpaserver-mdm/pom.xml +++ b/hapi-fhir-jpaserver-mdm/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/pom.xml b/hapi-fhir-jpaserver-model/pom.xml index 70bb7d54543..a0e13b95c67 100644 --- a/hapi-fhir-jpaserver-model/pom.xml +++ b/hapi-fhir-jpaserver-model/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboStringUnique.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboStringUnique.java index 8e980d69391..97d9d79419d 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboStringUnique.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboStringUnique.java @@ -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", diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboTokenNonUnique.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboTokenNonUnique.java index 07026856503..876ecdb7f5d 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboTokenNonUnique.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedComboTokenNonUnique.java @@ -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, 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) diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamString.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamString.java index ba3312bb801..5d5466291c6 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamString.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamString.java @@ -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) diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamToken.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamToken.java index e492efc9436..50cd671dcb4 100644 --- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamToken.java +++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ResourceIndexedSearchParamToken.java @@ -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) diff --git a/hapi-fhir-jpaserver-searchparam/pom.xml b/hapi-fhir-jpaserver-searchparam/pom.xml index 8ebac3ffed2..ac264c6bf99 100755 --- a/hapi-fhir-jpaserver-searchparam/pom.xml +++ b/hapi-fhir-jpaserver-searchparam/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java index 3b0676acf68..15c136c5420 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java @@ -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); } diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java index 290c166a38c..810286c2842 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/BaseSearchParamExtractor.java @@ -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 extractSearchParamComboUnique( String theResourceType, ResourceIndexedSearchParams theParams) { SearchParamSet retVal = new SearchParamSet<>(); - List runtimeComboUniqueParams = - mySearchParamRegistry.getActiveComboSearchParams(theResourceType, ComboSearchParamType.UNIQUE); + List runtimeComboUniqueParams = mySearchParamRegistry.getActiveComboSearchParams( + theResourceType, ComboSearchParamType.UNIQUE, ISearchParamRegistry.SearchParamLookupContextEnum.INDEX); for (RuntimeSearchParam runtimeParam : runtimeComboUniqueParams) { Set comboUniqueParams = @@ -485,8 +487,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor public SearchParamSet extractSearchParamComboNonUnique( String theResourceType, ResourceIndexedSearchParams theParams) { SearchParamSet retVal = new SearchParamSet<>(); - List runtimeComboNonUniqueParams = - mySearchParamRegistry.getActiveComboSearchParams(theResourceType, ComboSearchParamType.NON_UNIQUE); + List runtimeComboNonUniqueParams = mySearchParamRegistry.getActiveComboSearchParams( + theResourceType, + ComboSearchParamType.NON_UNIQUE, + ISearchParamRegistry.SearchParamLookupContextEnum.INDEX); for (RuntimeSearchParam runtimeParam : runtimeComboNonUniqueParams) { Set 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 getSearchParams(IBaseResource theResource) { RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource); - Collection retVal = - mySearchParamRegistry.getActiveSearchParams(def.getName()).values(); + Collection retVal = mySearchParamRegistry + .getActiveSearchParams(def.getName(), ISearchParamRegistry.SearchParamLookupContextEnum.INDEX) + .values(); List defaultList = Collections.emptyList(); retVal = ObjectUtils.defaultIfNull(retVal, defaultList); return retVal; diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java index 354996c66f1..a7903eaf03a 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java @@ -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 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, diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcher.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcher.java index 78fc2cae5ef..b481666b259 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcher.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcher.java @@ -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; } diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParamRegistryImpl.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParamRegistryImpl.java index 9670b18f175..95c6dd9a44d 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParamRegistryImpl.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParamRegistryImpl.java @@ -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 getActiveComboSearchParams(String theResourceName) { - return myJpaSearchParamCache.getActiveComboSearchParams(theResourceName); + public List getActiveComboSearchParams( + @Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) { + return filteredForContext(myJpaSearchParamCache.getActiveComboSearchParams(theResourceName), theContext); } @Override public List 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 getActiveComboSearchParams(String theResourceName, Set theParamNames) { - return myJpaSearchParamCache.getActiveComboSearchParams(theResourceName, theParamNames); + public List getActiveComboSearchParams( + @Nonnull String theResourceName, + @Nonnull Set 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 getActiveComboSearchParamById(String theResourceName, IIdType theId) { + public Optional 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 filteredForContext( + List theActiveComboSearchParams, SearchParamLookupContextEnum theContext) { + return theActiveComboSearchParams.stream() + .filter(t -> isAllowedForContext(t, theContext)) + .collect(Collectors.toList()); } } diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParameterCanonicalizer.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParameterCanonicalizer.java index 3ca4306d204..799b9a0691b 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParameterCanonicalizer.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParameterCanonicalizer.java @@ -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 theExtension) { diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/util/JpaParamUtil.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/util/JpaParamUtil.java index 35195681527..c3adf585eae 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/util/JpaParamUtil.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/util/JpaParamUtil.java @@ -162,7 +162,8 @@ public enum JpaParamUtil { List 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); } diff --git a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorDstu3Test.java b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorDstu3Test.java index a02afa00d62..9090f2c13b3 100644 --- a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorDstu3Test.java +++ b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorDstu3Test.java @@ -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 getActiveComboSearchParams(String theResourceName, Set theParamNames) { + public List getActiveComboSearchParams(@Nonnull String theResourceName, @Nonnull Set 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 getActiveComboSearchParams(String theResourceName) { + public List getActiveComboSearchParams(@Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) { throw new UnsupportedOperationException(); } @Override - public List getActiveComboSearchParams(String theResourceName, ComboSearchParamType theParamType) { + public List getActiveComboSearchParams(@Nonnull String theResourceName, @Nonnull ComboSearchParamType theParamType, @Nonnull SearchParamLookupContextEnum theContext) { throw new UnsupportedOperationException(Msg.code(2210)); } @Override - public Optional getActiveComboSearchParamById(String theResourceName, IIdType theId) { + public Optional getActiveComboSearchParamById(@Nonnull String theResourceName, @Nonnull IIdType theId) { throw new UnsupportedOperationException(Msg.code(2212)); } diff --git a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcherConfigurationR5Test.java b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcherConfigurationR5Test.java index aeca7648c6f..012110ea217 100644 --- a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcherConfigurationR5Test.java +++ b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcherConfigurationR5Test.java @@ -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(); diff --git a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcherR5Test.java b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcherR5Test.java index ccee696f68f..164ef8bd2c7 100644 --- a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcherR5Test.java +++ b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcherR5Test.java @@ -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); diff --git a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/registry/FhirContextSearchParamRegistryTest.java b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/registry/FhirContextSearchParamRegistryTest.java index d51b344ccd0..ca87895c9dc 100644 --- a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/registry/FhirContextSearchParamRegistryTest.java +++ b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/registry/FhirContextSearchParamRegistryTest.java @@ -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) diff --git a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParamRegistryImplTest.java b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParamRegistryImplTest.java index f379779f42d..d53afa15970 100644 --- a/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParamRegistryImplTest.java +++ b/hapi-fhir-jpaserver-searchparam/src/test/java/ca/uhn/fhir/jpa/searchparam/registry/SearchParamRegistryImplTest.java @@ -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")); diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml index e54ec66cff7..3a2409ffee7 100644 --- a/hapi-fhir-jpaserver-subscription/pom.xml +++ b/hapi-fhir-jpaserver-subscription/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/match/registry/SubscriptionLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/match/registry/SubscriptionLoader.java index 4bea23c546f..dbe6946869f 100644 --- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/match/registry/SubscriptionLoader.java +++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/match/registry/SubscriptionLoader.java @@ -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() diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/topic/SubscriptionTopicLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/topic/SubscriptionTopicLoader.java index de78e59a741..fe81226df6c 100644 --- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/topic/SubscriptionTopicLoader.java +++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/topic/SubscriptionTopicLoader.java @@ -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); diff --git a/hapi-fhir-jpaserver-test-dstu2/pom.xml b/hapi-fhir-jpaserver-test-dstu2/pom.xml index 401ada09cfd..dbcc2993fa2 100644 --- a/hapi-fhir-jpaserver-test-dstu2/pom.xml +++ b/hapi-fhir-jpaserver-test-dstu2/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu3/pom.xml b/hapi-fhir-jpaserver-test-dstu3/pom.xml index 77199d5dd61..d08301febb2 100644 --- a/hapi-fhir-jpaserver-test-dstu3/pom.xml +++ b/hapi-fhir-jpaserver-test-dstu3/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/searchparam/MatchUrlServiceTest.java b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/searchparam/MatchUrlServiceTest.java index f05aa52be17..a74b3771316 100644 --- a/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/searchparam/MatchUrlServiceTest.java +++ b/hapi-fhir-jpaserver-test-dstu3/src/test/java/ca/uhn/fhir/jpa/searchparam/MatchUrlServiceTest.java @@ -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()); diff --git a/hapi-fhir-jpaserver-test-r4/pom.xml b/hapi-fhir-jpaserver-test-r4/pom.xml index f8fd3550fd2..5a7a110a034 100644 --- a/hapi-fhir-jpaserver-test-r4/pom.xml +++ b/hapi-fhir-jpaserver-test-r4/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/ChainingR4SearchTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/ChainingR4SearchTest.java index 17fdab2bf8c..c97ff21fc75 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/ChainingR4SearchTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/ChainingR4SearchTest.java @@ -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()); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ComboUniqueParamTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ComboUniqueParamTest.java index b46d8b964d6..ffd95aac284 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ComboUniqueParamTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ComboUniqueParamTest.java @@ -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 uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation"); + List 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 params = mySearchParamRegistry.getActiveComboSearchParams("Patient"); + List params = mySearchParamRegistry.getActiveComboSearchParams("Patient", null); assertThat(params).hasSize(1); assertEquals(ComboSearchParamType.UNIQUE, params.get(0).getComboSearchParamType()); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java index a9f3cc57519..7d4ae952af1 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java @@ -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()); } diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/SearchParamExtractorR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/SearchParamExtractorR4Test.java index cf64663ec4d..109e972edb4 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/SearchParamExtractorR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/SearchParamExtractorR4Test.java @@ -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 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 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 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 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")); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantBatchOperationR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantBatchOperationR4Test.java index b1301470eab..b16277a4bf2 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantBatchOperationR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/MultitenantBatchOperationR4Test.java @@ -159,7 +159,7 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv myBatch2JobHelper.awaitJobCompletion(jobId.getValue()); - ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation").getSearchParamNames()); + ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation", null).getSearchParamNames()); logAllTokenIndexes(); @@ -196,7 +196,7 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv myBatch2JobHelper.awaitJobCompletion(jobId.getValue()); - ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation").getSearchParamNames()); + ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation", null).getSearchParamNames()); logAllTokenIndexes(); runInTransaction(() -> { @@ -224,7 +224,7 @@ public class MultitenantBatchOperationR4Test extends BaseMultitenantResourceProv doCreateResource(reindexTestHelper.buildObservationWithAlleleExtension(Observation.ObservationStatus.CANCELLED)); reindexTestHelper.createAlleleSearchParameter(); - ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation").getSearchParamNames()); + ourLog.info("Search params: {}", mySearchParamRegistry.getActiveSearchParams("Observation", null).getSearchParamNames()); // The searchparam value is on the observation, but it hasn't been indexed yet myTenantClientInterceptor.setTenantId(TENANT_A); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java index 0bee635ccc0..1f80074267c 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java @@ -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); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index d97013876ea..1ddb1cca9d3 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -353,7 +353,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { IFhirResourceDao 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 organizationDao = myDaoRegistry.getResourceDao(Organization.class); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java index ec11b173a61..e9c5bba1a80 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/ValueSetExpansionR4Test.java @@ -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()); } diff --git a/hapi-fhir-jpaserver-test-r4b/pom.xml b/hapi-fhir-jpaserver-test-r4b/pom.xml index fdfe6b44750..a87434cc1b9 100644 --- a/hapi-fhir-jpaserver-test-r4b/pom.xml +++ b/hapi-fhir-jpaserver-test-r4b/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r5/pom.xml b/hapi-fhir-jpaserver-test-r5/pom.xml index 36ba8df4382..39e0d036d5a 100644 --- a/hapi-fhir-jpaserver-test-r5/pom.xml +++ b/hapi-fhir-jpaserver-test-r5/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/r5/UpliftedRefchainsAndChainedSortingR5Test.java b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/r5/UpliftedRefchainsAndChainedSortingR5Test.java index f852b379a76..8cf00effbfc 100644 --- a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/r5/UpliftedRefchainsAndChainedSortingR5Test.java +++ b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/dao/r5/UpliftedRefchainsAndChainedSortingR5Test.java @@ -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")); diff --git a/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/SearchParameterDisabledForQueryingR5Test.java b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/SearchParameterDisabledForQueryingR5Test.java new file mode 100644 index 00000000000..b1cc6f53cd8 --- /dev/null +++ b/hapi-fhir-jpaserver-test-r5/src/test/java/ca/uhn/fhir/jpa/provider/r5/SearchParameterDisabledForQueryingR5Test.java @@ -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 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 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 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; + } + } + } + +} diff --git a/hapi-fhir-jpaserver-test-utilities/pom.xml b/hapi-fhir-jpaserver-test-utilities/pom.xml index 1b462be4e94..2d871304a7c 100644 --- a/hapi-fhir-jpaserver-test-utilities/pom.xml +++ b/hapi-fhir-jpaserver-test-utilities/pom.xml @@ -6,7 +6,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/util/ComboSearchParameterTestHelper.java b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/util/ComboSearchParameterTestHelper.java new file mode 100644 index 00000000000..f026ac642ba --- /dev/null +++ b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/util/ComboSearchParameterTestHelper.java @@ -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); + + } + +} diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/search/ExtendedHSearchIndexExtractorTest.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/search/ExtendedHSearchIndexExtractorTest.java index 6f85907b4a5..cb7ae2cf928 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/search/ExtendedHSearchIndexExtractorTest.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/search/ExtendedHSearchIndexExtractorTest.java @@ -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); diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/validation/SearchParameterDaoValidatorTest.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/validation/SearchParameterDaoValidatorTest.java index 5cac1bf8421..76356433611 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/validation/SearchParameterDaoValidatorTest.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/dao/validation/SearchParameterDaoValidatorTest.java @@ -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 diff --git a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilderTest.java b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilderTest.java index 550ed46cd10..cac4107d986 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilderTest.java +++ b/hapi-fhir-jpaserver-test-utilities/src/test/java/ca/uhn/fhir/jpa/search/builder/predicate/ResourceLinkPredicateBuilderTest.java @@ -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 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 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 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 result = myResourceLinkPredicateBuilder.createResourceLinkPaths(resourceType, paramName, List.of("Group")); assertThat(result).isEmpty(); } diff --git a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml index 0b75736bceb..dc293891cac 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/pom.xml +++ b/hapi-fhir-jpaserver-uhnfhirtest/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-server-cds-hooks/pom.xml b/hapi-fhir-server-cds-hooks/pom.xml index e918f3c485a..b575d54827d 100644 --- a/hapi-fhir-server-cds-hooks/pom.xml +++ b/hapi-fhir-server-cds-hooks/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-mdm/pom.xml b/hapi-fhir-server-mdm/pom.xml index f8ef8e73447..2ccc6687987 100644 --- a/hapi-fhir-server-mdm/pom.xml +++ b/hapi-fhir-server-mdm/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/config/MdmRuleValidator.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/config/MdmRuleValidator.java index cfd68b3545d..3bb0187f50d 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/config/MdmRuleValidator.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/rules/config/MdmRuleValidator.java @@ -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 + "'"); } diff --git a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchParamSvc.java b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchParamSvc.java index 459f35ba31d..18043f0687c 100644 --- a/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchParamSvc.java +++ b/hapi-fhir-server-mdm/src/main/java/ca/uhn/fhir/mdm/svc/MdmSearchParamSvc.java @@ -67,7 +67,8 @@ public class MdmSearchParamSvc { public List 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); } diff --git a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/config/MdmRuleValidatorTest.java b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/config/MdmRuleValidatorTest.java index e2e1253079f..a30d7dfc8bb 100644 --- a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/config/MdmRuleValidatorTest.java +++ b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/config/MdmRuleValidatorTest.java @@ -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 diff --git a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/CustomResourceMatcherR4Test.java b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/CustomResourceMatcherR4Test.java index d46e225119f..a6392d4d6f9 100644 --- a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/CustomResourceMatcherR4Test.java +++ b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/CustomResourceMatcherR4Test.java @@ -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 diff --git a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/FhirPathResourceMatcherR4Test.java b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/FhirPathResourceMatcherR4Test.java index d46a0d06776..275182d2918 100644 --- a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/FhirPathResourceMatcherR4Test.java +++ b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/FhirPathResourceMatcherR4Test.java @@ -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(); diff --git a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvcLoggingTest.java b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvcLoggingTest.java index 7ee69ea4d22..b13f3676b46 100644 --- a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvcLoggingTest.java +++ b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvcLoggingTest.java @@ -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()); diff --git a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvcR4Test.java b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvcR4Test.java index 4219d931382..cba439338d4 100644 --- a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvcR4Test.java +++ b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/MdmResourceMatcherSvcR4Test.java @@ -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()); diff --git a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/ResourceMatcherR4Test.java b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/ResourceMatcherR4Test.java index 74ab179211d..a2401c9271d 100644 --- a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/ResourceMatcherR4Test.java +++ b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/rules/svc/ResourceMatcherR4Test.java @@ -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(); diff --git a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/svc/EIDHelperR4Test.java b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/svc/EIDHelperR4Test.java index 16e12971cbc..23373d91f10 100644 --- a/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/svc/EIDHelperR4Test.java +++ b/hapi-fhir-server-mdm/src/test/java/ca/uhn/fhir/mdm/svc/EIDHelperR4Test.java @@ -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)) { diff --git a/hapi-fhir-server-openapi/pom.xml b/hapi-fhir-server-openapi/pom.xml index 52977af6093..f3eb5ea4a17 100644 --- a/hapi-fhir-server-openapi/pom.xml +++ b/hapi-fhir-server-openapi/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/pom.xml b/hapi-fhir-server/pom.xml index c546e4089f7..9e587344285 100644 --- a/hapi-fhir-server/pom.xml +++ b/hapi-fhir-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerConfiguration.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerConfiguration.java index 9ef4d74f66f..8538fe4ba2a 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerConfiguration.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/RestfulServerConfiguration.java @@ -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)); } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/SearchPreferHandlingInterceptor.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/SearchPreferHandlingInterceptor.java index 391667870fa..ebf64da0c99 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/SearchPreferHandlingInterceptor.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/SearchPreferHandlingInterceptor.java @@ -130,7 +130,8 @@ public class SearchPreferHandlingInterceptor { } } - RuntimeSearchParam activeSearchParam = searchParamRetriever.getActiveSearchParam(resourceName, paramName); + RuntimeSearchParam activeSearchParam = searchParamRetriever.getActiveSearchParam( + resourceName, paramName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); if (activeSearchParam == null) { if (theHandling == PreferHandlingEnum.LENIENT) { @@ -144,11 +145,14 @@ public class SearchPreferHandlingInterceptor { } else { // Strict handling - List allowedParams = - searchParamRetriever.getActiveSearchParams(resourceName).getSearchParamNames().stream() - .sorted() - .distinct() - .collect(Collectors.toList()); + List allowedParams = searchParamRetriever + .getActiveSearchParams( + resourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH) + .getSearchParamNames() + .stream() + .sorted() + .distinct() + .collect(Collectors.toList()); HapiLocalizer localizer = theRequestDetails.getFhirContext().getLocalizer(); String msg = localizer.getMessage( "ca.uhn.fhir.jpa.dao.BaseStorageDao.invalidSearchParameter", diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ServerCapabilityStatementProvider.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ServerCapabilityStatementProvider.java index f410effdaba..c867dc0b66a 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ServerCapabilityStatementProvider.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/ServerCapabilityStatementProvider.java @@ -318,6 +318,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv case UPDATE: terser.setElement(resource, "conditionalUpdate", "true"); break; + case UPDATE_REWRITE_HISTORY: case HISTORY_INSTANCE: case HISTORY_SYSTEM: case HISTORY_TYPE: @@ -401,12 +402,13 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv */ ResourceSearchParams searchParams; ISearchParamRegistry searchParamRegistry; - ResourceSearchParams serverConfigurationActiveSearchParams = - serverConfiguration.getActiveSearchParams(resourceName); + ResourceSearchParams serverConfigurationActiveSearchParams = serverConfiguration.getActiveSearchParams( + resourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); if (mySearchParamRegistry != null) { searchParamRegistry = mySearchParamRegistry; searchParams = mySearchParamRegistry - .getActiveSearchParams(resourceName) + .getActiveSearchParams( + resourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH) .makeCopy(); for (String nextBuiltInSpName : serverConfigurationActiveSearchParams.getSearchParamNames()) { if (nextBuiltInSpName.startsWith("_") @@ -465,7 +467,8 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv } for (RuntimeSearchParam t : searchParamRegistry - .getActiveSearchParams(nextResourceName) + .getActiveSearchParams( + nextResourceName, ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH) .values()) { if (t.getParamType() == RestSearchParameterTypeEnum.REFERENCE) { if (isNotBlank(t.getName())) { diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/FhirContextSearchParamRegistry.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/FhirContextSearchParamRegistry.java index ba2e21089ba..fc9cd4d6994 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/FhirContextSearchParamRegistry.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/FhirContextSearchParamRegistry.java @@ -35,6 +35,8 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import static ca.uhn.fhir.rest.server.util.ISearchParamRegistry.isAllowedForContext; + public class FhirContextSearchParamRegistry implements ISearchParamRegistry { private final List myExtraSearchParams = new ArrayList<>(); @@ -54,20 +56,28 @@ public class FhirContextSearchParamRegistry 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(String theResourceName) { + public ResourceSearchParams getActiveSearchParams( + @Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) { ResourceSearchParams retval = new ResourceSearchParams(theResourceName); RuntimeResourceDefinition nextResDef = myCtx.getResourceDefinition(theResourceName); for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) { - retval.put(nextSp.getName(), nextSp); + if (isAllowedForContext(nextSp, theContext)) { + retval.put(nextSp.getName(), nextSp); + } } for (RuntimeSearchParam next : myExtraSearchParams) { - retval.put(next.getName(), next); + if (isAllowedForContext(next, theContext)) { + retval.put(next.getName(), next); + } } return retval; @@ -78,34 +88,42 @@ public class FhirContextSearchParamRegistry implements ISearchParamRegistry { } @Override - public List getActiveComboSearchParams(String theResourceName, Set theParamNames) { + public List getActiveComboSearchParams( + @Nonnull String theResourceName, + @Nonnull Set theParamNames, + @Nonnull SearchParamLookupContextEnum theContext) { throw new UnsupportedOperationException(Msg.code(2066)); } @Nullable @Override - public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) { + public RuntimeSearchParam getActiveSearchParamByUrl( + @Nonnull String theUrl, @Nonnull SearchParamLookupContextEnum theContext) { // simple implementation for test support return myCtx.getResourceTypes().stream() - .flatMap(type -> getActiveSearchParams(type).values().stream()) + .flatMap(type -> getActiveSearchParams(type, theContext).values().stream()) .filter(rsp -> theUrl.equals(rsp.getUri())) .findFirst() .orElse(null); } @Override - public List getActiveComboSearchParams(String theResourceName) { + public List getActiveComboSearchParams( + @Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) { throw new UnsupportedOperationException(Msg.code(2068)); } @Override public List getActiveComboSearchParams( - String theResourceName, ComboSearchParamType theParamType) { + @Nonnull String theResourceName, + @Nonnull ComboSearchParamType theParamType, + @Nonnull SearchParamLookupContextEnum theContext) { throw new UnsupportedOperationException(Msg.code(2209)); } @Override - public Optional getActiveComboSearchParamById(String theResourceName, IIdType theId) { + public Optional getActiveComboSearchParamById( + @Nonnull String theResourceName, @Nonnull IIdType theId) { throw new UnsupportedOperationException(Msg.code(2211)); } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/ISearchParamRegistry.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/ISearchParamRegistry.java index 12b628fe641..f2cf439300d 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/ISearchParamRegistry.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/ISearchParamRegistry.java @@ -25,6 +25,7 @@ import ca.uhn.fhir.context.phonetic.IPhoneticEncoder; import ca.uhn.fhir.i18n.Msg; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import org.hl7.fhir.instance.model.api.IAnyResource; import org.hl7.fhir.instance.model.api.IIdType; @@ -50,14 +51,36 @@ public interface ISearchParamRegistry { } /** - * @return Returns {@literal null} if no match + * @deprecated Use {@link #getActiveSearchParam(String, String, SearchParamLookupContextEnum)} */ - RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName); + @Deprecated(since = "8.0.0", forRemoval = true) + default RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName) { + return getActiveSearchParam(theResourceName, theParamName, SearchParamLookupContextEnum.ALL); + } /** + * @param theContext The context to return active search params for, or {@literal null} to return any active search params + * @return Returns {@literal null} if no match + */ + RuntimeSearchParam getActiveSearchParam( + @Nonnull String theResourceName, + @Nonnull String theParamName, + @Nonnull SearchParamLookupContextEnum theContext); + + /** + * @deprecated Use {@link #getActiveSearchParam(String, String, SearchParamLookupContextEnum)} + */ + @Deprecated(since = "8.0.0", forRemoval = true) + default ResourceSearchParams getActiveSearchParams(String theResourceName) { + return getActiveSearchParams(theResourceName, SearchParamLookupContextEnum.ALL); + } + + /** + * @param theContext The context to return active search params for, or {@literal null} to return any active search params * @return Returns all active search params for the given resource */ - ResourceSearchParams getActiveSearchParams(String theResourceName); + ResourceSearchParams getActiveSearchParams( + @Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext); /** * Request that the cache be refreshed now, in the current thread @@ -77,22 +100,35 @@ public interface ISearchParamRegistry { */ default void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) {} - default List getActiveComboSearchParams(String theResourceName) { + /** + * @param theContext The context to return active search params for, or {@literal null} to return any active search params + */ + default List getActiveComboSearchParams( + @Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) { return Collections.emptyList(); } // TODO ND remove default implementation default List getActiveComboSearchParams( - String theResourceName, ComboSearchParamType theParamType) { + @Nonnull String theResourceName, + @Nonnull ComboSearchParamType theParamType, + @Nonnull SearchParamLookupContextEnum theContext) { return Collections.emptyList(); } // TODO ND remove default implementation - default Optional getActiveComboSearchParamById(String theResourceName, IIdType theId) { + default Optional getActiveComboSearchParamById( + @Nonnull String theResourceName, @Nonnull IIdType theId) { return Optional.empty(); } - default List getActiveComboSearchParams(String theResourceName, Set theParamNames) { + /** + * @param theContext The context to return active search params for, or {@literal null} to return any active search params + */ + default List getActiveComboSearchParams( + @Nonnull String theResourceName, + @Nonnull Set theParamNames, + @Nonnull SearchParamLookupContextEnum theContext) { return Collections.emptyList(); } @@ -100,10 +136,13 @@ public interface ISearchParamRegistry { * Returns a collection containing all of the valid active search parameters. This method is intended for * creating error messages for users as opposed to actual search processing. It will include meta parameters * such as _id and _lastUpdated. + * + * @param theContext The context to return active search params for, or {@literal null} to return any active search params */ - default Collection getValidSearchParameterNamesIncludingMeta(String theResourceName) { + default Collection getValidSearchParameterNamesIncludingMeta( + @Nonnull String theResourceName, @Nonnull SearchParamLookupContextEnum theContext) { TreeSet retval; - ResourceSearchParams activeSearchParams = getActiveSearchParams(theResourceName); + ResourceSearchParams activeSearchParams = getActiveSearchParams(theResourceName, theContext); if (activeSearchParams == null) { retval = new TreeSet<>(); } else { @@ -117,23 +156,28 @@ public interface ISearchParamRegistry { /** * Fetch a SearchParameter by URL * + * @param theContext The context to return active search params for, or {@literal null} to return any active search params * @return Returns null if it can't be found */ @Nullable - RuntimeSearchParam getActiveSearchParamByUrl(String theUrl); + RuntimeSearchParam getActiveSearchParamByUrl( + @Nonnull String theUrl, @Nonnull SearchParamLookupContextEnum theContext); /** * Find a search param for a resource. First, check the resource itself, then check the top-level `Resource` resource. * * @param theResourceType the resource type. * @param theParamName the search parameter name. - * + * @param theContext The context to return active search params for, or {@literal null} to return any active search params * @return the {@link RuntimeSearchParam} that is found. */ - default RuntimeSearchParam getRuntimeSearchParam(String theResourceType, String theParamName) { - RuntimeSearchParam availableSearchParamDef = getActiveSearchParam(theResourceType, theParamName); + default RuntimeSearchParam getRuntimeSearchParam( + @Nonnull String theResourceType, + @Nonnull String theParamName, + @Nonnull SearchParamLookupContextEnum theContext) { + RuntimeSearchParam availableSearchParamDef = getActiveSearchParam(theResourceType, theParamName, theContext); if (availableSearchParamDef == null) { - availableSearchParamDef = getActiveSearchParam("Resource", theParamName); + availableSearchParamDef = getActiveSearchParam("Resource", theParamName, theContext); } if (availableSearchParamDef == null) { throw new InvalidRequestException( @@ -145,17 +189,58 @@ public interface ISearchParamRegistry { /** * Get all the search params for a resource. First, check the resource itself, then check the top-level `Resource` resource and combine the two. * + * @param theContext The context to return active search params for, or {@literal null} to return any active search params * @param theResourceType the resource type. - * * @return the {@link ResourceSearchParams} that has all the search params. */ - default ResourceSearchParams getRuntimeSearchParams(String theResourceType) { + default ResourceSearchParams getRuntimeSearchParams( + @Nonnull String theResourceType, @Nonnull SearchParamLookupContextEnum theContext) { ResourceSearchParams availableSearchParams = - getActiveSearchParams(theResourceType).makeCopy(); - ResourceSearchParams resourceSearchParams = getActiveSearchParams("Resource"); + getActiveSearchParams(theResourceType, theContext).makeCopy(); + ResourceSearchParams resourceSearchParams = getActiveSearchParams("Resource", theContext); resourceSearchParams .getSearchParamNames() .forEach(param -> availableSearchParams.addSearchParamIfAbsent(param, resourceSearchParams.get(param))); return availableSearchParams; } + + /** + * Describes the context for looking up individual search parameters or lists of search parameters. + * These can be thought of as filter criteria - Most search parameters generally apply to all + * context, but some may be explicitly defined to only work for some. + * + * @since 8.0.0 + */ + enum SearchParamLookupContextEnum { + /** + * Search parameter should be used when indexing a resource that is being persisted + */ + INDEX, + /** + * Search parameter should be used for searching. This includes explicit searches such as + * standard REST FHIR searches, but also includes resolving match URLs, subscription criteria, + * etc. + */ + SEARCH, + /** + * Search parameter should be used for sorting via the {@literal _sort} parameter. + */ + SORT, + /** + * Return any search parameters that are known to the system for any context + */ + ALL + } + + static boolean isAllowedForContext( + @Nonnull RuntimeSearchParam theSearchParam, @Nullable SearchParamLookupContextEnum theContext) { + /* + * I'm thinking that a future enhancement might be to allow a SearchParameter to declare that it + * is supported for searching or for sorting or for both - But for now these are one and the same. + */ + if (theContext == SearchParamLookupContextEnum.SEARCH || theContext == SearchParamLookupContextEnum.SORT) { + return theSearchParam.isEnabledForSearching(); + } + return true; + } } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/ResourceSearchParams.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/ResourceSearchParams.java index 50327cb5d55..b964ffb515b 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/ResourceSearchParams.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/util/ResourceSearchParams.java @@ -30,9 +30,13 @@ import java.util.Map; import java.util.Set; import java.util.stream.Stream; +import static ca.uhn.fhir.rest.server.util.ISearchParamRegistry.isAllowedForContext; + public class ResourceSearchParams { private final String myResourceName; private final Map myMap; + private final Map myContextToParams = + new HashMap<>(); public ResourceSearchParams(String theResourceName) { myResourceName = theResourceName; @@ -48,6 +52,32 @@ public class ResourceSearchParams { return myMap.values(); } + /** + * Returns a filtered view of this {@link ResourceSearchParams} instance if + * any parameters are not valid for the given {@literal theContext}. + */ + public ResourceSearchParams toFilteredForContext(ISearchParamRegistry.SearchParamLookupContextEnum theContext) { + if (theContext == null) { + return this; + } + synchronized (this) { + ResourceSearchParams retVal = myContextToParams.get(theContext); + if (retVal == null) { + Map filteredMap = new HashMap<>(myMap.size()); + for (var nextEntry : myMap.entrySet()) { + String key = nextEntry.getKey(); + RuntimeSearchParam nextParam = nextEntry.getValue(); + if (isAllowedForContext(nextParam, theContext)) { + filteredMap.put(key, nextParam); + } + } + retVal = new ResourceSearchParams(myResourceName, filteredMap); + myContextToParams.put(theContext, retVal); + } + return retVal; + } + } + public static ResourceSearchParams empty(String theResourceName) { return new ResourceSearchParams(theResourceName, Collections.emptyMap()); } @@ -57,6 +87,7 @@ public class ResourceSearchParams { } public void remove(String theName) { + myContextToParams.clear(); myMap.remove(theName); } @@ -69,10 +100,12 @@ public class ResourceSearchParams { } public RuntimeSearchParam put(String theName, RuntimeSearchParam theSearchParam) { + myContextToParams.clear(); return myMap.put(theName, theSearchParam); } public void addSearchParamIfAbsent(String theParamName, RuntimeSearchParam theRuntimeSearchParam) { + myContextToParams.clear(); myMap.putIfAbsent(theParamName, theRuntimeSearchParam); } diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml index bf3ad7b88e5..9100ff57373 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-api/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml index bf1ac109227..1c113662109 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml @@ -21,7 +21,7 @@ ca.uhn.hapi.fhir hapi-fhir-caching-api - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml index 02ee65b7546..447b897acb0 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-guava/pom.xml @@ -7,7 +7,7 @@ hapi-fhir-serviceloaders ca.uhn.hapi.fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml b/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml index 681571f22ee..b9e26c9bbdc 100644 --- a/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml +++ b/hapi-fhir-serviceloaders/hapi-fhir-caching-testing/pom.xml @@ -7,7 +7,7 @@ hapi-fhir ca.uhn.hapi.fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../../pom.xml diff --git a/hapi-fhir-serviceloaders/pom.xml b/hapi-fhir-serviceloaders/pom.xml index dd30a461633..4f4c79b162b 100644 --- a/hapi-fhir-serviceloaders/pom.xml +++ b/hapi-fhir-serviceloaders/pom.xml @@ -5,7 +5,7 @@ hapi-deployable-pom ca.uhn.hapi.fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml index 2018d5bdefb..2aa9a667d9f 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml index cb97238c300..9d61904842c 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-apache/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT hapi-fhir-spring-boot-sample-client-apache diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml index f616b02ff64..8e12e9d930a 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-client-okhttp/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml index 8f685df4c7c..6c3fb378ea3 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot-samples - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml index 80403576f54..00493b33731 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir-spring-boot - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml index 604e613b5e3..369064e3a92 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-spring-boot/pom.xml b/hapi-fhir-spring-boot/pom.xml index 76cb09d60aa..ad501b97312 100644 --- a/hapi-fhir-spring-boot/pom.xml +++ b/hapi-fhir-spring-boot/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-sql-migrate/pom.xml b/hapi-fhir-sql-migrate/pom.xml index 5ed0423570a..a6839cea39d 100644 --- a/hapi-fhir-sql-migrate/pom.xml +++ b/hapi-fhir-sql-migrate/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2-jobs/pom.xml b/hapi-fhir-storage-batch2-jobs/pom.xml index 03b1fa78bb8..7d53202960d 100644 --- a/hapi-fhir-storage-batch2-jobs/pom.xml +++ b/hapi-fhir-storage-batch2-jobs/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2-test-utilities/pom.xml b/hapi-fhir-storage-batch2-test-utilities/pom.xml index 79dd3440099..bde3a4afffa 100644 --- a/hapi-fhir-storage-batch2-test-utilities/pom.xml +++ b/hapi-fhir-storage-batch2-test-utilities/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-batch2/pom.xml b/hapi-fhir-storage-batch2/pom.xml index 4bfa0f67206..d969f293560 100644 --- a/hapi-fhir-storage-batch2/pom.xml +++ b/hapi-fhir-storage-batch2/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-cr/pom.xml b/hapi-fhir-storage-cr/pom.xml index ff48662dc28..75e5caec2dc 100644 --- a/hapi-fhir-storage-cr/pom.xml +++ b/hapi-fhir-storage-cr/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-mdm/pom.xml b/hapi-fhir-storage-mdm/pom.xml index 203da52104f..a630a234bc0 100644 --- a/hapi-fhir-storage-mdm/pom.xml +++ b/hapi-fhir-storage-mdm/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage-test-utilities/pom.xml b/hapi-fhir-storage-test-utilities/pom.xml index 8064e78face..5e1a4749d5a 100644 --- a/hapi-fhir-storage-test-utilities/pom.xml +++ b/hapi-fhir-storage-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage/pom.xml b/hapi-fhir-storage/pom.xml index 3a7b8ce21d6..95601bdf362 100644 --- a/hapi-fhir-storage/pom.xml +++ b/hapi-fhir-storage/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseStorageDao.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseStorageDao.java index 45fcda04d08..1f1660b16ea 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseStorageDao.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/BaseStorageDao.java @@ -519,29 +519,48 @@ public abstract class BaseStorageDao { return; } - ResourceSearchParams searchParams = mySearchParamRegistry.getActiveSearchParams(getResourceName()); + ResourceSearchParams searchParams = mySearchParamRegistry.getActiveSearchParams( + getResourceName(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); Set paramNames = theSource.keySet(); for (String nextParamName : paramNames) { QualifierDetails qualifiedParamName = QualifierDetails.extractQualifiersFromParameterName(nextParamName); RuntimeSearchParam param = searchParams.get(qualifiedParamName.getParamName()); if (param == null) { - Collection validNames = - mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(getResourceName()); - String msg = getContext() - .getLocalizer() - .getMessageSanitized( - BaseStorageDao.class, - "invalidSearchParameter", - qualifiedParamName.getParamName(), - getResourceName(), - validNames); - throw new InvalidRequestException(Msg.code(524) + msg); + Collection validNames = mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta( + getResourceName(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); + RuntimeSearchParam notEnabledForSearchParam = mySearchParamRegistry.getActiveSearchParam( + getResourceName(), + qualifiedParamName.getParamName(), + ISearchParamRegistry.SearchParamLookupContextEnum.ALL); + if (notEnabledForSearchParam != null) { + String msg = getContext() + .getLocalizer() + .getMessageSanitized( + BaseStorageDao.class, + "invalidSearchParameterNotEnabledForSearch", + qualifiedParamName.getParamName(), + getResourceName(), + validNames); + throw new InvalidRequestException(Msg.code(2539) + msg); + } else { + String msg = getContext() + .getLocalizer() + .getMessageSanitized( + BaseStorageDao.class, + "invalidSearchParameter", + qualifiedParamName.getParamName(), + getResourceName(), + validNames); + throw new InvalidRequestException(Msg.code(524) + msg); + } } // Should not be null since the check above would have caught it - RuntimeSearchParam paramDef = - mySearchParamRegistry.getActiveSearchParam(getResourceName(), qualifiedParamName.getParamName()); + RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam( + getResourceName(), + qualifiedParamName.getParamName(), + ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); for (String nextValue : theSource.get(nextParamName)) { QualifiedParamList qualifiedParam = QualifiedParamList.splitQueryStringByCommasIgnoreEscape( diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/index/DaoResourceLinkResolver.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/index/DaoResourceLinkResolver.java index 9434e126936..3c584e8aed1 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/index/DaoResourceLinkResolver.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/index/DaoResourceLinkResolver.java @@ -105,8 +105,10 @@ public class DaoResourceLinkResolver implements RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(resourceType); Class type = resourceDef.getImplementingClass(); - RuntimeSearchParam searchParam = - mySearchParamRegistry.getActiveSearchParam(theSourceResourceName, thePathAndRef.getSearchParamName()); + RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam( + theSourceResourceName, + thePathAndRef.getSearchParamName(), + ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); T persistentId = null; if (theTransactionDetails != null) { diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/validation/SearchParameterDaoValidator.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/validation/SearchParameterDaoValidator.java index 48f0cdf817b..e8dda3ea4cb 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/validation/SearchParameterDaoValidator.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/dao/validation/SearchParameterDaoValidator.java @@ -73,8 +73,8 @@ public class SearchParameterDaoValidator { if (myStorageSettings.isDefaultSearchParamsCanBeOverridden() == false) { for (IPrimitiveType nextBaseType : searchParameter.getBase()) { String nextBase = nextBaseType.getValueAsString(); - RuntimeSearchParam existingSearchParam = - mySearchParamRegistry.getActiveSearchParam(nextBase, searchParameter.getCode()); + RuntimeSearchParam existingSearchParam = mySearchParamRegistry.getActiveSearchParam( + nextBase, searchParameter.getCode(), ISearchParamRegistry.SearchParamLookupContextEnum.ALL); if (existingSearchParam != null) { boolean isBuiltIn = existingSearchParam.getId() == null; isBuiltIn |= existingSearchParam.getUri().startsWith("http://hl7.org/fhir/SearchParameter/"); @@ -221,7 +221,8 @@ public class SearchParameterDaoValidator { .filter(SearchParameter.SearchParameterComponentComponent::hasDefinition) .map(SearchParameter.SearchParameterComponentComponent::getDefinition) .filter(Objects::nonNull) - .map(mySearchParamRegistry::getActiveSearchParamByUrl) + .map((String url) -> mySearchParamRegistry.getActiveSearchParamByUrl( + url, ISearchParamRegistry.SearchParamLookupContextEnum.ALL)) .filter(Objects::nonNull) .forEach(theRuntimeSp -> validateComponentSpTypeAgainstWhiteList( theRuntimeSp, getAllowedSearchParameterTypes(theSearchParameter))); diff --git a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/graphql/DaoRegistryGraphQLStorageServices.java b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/graphql/DaoRegistryGraphQLStorageServices.java index 8eeec832887..54b39d5c5d3 100644 --- a/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/graphql/DaoRegistryGraphQLStorageServices.java +++ b/hapi-fhir-storage/src/main/java/ca/uhn/fhir/jpa/graphql/DaoRegistryGraphQLStorageServices.java @@ -130,7 +130,8 @@ public class DaoRegistryGraphQLStorageServices implements IGraphQLStorageService RuntimeResourceDefinition typeDef = fhirContext.getResourceDefinition(theType); SearchParameterMap params = new SearchParameterMap(); - ResourceSearchParams searchParams = mySearchParamRegistry.getRuntimeSearchParams(typeDef.getName()); + ResourceSearchParams searchParams = mySearchParamRegistry.getRuntimeSearchParams( + typeDef.getName(), ISearchParamRegistry.SearchParamLookupContextEnum.SEARCH); for (Argument nextArgument : resourceSearchParam) { diff --git a/hapi-fhir-structures-dstu2.1/pom.xml b/hapi-fhir-structures-dstu2.1/pom.xml index 3f9157ec7fb..c05d5fd8a67 100644 --- a/hapi-fhir-structures-dstu2.1/pom.xml +++ b/hapi-fhir-structures-dstu2.1/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu2/pom.xml b/hapi-fhir-structures-dstu2/pom.xml index cb6d3075fee..fd167af4703 100644 --- a/hapi-fhir-structures-dstu2/pom.xml +++ b/hapi-fhir-structures-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-dstu3/pom.xml b/hapi-fhir-structures-dstu3/pom.xml index f22f142216c..abac98a84ee 100644 --- a/hapi-fhir-structures-dstu3/pom.xml +++ b/hapi-fhir-structures-dstu3/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-hl7org-dstu2/pom.xml b/hapi-fhir-structures-hl7org-dstu2/pom.xml index 0746dc2ed00..3ae013f8558 100644 --- a/hapi-fhir-structures-hl7org-dstu2/pom.xml +++ b/hapi-fhir-structures-hl7org-dstu2/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4/pom.xml b/hapi-fhir-structures-r4/pom.xml index bd85e89ca1d..8bed9856e8d 100644 --- a/hapi-fhir-structures-r4/pom.xml +++ b/hapi-fhir-structures-r4/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r4b/pom.xml b/hapi-fhir-structures-r4b/pom.xml index 1640143910e..ab6bec9493a 100644 --- a/hapi-fhir-structures-r4b/pom.xml +++ b/hapi-fhir-structures-r4b/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-structures-r5/pom.xml b/hapi-fhir-structures-r5/pom.xml index 99e0226c515..47abaaa070a 100644 --- a/hapi-fhir-structures-r5/pom.xml +++ b/hapi-fhir-structures-r5/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-test-utilities/pom.xml b/hapi-fhir-test-utilities/pom.xml index 23b6ea26fa3..49a1756a1f9 100644 --- a/hapi-fhir-test-utilities/pom.xml +++ b/hapi-fhir-test-utilities/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-testpage-overlay/pom.xml b/hapi-fhir-testpage-overlay/pom.xml index 4780d6ae2a4..477dd26b6bf 100644 --- a/hapi-fhir-testpage-overlay/pom.xml +++ b/hapi-fhir-testpage-overlay/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-fhir-validation-resources-dstu2.1/pom.xml b/hapi-fhir-validation-resources-dstu2.1/pom.xml index 8584f03e750..3c3d4b3f0d9 100644 --- a/hapi-fhir-validation-resources-dstu2.1/pom.xml +++ b/hapi-fhir-validation-resources-dstu2.1/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu2/pom.xml b/hapi-fhir-validation-resources-dstu2/pom.xml index 0b99c52a3ea..f9949c45a2a 100644 --- a/hapi-fhir-validation-resources-dstu2/pom.xml +++ b/hapi-fhir-validation-resources-dstu2/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-dstu3/pom.xml b/hapi-fhir-validation-resources-dstu3/pom.xml index 37de22f2b74..bfa8f0f09e8 100644 --- a/hapi-fhir-validation-resources-dstu3/pom.xml +++ b/hapi-fhir-validation-resources-dstu3/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4/pom.xml b/hapi-fhir-validation-resources-r4/pom.xml index f95193a3df9..1251df6561b 100644 --- a/hapi-fhir-validation-resources-r4/pom.xml +++ b/hapi-fhir-validation-resources-r4/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r4b/pom.xml b/hapi-fhir-validation-resources-r4b/pom.xml index 80e417e03e6..a7d3b7fa43f 100644 --- a/hapi-fhir-validation-resources-r4b/pom.xml +++ b/hapi-fhir-validation-resources-r4b/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation-resources-r5/pom.xml b/hapi-fhir-validation-resources-r5/pom.xml index 6bec6d96836..2b0fb626f70 100644 --- a/hapi-fhir-validation-resources-r5/pom.xml +++ b/hapi-fhir-validation-resources-r5/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-fhir-validation/pom.xml b/hapi-fhir-validation/pom.xml index 73b34e4e636..2ac7279fb38 100644 --- a/hapi-fhir-validation/pom.xml +++ b/hapi-fhir-validation/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-deployable-pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../hapi-deployable-pom/pom.xml diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index 922d9292d84..f38d95b4a9f 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/hapi-tinder-test/pom.xml b/hapi-tinder-test/pom.xml index 6361f0fd6b0..522533d34c2 100644 --- a/hapi-tinder-test/pom.xml +++ b/hapi-tinder-test/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index e4702185057..18e8f8b071a 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ ca.uhn.hapi.fhir hapi-fhir pom - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT HAPI-FHIR An open-source implementation of the FHIR specification in Java. diff --git a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml index 1bd1f10d939..3b86d9faf3a 100644 --- a/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml +++ b/tests/hapi-fhir-base-test-jaxrsserver-kotlin/pom.xml @@ -7,7 +7,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-client/pom.xml b/tests/hapi-fhir-base-test-mindeps-client/pom.xml index e3365df52e0..cfb03c7446e 100644 --- a/tests/hapi-fhir-base-test-mindeps-client/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-client/pom.xml @@ -4,7 +4,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../../pom.xml diff --git a/tests/hapi-fhir-base-test-mindeps-server/pom.xml b/tests/hapi-fhir-base-test-mindeps-server/pom.xml index 0cf2b458c2f..d616765f30b 100644 --- a/tests/hapi-fhir-base-test-mindeps-server/pom.xml +++ b/tests/hapi-fhir-base-test-mindeps-server/pom.xml @@ -5,7 +5,7 @@ ca.uhn.hapi.fhir hapi-fhir - 7.7.0-SNAPSHOT + 7.7.1-SNAPSHOT ../../pom.xml