001/*-
002 * #%L
003 * HAPI FHIR JPA Server
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.config;
021
022import ca.uhn.fhir.context.ConfigurationException;
023import ca.uhn.fhir.context.FhirContext;
024import ca.uhn.fhir.i18n.Msg;
025import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
026import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
027import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
028import ca.uhn.fhir.jpa.api.dao.IDao;
029import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
030import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
031import ca.uhn.fhir.jpa.dao.ISearchBuilder;
032import ca.uhn.fhir.jpa.dao.SearchBuilderFactory;
033import ca.uhn.fhir.jpa.dao.data.IResourceSearchViewDao;
034import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
035import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
036import ca.uhn.fhir.jpa.model.config.PartitionSettings;
037import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
038import ca.uhn.fhir.jpa.search.ExceptionService;
039import ca.uhn.fhir.jpa.search.ISynchronousSearchSvc;
040import ca.uhn.fhir.jpa.search.PersistedJpaBundleProviderFactory;
041import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
042import ca.uhn.fhir.jpa.search.SearchStrategyFactory;
043import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
044import ca.uhn.fhir.jpa.search.builder.sql.SqlObjectFactory;
045import ca.uhn.fhir.jpa.search.builder.tasks.SearchContinuationTask;
046import ca.uhn.fhir.jpa.search.builder.tasks.SearchTask;
047import ca.uhn.fhir.jpa.search.builder.tasks.SearchTaskParameters;
048import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc;
049import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc;
050import ca.uhn.fhir.rest.server.IPagingProvider;
051import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
052import jakarta.annotation.PostConstruct;
053import org.hl7.fhir.instance.model.api.IBaseResource;
054import org.springframework.beans.factory.BeanFactory;
055import org.springframework.beans.factory.annotation.Autowired;
056import org.springframework.context.annotation.Bean;
057import org.springframework.context.annotation.Configuration;
058import org.springframework.context.annotation.Scope;
059import org.springframework.transaction.PlatformTransactionManager;
060
061@Configuration
062public class SearchConfig {
063        public static final String SEARCH_TASK = "searchTask";
064        public static final String CONTINUE_TASK = "continueTask";
065
066        @Autowired
067        private JpaStorageSettings myStorageSettings;
068
069        @Autowired
070        private HapiFhirLocalContainerEntityManagerFactoryBean myEntityManagerFactory;
071
072        @Autowired
073        private SqlObjectFactory mySqlBuilderFactory;
074
075        @Autowired
076        private HibernatePropertiesProvider myDialectProvider;
077
078        @Autowired
079        private ISearchParamRegistry mySearchParamRegistry;
080
081        @Autowired
082        private PartitionSettings myPartitionSettings;
083
084        @Autowired
085        protected IInterceptorBroadcaster myInterceptorBroadcaster;
086
087        @Autowired
088        protected IResourceTagDao myResourceTagDao;
089
090        @Autowired
091        private DaoRegistry myDaoRegistry;
092
093        @Autowired
094        private IResourceSearchViewDao myResourceSearchViewDao;
095
096        @Autowired
097        private FhirContext myContext;
098
099        @Autowired
100        private IIdHelperService myIdHelperService;
101
102        @Autowired
103        private PlatformTransactionManager myManagedTxManager;
104
105        @Autowired
106        private SearchStrategyFactory mySearchStrategyFactory;
107
108        @Autowired
109        private SearchBuilderFactory mySearchBuilderFactory;
110
111        @Autowired
112        private ISearchResultCacheSvc mySearchResultCacheSvc;
113
114        @Autowired
115        private ISearchCacheSvc mySearchCacheSvc;
116
117        @Autowired
118        private IPagingProvider myPagingProvider;
119
120        @Autowired
121        private BeanFactory myBeanFactory;
122
123        @Autowired
124        private ISynchronousSearchSvc mySynchronousSearchSvc;
125
126        @Autowired
127        private PersistedJpaBundleProviderFactory myPersistedJpaBundleProviderFactory;
128
129        @Autowired
130        private IRequestPartitionHelperSvc myRequestPartitionHelperService;
131
132        @Autowired
133        private HapiTransactionService myHapiTransactionService;
134
135        @Bean
136        public ISearchCoordinatorSvc searchCoordinatorSvc() {
137                return new SearchCoordinatorSvcImpl(
138                                myContext,
139                                myStorageSettings,
140                                myInterceptorBroadcaster,
141                                myHapiTransactionService,
142                                mySearchCacheSvc,
143                                mySearchResultCacheSvc,
144                                myDaoRegistry,
145                                mySearchBuilderFactory,
146                                mySynchronousSearchSvc,
147                                myPersistedJpaBundleProviderFactory,
148                                mySearchParamRegistry,
149                                mySearchStrategyFactory,
150                                exceptionService(),
151                                myBeanFactory);
152        }
153
154        @Bean
155        public ExceptionService exceptionService() {
156                return new ExceptionService(myContext);
157        }
158
159        @Bean(name = ISearchBuilder.SEARCH_BUILDER_BEAN_NAME)
160        @Scope("prototype")
161        public ISearchBuilder newSearchBuilder(
162                        IDao theDao, String theResourceName, Class<? extends IBaseResource> theResourceType) {
163                return new SearchBuilder(
164                                theDao,
165                                theResourceName,
166                                myStorageSettings,
167                                myEntityManagerFactory,
168                                mySqlBuilderFactory,
169                                myDialectProvider,
170                                mySearchParamRegistry,
171                                myPartitionSettings,
172                                myInterceptorBroadcaster,
173                                myResourceTagDao,
174                                myDaoRegistry,
175                                myResourceSearchViewDao,
176                                myContext,
177                                myIdHelperService,
178                                theResourceType);
179        }
180
181        @Bean(name = SEARCH_TASK)
182        @Scope("prototype")
183        public SearchTask createSearchTask(SearchTaskParameters theParams) {
184                return new SearchTask(
185                                theParams,
186                                myHapiTransactionService,
187                                myContext,
188                                myInterceptorBroadcaster,
189                                mySearchBuilderFactory,
190                                mySearchResultCacheSvc,
191                                myStorageSettings,
192                                mySearchCacheSvc,
193                                myPagingProvider);
194        }
195
196        @Bean(name = CONTINUE_TASK)
197        @Scope("prototype")
198        public SearchContinuationTask createSearchContinuationTask(SearchTaskParameters theParams) {
199                return new SearchContinuationTask(
200                                theParams,
201                                myHapiTransactionService,
202                                myContext,
203                                myInterceptorBroadcaster,
204                                mySearchBuilderFactory,
205                                mySearchResultCacheSvc,
206                                myStorageSettings,
207                                mySearchCacheSvc,
208                                myPagingProvider,
209                                exceptionService() // singleton
210                                );
211        }
212
213        @PostConstruct
214        public void validateConfiguration() {
215                if (myStorageSettings.isIndexStorageOptimized()
216                                && myPartitionSettings.isPartitioningEnabled()
217                                && myPartitionSettings.isIncludePartitionInSearchHashes()) {
218                        throw new ConfigurationException(Msg.code(2525) + "Incorrect configuration. "
219                                        + "StorageSettings#isIndexStorageOptimized and PartitionSettings.isIncludePartitionInSearchHashes "
220                                        + "cannot be enabled at the same time.");
221                }
222        }
223}