e47bb1d485ae30e687f19f44e1bcd32ad57d8d12
[taxeditor.git] / taxeditor-store / src / main / java / eu / etaxonomy / taxeditor / store / CdmStore.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.taxeditor.store;
11
12 import java.util.ArrayList;
13 import java.util.List;
14
15 import org.apache.log4j.Logger;
16 import org.eclipse.core.runtime.Status;
17 import org.eclipse.ui.PlatformUI;
18 import org.springframework.core.io.ClassPathResource;
19 import org.springframework.core.io.Resource;
20 import org.springframework.security.providers.ProviderManager;
21
22 import eu.etaxonomy.cdm.api.application.CdmApplicationController;
23 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
24 import eu.etaxonomy.cdm.api.service.IAgentService;
25 import eu.etaxonomy.cdm.api.service.ICommonService;
26 import eu.etaxonomy.cdm.api.service.ILocationService;
27 import eu.etaxonomy.cdm.api.service.INameService;
28 import eu.etaxonomy.cdm.api.service.IReferenceService;
29 import eu.etaxonomy.cdm.api.service.ITaxonService;
30 import eu.etaxonomy.cdm.api.service.ITaxonTreeService;
31 import eu.etaxonomy.cdm.api.service.ITermService;
32 import eu.etaxonomy.cdm.api.service.IUserService;
33 import eu.etaxonomy.cdm.api.service.IVocabularyService;
34 import eu.etaxonomy.cdm.api.service.config.IIdentifiableEntityServiceConfigurator;
35 import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;
36 import eu.etaxonomy.cdm.database.DataSourceNotFoundException;
37 import eu.etaxonomy.cdm.database.DatabaseSchemaMismatchException;
38 import eu.etaxonomy.cdm.database.DbSchemaValidation;
39 import eu.etaxonomy.cdm.database.ICdmDataSource;
40 import eu.etaxonomy.cdm.ext.IEditGeoService;
41 import eu.etaxonomy.cdm.model.agent.AgentBase;
42 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
43 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
44 import eu.etaxonomy.cdm.model.common.Language;
45 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
46 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
47 import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
48 import eu.etaxonomy.taxeditor.dialogs.DatasourceLauncherDialog;
49 import eu.etaxonomy.taxeditor.io.ExportHandler;
50 import eu.etaxonomy.taxeditor.io.ImportHandler;
51 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
52 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
53
54 /**
55 * This implementation of ICdmDataRepository depends on hibernate sessions to store the data correctly
56 * for the current session. No state is held in this class.
57 *
58 * Only methods that either get or manipulate data are exposed here. So this class acts as a facade
59 * for the methods in cdmlib-service.
60 *
61 *
62 * @author n.hoffmann
63 * @created 17.03.2009
64 * @version 1.0
65 */
66 public class CdmStore{
67 private static final Logger logger = Logger.getLogger(CdmStore.class);
68
69 // FIXME change this to ClassPathResources as soon as it is included into the plugin
70 private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource("/eu/etaxonomy/cdm/editorApplicationContext.xml", TaxeditorStorePlugin.class.getClassLoader());
71 private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.UPDATE;
72
73 private static CdmStore instance;
74
75 private CdmApplicationController applicationController;
76
77 private static LoginManager loginManager;
78
79 private static ImportHandler importHandler;
80
81 private static ExportHandler exportHandler;
82
83 private Language language;
84
85 private static ICdmDataSource cdmDatasource;
86
87
88 /**
89 *
90 * @param applicationContextBean
91 * @return
92 */
93 protected static CdmStore getDefault(){
94 if(instance == null){
95
96 // Prompt user for datasource if there are more than one
97 if(PreferencesUtil.getPreferenceStore().getBoolean(PreferencesUtil.SHOW_DATASOURCE_CHOOSER)
98 && CdmDataSourceRepository.getAll().size() > 1){
99 createDatasourceChooser(null);
100 }else{
101 // Start default cdm database
102 instance = initialize(DEFAULT_DB_SCHEMA_VALIDATION, DEFAULT_APPLICATION_CONTEXT);
103 }
104
105 }
106
107 return instance;
108 }
109
110 private static CdmStore initialize(DbSchemaValidation dbSchemaValidation, Resource applicationContextBean){
111
112 logger.info("Initializing application context ...");
113
114 cdmDatasource = CdmDataSourceRepository.getCurrentDataSource();
115
116 try {
117 if (!cdmDatasource.testConnection()) {
118 createDatasourceChooser("The database for the chosen datasource '" + cdmDatasource + "' \n could not be connected to." +
119 "Please choose a new data source to connect to");
120 } else {
121 instance = new CdmStore(cdmDatasource, dbSchemaValidation, applicationContextBean);
122 logger.info("Application context initialized.");
123
124 if (!getCommonService().isDatabaseSchemaCompatible()) {
125 // Show the datasource chooser
126 if(CdmDataSourceRepository.getAll().size() > 1){
127 createDatasourceChooser("The database schema for the chosen " +
128 "datasource '" + cdmDatasource + "' \n is not valid for this version of the taxonomic editor. \n" +
129 "Please choose a new data source to connect to");
130 } else {
131 throw new DatabaseSchemaMismatchException();
132 }
133 }
134 }
135 return instance;
136 } catch (DataSourceNotFoundException e) {
137 StoreUtil.errorDialog("Chosen Datasource is not available", "Could not connect to the chosen " +
138 "datasource '" + cdmDatasource + "'. Please check settings in datasources.xml. If the datasource " +
139 "is located on a remote machine, make sure you are connected to the network.");
140 logger.error(e);
141 } catch (NullPointerException e){
142 StoreUtil.errorDialog("Corrupt Datasource", "The configuration for the chosen " +
143 "datasource '" + cdmDatasource + "' is corrupt. Please check settings in datasources.xml.");
144 logger.error(e);
145 } catch (DatabaseSchemaMismatchException e){
146 StoreUtil.errorDialog("Database Schema incompatible", "The database schema for the chosen " +
147 "datasource '" + cdmDatasource + "' is not valid for this version of the taxonomic editor.");
148 logger.error(e);
149 } catch (Exception e){
150 StoreUtil.errorDialog("Unknown Datasource Error", "An error occurred while connecting to the datasource." +
151 "Please refer to the error log.");
152 logger.error(e);
153 }
154
155 // FIXME present datasource chooser dialog instead of closing the workbench
156 PlatformUI.getWorkbench().close();
157 return null;
158 }
159
160 /**
161 * Creates the datasource chooser.
162 * @param message Message to show. Specify null if none.
163 */
164 private static void createDatasourceChooser(String message) {
165 DatasourceLauncherDialog chooseDataSource = new DatasourceLauncherDialog(StoreUtil.getShell(), message);
166 if(chooseDataSource.open() == Status.OK){
167 instance = initialize(DEFAULT_DB_SCHEMA_VALIDATION, DEFAULT_APPLICATION_CONTEXT);
168 }else{
169 // no datasource chosen.
170 logger.warn("No datasource chosen. Exiting now.");
171 PlatformUI.getWorkbench().close();
172 }
173 }
174
175 /**
176 *
177 */
178 private CdmStore(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, Resource applicationContextBean) {
179 try {
180 applicationController = CdmApplicationController.NewInstance(applicationContextBean, dataSource, dbSchemaValidation, false);
181 } catch (Exception e) {
182 throw new RuntimeException(e);
183 }
184 }
185
186 /**
187 * All calls to the datastore require
188 *
189 * @return
190 */
191 private CdmApplicationController getApplicationController(){
192 try{
193 return applicationController;
194 }catch(Exception e){
195 logger.error("Exception thrown", e);
196 }
197 return null;
198 }
199
200
201 @Deprecated
202 public static CdmApplicationController getApplicationControllerWillBeObsolete(){
203 return getDefault().getApplicationController();
204 }
205
206 /*
207 * CONVERSATIONS
208 */
209
210 /**
211 * Create a new conversation and bind resources to it
212 *
213 * @return
214 */
215 public static ConversationHolder NewConversation(){
216
217 ConversationHolder conversation = getDefault().getApplicationController().NewConversation();
218
219 return conversation;
220 }
221
222 /**
223 * Creates a new conversation, binds resources to the conversation and
224 * start a transaction for this conversation.
225 *
226 * @return
227 */
228 public static ConversationHolder NewTransactionalConversation() {
229 ConversationHolder conversation = NewConversation();
230
231 conversation.startTransaction();
232 return conversation;
233 }
234
235 /*
236 * EXPOSING SERVICES
237 */
238
239 public static ITaxonService getTaxonService(){ return getDefault().getApplicationController().getTaxonService();}
240
241 public static ITaxonTreeService getTaxonTreeService() { return getDefault().getApplicationController().getTaxonTreeService();}
242
243 public static INameService getNameService(){ return getDefault().getApplicationController().getNameService();}
244
245 public static IReferenceService getReferenceService(){ return getDefault().getApplicationController().getReferenceService();}
246
247 public static ILocationService getLocationService(){ return getDefault().getApplicationController().getLocationService();}
248
249 public static ProviderManager getAuthenticationManager() { return getDefault().getApplicationController().getAuthenticationManager();}
250
251 public static IUserService getUserService() { return getDefault().getApplicationController().getUserService(); }
252
253 public static ICommonService getCommonService() { return getDefault().getApplicationController().getCommonService(); }
254
255 public static IAgentService getAgentService() { return getDefault().getApplicationController().getAgentService(); }
256
257 public static ITermService getTermService() { return getDefault().getApplicationController().getTermService(); }
258
259 public static IVocabularyService getVocabularyService() { return getDefault().getApplicationController().getVocabularyService(); }
260
261 public static IEditGeoService getGeoService(){
262 return (IEditGeoService) getDefault().getApplicationController().getBean("editGeoService");
263 }
264
265 /*
266 * METHODS TO FIND ENTITIES
267 */
268
269 /**
270 *
271 * @param configurator
272 * @return
273 */
274 public static List<TaxonNameBase> findNames(IIdentifiableEntityServiceConfigurator configurator){
275 // TODO we want to use IIdentifiableEntityServiceConfigurator for all find methods
276 // unfortunately this is not consistently implemented in the library.
277 // FIXME use proper method once it is implemented in the library
278 String titleSearchString = configurator.getTitleSearchString().replace("*", "%");
279
280 return getNameService().getNamesByName(titleSearchString);
281 }
282
283 /**
284 *
285 * @param configurator
286 * @return
287 */
288 public static List<IdentifiableEntity> findTaxaAndNames(ITaxonServiceConfigurator configurator){
289 return getTaxonService().findTaxaAndNames(configurator).getRecords();
290 }
291
292 /**
293 *
294 * @param configurator
295 * @return
296 */
297 public static List<ReferenceBase> findReferences(IIdentifiableEntityServiceConfigurator configurator){
298 // TODO we want to use IIdentifiableEntityServiceConfigurator for all find methods
299 // unfortunately this is not consistently implemented in the library.
300 // FIXME use proper method once it is implemented in the library
301 String titleSearchString = configurator.getTitleSearchString().replace("*", "%");
302
303 return getReferenceService().findByTitle(null, titleSearchString, null, null, null, null, null, null).getRecords();
304 }
305
306 /**
307 *
308 * @param configurator
309 * @return
310 */
311 public static List<AgentBase> findAgents(IIdentifiableEntityServiceConfigurator configurator){
312 // TODO we want to use IIdentifiableEntityServiceConfigurator for all find methods
313 // unfortunately this is not consistently implemented in the library.
314 // FIXME use proper method once it is implemented in the library
315 String titleSearchString = configurator.getTitleSearchString().replace("*", "%");
316
317 return getAgentService().findByTitle(null, titleSearchString, null, null, null, null, null, null).getRecords();
318 }
319
320 public static List<TeamOrPersonBase> findTeamOrPersons(IIdentifiableEntityServiceConfigurator configurator){
321 // TODO move this to cdmlib
322 List<TeamOrPersonBase> result = new ArrayList<TeamOrPersonBase>();
323 for (AgentBase agent : findAgents(configurator)) {
324 if (agent instanceof TeamOrPersonBase) {
325 result.add((TeamOrPersonBase) agent);
326 }
327 }
328 return result;
329 }
330
331 /*
332 * LANGUAGE
333 */
334
335 /**
336 * @return
337 */
338 public static Language getDefaultLanguage(){
339 if(getDefault().getLanguage() == null){
340 getDefault().setLanguage(Language.DEFAULT());
341 }
342 return getDefault().getLanguage();
343 }
344
345 public static void setDefaultLanguage(Language language){
346 getDefault().setLanguage(language);
347 }
348
349 /**
350 * @return the language
351 */
352 private Language getLanguage() {
353 return language;
354 }
355
356 /**
357 * @param language the language to set
358 */
359 private void setLanguage(Language language) {
360 this.language = language;
361 }
362
363 /*
364 * LOGIN
365 */
366
367 /**
368 *
369 */
370 public static LoginManager getLoginManager(){
371 if(loginManager == null){
372 loginManager = new LoginManager();
373 }
374 return loginManager;
375 }
376
377 /*
378 * IMPORT/EXPORT FACTORIES
379 */
380
381 /**
382 *
383 */
384 public static synchronized ImportHandler getImportHandler(){
385 if(importHandler == null){
386 importHandler = ImportHandler.NewInstance(getDefault().getApplicationController());
387 }
388 return importHandler;
389 }
390
391 /**
392 *
393 * @return
394 */
395 public static synchronized ExportHandler getExportHandler(){
396 if(exportHandler == null){
397 exportHandler = ExportHandler.NewInstance(getDefault().getApplicationController());
398 }
399 return exportHandler;
400 }
401 }