001/*- 002 * #%L 003 * HAPI FHIR JPA - Search Parameters 004 * %% 005 * Copyright (C) 2014 - 2025 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}