2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.store
;
12 import java
.lang
.reflect
.InvocationTargetException
;
13 import java
.util
.ArrayList
;
14 import java
.util
.List
;
16 import org
.apache
.log4j
.Logger
;
17 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
18 import org
.eclipse
.core
.runtime
.ListenerList
;
19 import org
.eclipse
.jface
.dialogs
.ProgressMonitorDialog
;
20 import org
.eclipse
.jface
.operation
.IRunnableWithProgress
;
21 import org
.springframework
.core
.io
.ClassPathResource
;
22 import org
.springframework
.core
.io
.Resource
;
23 import org
.springframework
.security
.authentication
.ProviderManager
;
25 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationController
;
26 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
27 import eu
.etaxonomy
.cdm
.api
.service
.IAgentService
;
28 import eu
.etaxonomy
.cdm
.api
.service
.ICommonService
;
29 import eu
.etaxonomy
.cdm
.api
.service
.ILocationService
;
30 import eu
.etaxonomy
.cdm
.api
.service
.IMediaService
;
31 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
32 import eu
.etaxonomy
.cdm
.api
.service
.IReferenceService
;
33 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonNodeService
;
34 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
35 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonTreeService
;
36 import eu
.etaxonomy
.cdm
.api
.service
.ITermService
;
37 import eu
.etaxonomy
.cdm
.api
.service
.IUserService
;
38 import eu
.etaxonomy
.cdm
.api
.service
.IVocabularyService
;
39 import eu
.etaxonomy
.cdm
.api
.service
.config
.IIdentifiableEntityServiceConfigurator
;
40 import eu
.etaxonomy
.cdm
.api
.service
.config
.ITaxonServiceConfigurator
;
41 import eu
.etaxonomy
.cdm
.database
.DataSourceNotFoundException
;
42 import eu
.etaxonomy
.cdm
.database
.DatabaseSchemaMismatchException
;
43 import eu
.etaxonomy
.cdm
.database
.DatabaseTypeEnum
;
44 import eu
.etaxonomy
.cdm
.database
.DbSchemaValidation
;
45 import eu
.etaxonomy
.cdm
.database
.ICdmDataSource
;
46 import eu
.etaxonomy
.cdm
.ext
.IEditGeoService
;
47 import eu
.etaxonomy
.cdm
.model
.agent
.AgentBase
;
48 import eu
.etaxonomy
.cdm
.model
.agent
.TeamOrPersonBase
;
49 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
50 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
51 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
52 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
53 import eu
.etaxonomy
.taxeditor
.datasource
.CdmDataSourceRepository
;
54 import eu
.etaxonomy
.taxeditor
.datasource
.view
.CdmDataSourceView
;
55 import eu
.etaxonomy
.taxeditor
.dialogs
.LoginDialog
;
56 import eu
.etaxonomy
.taxeditor
.io
.ExportHandler
;
57 import eu
.etaxonomy
.taxeditor
.io
.ImportHandler
;
58 import eu
.etaxonomy
.taxeditor
.model
.IContextListener
;
59 import eu
.etaxonomy
.taxeditor
.model
.IContextListener
.EventType
;
60 import eu
.etaxonomy
.taxeditor
.store
.internal
.TaxeditorStorePlugin
;
63 * This implementation of ICdmDataRepository depends on hibernate sessions to store the data correctly
64 * for the current session. No state is held in this class.
66 * Only methods that either get or manipulate data are exposed here. So this class acts as a facade
67 * for the methods in cdmlib-service.
74 public class CdmStore
{
75 private static final Logger logger
= Logger
.getLogger(CdmStore
.class);
77 // FIXME change this to ClassPathResources as soon as it is included into the plugin
78 private static final Resource DEFAULT_APPLICATION_CONTEXT
= new ClassPathResource("/eu/etaxonomy/cdm/editorApplicationContext.xml", TaxeditorStorePlugin
.class.getClassLoader());
79 private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION
= DbSchemaValidation
.UPDATE
;
81 private static CdmStore instance
;
83 private CdmApplicationController applicationController
;
85 private static LoginManager loginManager
;
87 private static ImportHandler importHandler
;
89 private static ExportHandler exportHandler
;
91 private Language language
;
93 private static ListenerList contextListeners
= new ListenerList();
95 private static ICdmDataSource cdmDatasource
;
97 private boolean isConnected
;
102 * @param applicationContextBean
105 protected static CdmStore
getDefault(){
106 if(instance
!= null && instance
.isConnected
){
108 }else if(instance
== null){
113 }else if(!instance
.isConnected
){
115 StoreUtil
.warningDialog("No datasource connection", "Application is not connected to a datastore.");
117 // TODO open datasource view
124 * Initialize the with the last edited datasource
126 public static void initialize() {
128 ICdmDataSource datasource
= CdmDataSourceRepository
.getCurrentDataSource();
130 initialize(datasource
);
134 * Initialize with a specific datasource
138 public static void initialize(ICdmDataSource datasource
) {
139 initialize(datasource
, DEFAULT_DB_SCHEMA_VALIDATION
, DEFAULT_APPLICATION_CONTEXT
);
143 * Initialize and provide
146 * @param dbSchemaValidation
147 * @param applicationContextBean
149 private static void initialize(final ICdmDataSource datasource
, final DbSchemaValidation dbSchemaValidation
, final Resource applicationContextBean
){
152 logger
.error("Application context already initialized.");
156 logger
.info("Initializing application context ...");
159 if (datasource
.testConnection()) {
160 cdmDatasource
= datasource
;
162 ProgressMonitorDialog progressMonitorDialog
= new ProgressMonitorDialog(StoreUtil
.getShell());
163 IRunnableWithProgress runnable
= new IRunnableWithProgress() {
165 public void run(IProgressMonitor monitor
) throws InvocationTargetException
,
166 InterruptedException
{
168 if(cdmDatasource
.getDatabaseType().equals(DatabaseTypeEnum
.H2
)){
169 message
= " local CDM Store ";
171 message
= " CDM Community Store ";
173 message
+= "'" + cdmDatasource
.getName() + "'";
175 monitor
.beginTask("Establishing connection to" + message
, 10);
176 // TODO get real feedback from CDMStore initialisation process
179 instance
= new CdmStore(datasource
, dbSchemaValidation
, applicationContextBean
);
185 progressMonitorDialog
.run(false, false, runnable
);
187 if (!getCommonService().isDatabaseSchemaCompatible()) {
189 // Show the datasource chooser
190 if(CdmDataSourceRepository
.getAll().size() > 1){
191 // Show an error message
192 StoreUtil
.errorDialog("DatabaseCompatibilityCheck failed", "The database schema for the chosen " +
193 "datasource '" + datasource
+ "' \n is not valid for this version of the taxonomic editor. \n" +
194 "Please choose a new data source to connect to in the Datasource View.");
196 // Show datasource view if not shown yet
197 StoreUtil
.showView(CdmDataSourceView
.ID
);
199 throw new DatabaseSchemaMismatchException();
202 notifyContextStart();
204 logger
.info("Application context initialized.");
207 } catch (DataSourceNotFoundException e
) {
208 StoreUtil
.errorDialog("Chosen Datasource is not available", "Could not connect to the chosen " +
209 "datasource '" + datasource
+ "'. Please check settings in datasources.xml. If the datasource " +
210 "is located on a remote machine, make sure you are connected to the network.");
212 } catch (NullPointerException e
){
213 StoreUtil
.errorDialog("Corrupt Datasource", "The configuration for the chosen " +
214 "datasource '" + datasource
+ "' is corrupt. Please check settings in datasources.xml.");
216 } catch (DatabaseSchemaMismatchException e
){
217 StoreUtil
.errorDialog("Database Schema incompatible", "The database schema for the chosen " +
218 "datasource '" + datasource
+ "' is not valid for this version of the taxonomic editor.");
220 } catch (Exception e
){
221 StoreUtil
.errorDialog("Unknown Datasource Error", "An error occurred while connecting to the datasource." +
222 "Please refer to the error log.");
228 * Closes the current application context
230 public static void close(){
231 notifyContextAboutToStop();
232 if(isActive() && StoreUtil
.closeAll()){
234 instance
.getApplicationController().close();
235 instance
.isConnected
= false;
236 cdmDatasource
= null;
244 private CdmStore(ICdmDataSource dataSource
, DbSchemaValidation dbSchemaValidation
, Resource applicationContextBean
) {
246 // this should be more modulized
247 applicationController
= CdmApplicationController
.NewInstance(applicationContextBean
, dataSource
, dbSchemaValidation
, false);
251 cdmDatasource
= dataSource
;
252 } catch (Exception e
) {
253 throw new RuntimeException(e
);
258 * All calls to the datastore require
262 private CdmApplicationController
getApplicationController(){
264 return applicationController
;
266 logger
.error("Exception thrown", e
);
276 * Creates a new conversation, binds resources to the conversation and
277 * start a transaction for this conversation.
281 public static ConversationHolder
createConversation() {
282 ConversationHolder conversation
= getDefault().getApplicationController().NewConversation();
284 conversation
.startTransaction();
292 public static ITaxonService
getTaxonService(){ return getDefault().getApplicationController().getTaxonService();}
294 public static ITaxonTreeService
getTaxonTreeService() { return getDefault().getApplicationController().getTaxonTreeService();}
296 public static ITaxonNodeService
getTaxonNodeService() { return getDefault().getApplicationController().getTaxonNodeService();}
298 public static INameService
getNameService(){ return getDefault().getApplicationController().getNameService();}
300 public static IReferenceService
getReferenceService(){ return getDefault().getApplicationController().getReferenceService();}
302 public static ILocationService
getLocationService(){ return getDefault().getApplicationController().getLocationService();}
304 public static ProviderManager
getAuthenticationManager() { return getDefault().getApplicationController().getAuthenticationManager();}
306 public static IUserService
getUserService() { return getDefault().getApplicationController().getUserService(); }
308 public static ICommonService
getCommonService() { return getDefault().getApplicationController().getCommonService(); }
310 public static IAgentService
getAgentService() { return getDefault().getApplicationController().getAgentService(); }
312 public static ITermService
getTermService() { return getDefault().getApplicationController().getTermService(); }
314 public static IVocabularyService
getVocabularyService() { return getDefault().getApplicationController().getVocabularyService(); }
316 public static IMediaService
getMediaService() { return getDefault().getApplicationController().getMediaService(); }
318 public static IEditGeoService
getGeoService(){
319 return (IEditGeoService
) getDefault().getApplicationController().getBean("editGeoService");
323 * METHODS TO FIND ENTITIES
328 * @param configurator
331 public static List
<TaxonNameBase
> findNames(IIdentifiableEntityServiceConfigurator configurator
){
332 // TODO we want to use IIdentifiableEntityServiceConfigurator for all find methods
333 // unfortunately this is not consistently implemented in the library.
334 // FIXME use proper method once it is implemented in the library
335 String titleSearchString
= configurator
.getTitleSearchString().replace("*", "%");
337 return getNameService().getNamesByName(titleSearchString
);
342 * @param configurator
345 public static List
<IdentifiableEntity
> findTaxaAndNames(ITaxonServiceConfigurator configurator
){
346 return getTaxonService().findTaxaAndNames(configurator
).getRecords();
351 * @param configurator
354 public static List
<ReferenceBase
> findReferences(IIdentifiableEntityServiceConfigurator configurator
){
355 // TODO we want to use IIdentifiableEntityServiceConfigurator for all find methods
356 // unfortunately this is not consistently implemented in the library.
357 // FIXME use proper method once it is implemented in the library
358 String titleSearchString
= configurator
.getTitleSearchString().replace("*", "%");
360 return getReferenceService().findByTitle(null, titleSearchString
, null, null, null, null, null, null).getRecords();
365 * @param configurator
368 public static List
<AgentBase
> findAgents(IIdentifiableEntityServiceConfigurator configurator
){
369 // TODO we want to use IIdentifiableEntityServiceConfigurator for all find methods
370 // unfortunately this is not consistently implemented in the library.
371 // FIXME use proper method once it is implemented in the library
372 String titleSearchString
= configurator
.getTitleSearchString().replace("*", "%");
374 return getAgentService().findByTitle(null, titleSearchString
, null, null, null, null, null, null).getRecords();
377 public static List
<TeamOrPersonBase
> findTeamOrPersons(IIdentifiableEntityServiceConfigurator configurator
){
378 // TODO move this to cdmlib
379 List
<TeamOrPersonBase
> result
= new ArrayList
<TeamOrPersonBase
>();
380 for (AgentBase agent
: findAgents(configurator
)) {
381 if (agent
instanceof TeamOrPersonBase
) {
382 result
.add((TeamOrPersonBase
) agent
);
395 public static Language
getDefaultLanguage(){
396 if(getDefault().getLanguage() == null){
397 getDefault().setLanguage(Language
.DEFAULT());
399 return getDefault().getLanguage();
402 public static void setDefaultLanguage(Language language
){
403 getDefault().setLanguage(language
);
407 * @return the language
409 private Language
getLanguage() {
414 * @param language the language to set
416 private void setLanguage(Language language
) {
417 this.language
= language
;
427 public static LoginManager
getLoginManager(){
428 if(loginManager
== null){
429 loginManager
= new LoginManager();
434 private int authenticate(){
436 LoginDialog loginDialog
= new LoginDialog(StoreUtil
.getShell());
437 return loginDialog
.open();
441 * IMPORT/EXPORT FACTORIES
447 public static synchronized ImportHandler
getImportHandler(){
448 if(importHandler
== null){
449 importHandler
= ImportHandler
.NewInstance(getDefault().getApplicationController());
451 return importHandler
;
458 public static synchronized ExportHandler
getExportHandler(){
459 if(exportHandler
== null){
460 exportHandler
= ExportHandler
.NewInstance(getDefault().getApplicationController());
462 return exportHandler
;
466 * Whether this CdmStore is currently connected to a datasource
469 public static boolean isActive(){
470 return instance
!= null && instance
.isConnected
;
473 public static void addContextListener(IContextListener listener
){
474 contextListeners
.add(listener
);
477 public static void removeContextListener(IContextListener listener
) {
478 contextListeners
.remove(listener
);
481 public static void notifyContextStart() {
482 logger
.warn("Application event occured");
484 instance
.authenticate();
487 for(Object listener
: contextListeners
.getListeners()){
488 ((IContextListener
) listener
).onContextEvent(EventType
.START
);
492 public static void notifyContextAboutToStop(){
493 for(Object listener
: contextListeners
.getListeners()){
494 ((IContextListener
) listener
).onContextEvent(EventType
.ABOUT_TO_STOP
);
498 public static void notifyContextStop() {
499 logger
.warn("Application event occured");
501 for(Object listener
: contextListeners
.getListeners()){
502 ((IContextListener
) listener
).onContextEvent(EventType
.STOP
);
506 public static ICdmDataSource
getDataSource(){
508 return cdmDatasource
;