001/*- 002 * #%L 003 * HAPI FHIR Storage api 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.dao; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.interceptor.model.RequestPartitionId; 024import ca.uhn.fhir.jpa.model.search.SearchBuilderLoadIncludesParameters; 025import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails; 026import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; 027import ca.uhn.fhir.model.api.Include; 028import ca.uhn.fhir.rest.api.server.RequestDetails; 029import ca.uhn.fhir.rest.api.server.storage.IResourcePersistentId; 030import ca.uhn.fhir.rest.param.DateRangeParam; 031import com.google.common.collect.Streams; 032import jakarta.annotation.Nonnull; 033import jakarta.persistence.EntityManager; 034import org.apache.commons.io.IOUtils; 035import org.hl7.fhir.instance.model.api.IBaseResource; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039import java.util.ArrayList; 040import java.util.Collection; 041import java.util.List; 042import java.util.Set; 043import java.util.stream.Stream; 044 045public interface ISearchBuilder<T extends IResourcePersistentId<?>> { 046 static final Logger ourLog = LoggerFactory.getLogger(ISearchBuilder.class); 047 048 String SEARCH_BUILDER_BEAN_NAME = "SearchBuilder"; 049 050 IResultIterator<T> createQuery( 051 SearchParameterMap theParams, 052 SearchRuntimeDetails theSearchRuntime, 053 RequestDetails theRequest, 054 @Nonnull RequestPartitionId theRequestPartitionId); 055 056 /** 057 * Stream equivalent of createQuery. 058 * Note: the Stream must be closed. 059 */ 060 default Stream<T> createQueryStream( 061 SearchParameterMap theParams, 062 SearchRuntimeDetails theSearchRuntime, 063 RequestDetails theRequest, 064 @Nonnull RequestPartitionId theRequestPartitionId) { 065 IResultIterator<T> iter = createQuery(theParams, theSearchRuntime, theRequest, theRequestPartitionId); 066 // Adapt IResultIterator to stream 067 Stream<T> stream = Streams.stream(iter); 068 // The iterator might have an open ResultSet. Connect the close handler. 069 return stream.onClose(() -> IOUtils.closeQuietly(iter)); 070 } 071 072 Long createCountQuery( 073 SearchParameterMap theParams, 074 String theSearchUuid, 075 RequestDetails theRequest, 076 RequestPartitionId theRequestPartitionId); 077 078 void setMaxResultsToFetch(Integer theMaxResultsToFetch); 079 080 void loadResourcesByPid( 081 Collection<T> thePids, 082 Collection<T> theIncludedPids, 083 List<IBaseResource> theResourceListToPopulate, 084 boolean theForHistoryOperation, 085 RequestDetails theDetails); 086 087 default List<IBaseResource> loadResourcesByPid(Collection<T> thePids, RequestDetails theDetails) { 088 ArrayList<IBaseResource> result = new ArrayList<>(); 089 loadResourcesByPid(thePids, List.of(), result, false, theDetails); 090 if (result.size() != thePids.size()) { 091 ourLog.warn("Only found {} resources for {} pids", result.size(), thePids.size()); 092 } 093 return result; 094 } 095 096 /** 097 * Use the loadIncludes that takes a parameters object instead. 098 */ 099 @Deprecated 100 Set<T> loadIncludes( 101 FhirContext theContext, 102 EntityManager theEntityManager, 103 Collection<T> theMatches, 104 Collection<Include> theRevIncludes, 105 boolean theReverseMode, 106 DateRangeParam theLastUpdated, 107 String theSearchIdOrDescription, 108 RequestDetails theRequest, 109 Integer theMaxCount); 110 111 default Set<T> loadIncludes(SearchBuilderLoadIncludesParameters<T> theParameters) { 112 return this.loadIncludes( 113 theParameters.getFhirContext(), 114 theParameters.getEntityManager(), 115 theParameters.getMatches(), 116 theParameters.getIncludeFilters(), 117 theParameters.isReverseMode(), 118 theParameters.getLastUpdated(), 119 theParameters.getSearchIdOrDescription(), 120 theParameters.getRequestDetails(), 121 theParameters.getMaxCount()); 122 } 123 124 /** 125 * How many results may be fetched at once 126 */ 127 void setFetchSize(int theFetchSize); 128 129 void setPreviouslyAddedResourcePids(List<T> thePreviouslyAddedResourcePids); 130}