001/*-
002 * #%L
003 * HAPI FHIR JPA - Search Parameters
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.searchparam.extractor;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.context.FhirVersionEnum;
024import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
025import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
026import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
027import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
028import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
029import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
030import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
031import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized;
032import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
033import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
034import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
035import ca.uhn.fhir.jpa.model.entity.StorageSettings;
036import ca.uhn.fhir.rest.api.server.RequestDetails;
037import jakarta.annotation.Nonnull;
038import org.hl7.fhir.instance.model.api.IBaseResource;
039
040import static ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService.handleWarnings;
041
042public class SearchParamExtractionUtil {
043
044        private final FhirContext myFhirContext;
045        private final StorageSettings myStorageSettings;
046        private final ISearchParamExtractor mySearchParamExtractor;
047        private final IInterceptorBroadcaster myInterceptorBroadcaster;
048
049        public SearchParamExtractionUtil(
050                        FhirContext theFhirContext,
051                        StorageSettings theStorageSettings,
052                        ISearchParamExtractor theSearchParamExtractor,
053                        IInterceptorBroadcaster theInterceptorBroadcaster) {
054                myFhirContext = theFhirContext;
055                myStorageSettings = theStorageSettings;
056                mySearchParamExtractor = theSearchParamExtractor;
057                myInterceptorBroadcaster = theInterceptorBroadcaster;
058        }
059
060        public void extractSearchIndexParameters(
061                        RequestDetails theRequestDetails,
062                        ResourceIndexedSearchParams theParams,
063                        IBaseResource theResource,
064                        @Nonnull ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
065
066                // Strings
067                ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> strings =
068                                extractSearchParamStrings(theResource, theSearchParamFilter);
069                handleWarnings(theRequestDetails, myInterceptorBroadcaster, strings);
070                theParams.myStringParams.addAll(strings);
071
072                // Numbers
073                ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> numbers =
074                                extractSearchParamNumber(theResource, theSearchParamFilter);
075                handleWarnings(theRequestDetails, myInterceptorBroadcaster, numbers);
076                theParams.myNumberParams.addAll(numbers);
077
078                // Quantities
079                ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> quantities =
080                                extractSearchParamQuantity(theResource, theSearchParamFilter);
081                handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantities);
082                theParams.myQuantityParams.addAll(quantities);
083
084                if (myStorageSettings
085                                                .getNormalizedQuantitySearchLevel()
086                                                .equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_STORAGE_SUPPORTED)
087                                || myStorageSettings
088                                                .getNormalizedQuantitySearchLevel()
089                                                .equals(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_SUPPORTED)) {
090                        ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantityNormalized> quantitiesNormalized =
091                                        extractSearchParamQuantityNormalized(theResource, theSearchParamFilter);
092                        handleWarnings(theRequestDetails, myInterceptorBroadcaster, quantitiesNormalized);
093                        theParams.myQuantityNormalizedParams.addAll(quantitiesNormalized);
094                }
095
096                // Dates
097                ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> dates =
098                                extractSearchParamDates(theResource, theSearchParamFilter);
099                handleWarnings(theRequestDetails, myInterceptorBroadcaster, dates);
100                theParams.myDateParams.addAll(dates);
101
102                // URIs
103                ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> uris =
104                                extractSearchParamUri(theResource, theSearchParamFilter);
105                handleWarnings(theRequestDetails, myInterceptorBroadcaster, uris);
106                theParams.myUriParams.addAll(uris);
107
108                // Tokens (can result in both Token and String, as we index the display name for
109                // the types: Coding, CodeableConcept)
110                ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> tokens =
111                                extractSearchParamTokens(theResource, theSearchParamFilter);
112                for (BaseResourceIndexedSearchParam next : tokens) {
113                        if (next instanceof ResourceIndexedSearchParamToken) {
114                                theParams.myTokenParams.add((ResourceIndexedSearchParamToken) next);
115                        } else if (next instanceof ResourceIndexedSearchParamCoords) {
116                                theParams.myCoordsParams.add((ResourceIndexedSearchParamCoords) next);
117                        } else {
118                                theParams.myStringParams.add((ResourceIndexedSearchParamString) next);
119                        }
120                }
121
122                // Composites
123                // dst2 composites use stuff like value[x] , and we don't support them.
124                if (myFhirContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
125                        ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamComposite> composites =
126                                        extractSearchParamComposites(theResource, theSearchParamFilter);
127                        handleWarnings(theRequestDetails, myInterceptorBroadcaster, composites);
128                        theParams.myCompositeParams.addAll(composites);
129                }
130
131                // Specials
132                ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> specials =
133                                extractSearchParamSpecial(theResource, theSearchParamFilter);
134                for (BaseResourceIndexedSearchParam next : specials) {
135                        if (next instanceof ResourceIndexedSearchParamCoords) {
136                                theParams.myCoordsParams.add((ResourceIndexedSearchParamCoords) next);
137                        }
138                }
139        }
140
141        private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> extractSearchParamDates(
142                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
143                return mySearchParamExtractor.extractSearchParamDates(theResource, theSearchParamFilter);
144        }
145
146        private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(
147                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
148                return mySearchParamExtractor.extractSearchParamNumber(theResource, theSearchParamFilter);
149        }
150
151        private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(
152                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
153                return mySearchParamExtractor.extractSearchParamQuantity(theResource, theSearchParamFilter);
154        }
155
156        private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantityNormalized>
157                        extractSearchParamQuantityNormalized(
158                                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
159                return mySearchParamExtractor.extractSearchParamQuantityNormalized(theResource, theSearchParamFilter);
160        }
161
162        private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> extractSearchParamStrings(
163                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
164                return mySearchParamExtractor.extractSearchParamStrings(theResource, theSearchParamFilter);
165        }
166
167        private ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(
168                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
169                return mySearchParamExtractor.extractSearchParamTokens(theResource, theSearchParamFilter);
170        }
171
172        private ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamSpecial(
173                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
174                return mySearchParamExtractor.extractSearchParamSpecial(theResource, theSearchParamFilter);
175        }
176
177        private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> extractSearchParamUri(
178                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
179                return mySearchParamExtractor.extractSearchParamUri(theResource, theSearchParamFilter);
180        }
181
182        private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamComposite> extractSearchParamComposites(
183                        IBaseResource theResource, ISearchParamExtractor.ISearchParamFilter theSearchParamFilter) {
184                return mySearchParamExtractor.extractSearchParamComposites(theResource, theSearchParamFilter);
185        }
186}