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.provider; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.i18n.Msg; 024import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; 025import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult; 026import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher; 027import ca.uhn.fhir.rest.api.server.RequestDetails; 028import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; 029import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider; 030import org.hl7.fhir.instance.model.api.IBaseResource; 031 032import java.util.ArrayList; 033import java.util.List; 034import java.util.function.Function; 035 036public class SearchableHashMapResourceProvider<T extends IBaseResource> extends HashMapResourceProvider<T> { 037 private final SearchParamMatcher mySearchParamMatcher; 038 039 /** 040 * Constructor 041 * 042 * @param theFhirContext The FHIR context 043 * @param theResourceType The resource type to support 044 */ 045 public SearchableHashMapResourceProvider( 046 FhirContext theFhirContext, Class<T> theResourceType, SearchParamMatcher theSearchParamMatcher) { 047 super(theFhirContext, theResourceType); 048 mySearchParamMatcher = theSearchParamMatcher; 049 } 050 051 public List<IBaseResource> searchByCriteria(String theCriteria, RequestDetails theRequest) { 052 return searchBy(resource -> mySearchParamMatcher.match(theCriteria, resource, theRequest), theRequest); 053 } 054 055 public List<IBaseResource> searchByParams(SearchParameterMap theSearchParams, RequestDetails theRequest) { 056 return searchBy( 057 resource -> mySearchParamMatcher.match( 058 theSearchParams.toNormalizedQueryString(getFhirContext()), resource, theRequest), 059 theRequest); 060 } 061 062 private List<IBaseResource> searchBy( 063 Function<IBaseResource, InMemoryMatchResult> theMatcher, RequestDetails theRequest) { 064 mySearchCount.incrementAndGet(); 065 List<T> allEResources = getAllResources(); 066 067 List<T> matches = new ArrayList<>(); 068 for (T resource : allEResources) { 069 InMemoryMatchResult result = theMatcher.apply(resource); 070 if (!result.supported()) { 071 throw new InvalidRequestException( 072 Msg.code(502) + "Search not supported by in-memory matcher: " + result.getUnsupportedReason()); 073 } 074 if (result.matched()) { 075 matches.add(resource); 076 } 077 } 078 return fireInterceptorsAndFilterAsNeeded(matches, theRequest); 079 } 080}