Fixes #2388
[taxeditor.git] / eu.etaxonomy.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.lang.reflect.InvocationTargetException;
13 import java.lang.reflect.Method;
14 import java.lang.reflect.Type;
15
16 import org.eclipse.core.runtime.IProgressMonitor;
17 import org.eclipse.core.runtime.jobs.Job;
18 import org.eclipse.swt.widgets.Display;
19 import org.springframework.core.io.ClassPathResource;
20 import org.springframework.core.io.Resource;
21 import org.springframework.security.authentication.ProviderManager;
22
23 import eu.etaxonomy.cdm.api.application.CdmApplicationController;
24 import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
25 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
26 import eu.etaxonomy.cdm.api.service.IService;
27 import eu.etaxonomy.cdm.database.DbSchemaValidation;
28 import eu.etaxonomy.cdm.database.ICdmDataSource;
29 import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
30 import eu.etaxonomy.cdm.model.common.Language;
31 import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
32 import eu.etaxonomy.taxeditor.io.ExportManager;
33 import eu.etaxonomy.taxeditor.io.ImportManager;
34 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
35 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
36 import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
37
38 /**
39 * This implementation of ICdmDataRepository depends on hibernate sessions to
40 * store the data correctly for the current session. No state is held in this
41 * class.
42 *
43 * Only methods that either get or manipulate data are exposed here. So this
44 * class acts as a facade for the methods in cdmlib-service.
45 *
46 * @author n.hoffmann
47 * @created 17.03.2009
48 * @version 1.0
49 */
50 public class CdmStore {
51
52 private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource(
53 "/eu/etaxonomy/cdm/editorApplicationContext.xml",
54 TaxeditorStorePlugin.class);
55 private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
56
57 private static CdmStore instance;
58
59 private final ICdmApplicationConfiguration applicationConfiguration;
60
61 private static LoginManager loginManager = new LoginManager();
62
63 private static ContextManager contextManager = new ContextManager();;
64
65 private static TermManager termManager = new TermManager();
66
67 private static SearchManager searchManager = new SearchManager();
68
69 private static EditorManager editorManager = new EditorManager();
70
71 private static CdmStoreConnector job;
72
73 private Language language;
74
75 private ICdmDataSource cdmDatasource;
76
77 private boolean isConnected;
78
79 /**
80 * <p>
81 * getDefault
82 * </p>
83 *
84 * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
85 */
86 protected static CdmStore getDefault() {
87 if (instance != null && instance.isConnected) {
88 return instance;
89 } else if (instance == null || !instance.isConnected) {
90
91 StoreUtil
92 .warningDialog(
93 "Application is not connected to a datastore",
94 instance,
95 "The requested operation is only available when "
96 + "connected to a datasource. You may choose a datasource to connect to or create a new one in the datasource view.");
97
98 StoreUtil.showView(CdmDataSourceViewPart.ID);
99
100 }
101
102 throw new RuntimeException();
103 }
104
105 /**
106 * Initialize the with the last edited datasource
107 */
108 public static void connect() {
109
110 ICdmDataSource datasource = CdmDataSourceRepository
111 .getCurrentDataSource();
112
113 connect(datasource);
114 }
115
116 /**
117 * Initialize with a specific datasource
118 *
119 * @param datasource
120 * a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
121 */
122 public static void connect(ICdmDataSource datasource) {
123 connect(datasource, DEFAULT_DB_SCHEMA_VALIDATION,
124 DEFAULT_APPLICATION_CONTEXT);
125 }
126
127 /**
128 * Initialize and provide
129 *
130 * @param datasource
131 * @param dbSchemaValidation
132 * @param applicationContextBean
133 */
134 private static void connect(final ICdmDataSource datasource,
135 final DbSchemaValidation dbSchemaValidation,
136 final Resource applicationContextBean) {
137 StoreUtil.info("Connecting to datasource: " + datasource);
138
139 job = new CdmStoreConnector(Display.getDefault(), datasource,
140 dbSchemaValidation, applicationContextBean);
141 job.setUser(true);
142 job.setPriority(Job.BUILD);
143 job.schedule();
144
145 }
146
147 public static boolean isConnecting() {
148 return job != null && job.getState() == Job.RUNNING;
149 }
150
151 /**
152 * Closes the current application context
153 *
154 * @param monitor
155 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
156 */
157 public static void close(final IProgressMonitor monitor) {
158 Display.getDefault().asyncExec(new Runnable() {
159 /*
160 * (non-Javadoc)
161 *
162 * @see java.lang.Runnable#run()
163 */
164 @Override
165 public void run() {
166 getContextManager().notifyContextAboutToStop(monitor);
167 if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
168 getContextManager().notifyContextStop(monitor);
169 instance.close();
170 }
171 }
172 });
173 }
174
175 private void close() {
176 isConnected = false;
177 cdmDatasource = null;
178 }
179
180 static void setInstance(CdmApplicationController applicationController,
181 ICdmDataSource dataSource) {
182 instance = new CdmStore(applicationController, dataSource);
183 }
184
185 private CdmStore(CdmApplicationController applicationController,
186 ICdmDataSource dataSource) {
187 this.applicationConfiguration = applicationController;
188 this.cdmDatasource = dataSource;
189 isConnected = true;
190 }
191
192 /**
193 * All calls to the datastore require
194 *
195 * @return
196 */
197 private ICdmApplicationConfiguration getApplicationConfiguration() {
198 try {
199 return applicationConfiguration;
200 } catch (Exception e) {
201 StoreUtil.error(CdmStore.class, e);
202 }
203 return null;
204 }
205
206 /**
207 * <p>
208 * getCurrentApplicationController
209 * </p>
210 *
211 * @return a
212 * {@link eu.etaxonomy.cdm.api.application.CdmApplicationController}
213 * object.
214 */
215 public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
216 if (getDefault() != null) {
217 return getDefault().getApplicationConfiguration();
218 }
219 return null;
220 }
221
222 /*
223 * CONVERSATIONS
224 */
225
226 /**
227 * Creates a new conversation, binds resources to the conversation and start
228 * a transaction for this conversation.
229 *
230 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
231 * object.
232 */
233 public static ConversationHolder createConversation() {
234 ConversationHolder conversation = getCurrentApplicationConfiguration()
235 .NewConversation();
236
237 conversation.startTransaction();
238 return conversation;
239 }
240
241 /**
242 * Generic method that will return an implementation of the given service
243 * interface or <code>null</code> if the
244 *
245 * @param <T>
246 * @param serviceClass
247 * @return
248 */
249 public static <T extends IService> T getService(Class<T> serviceClass) {
250 ICdmApplicationConfiguration configuration = getCurrentApplicationConfiguration();
251
252 Method[] methods = ICdmApplicationConfiguration.class
253 .getDeclaredMethods();
254
255 T service = null;
256
257 for (Method method : methods) {
258 Type type = method.getGenericReturnType();
259
260 if (type.equals(serviceClass)) {
261 try {
262 service = (T) method.invoke(configuration, null);
263 break;
264 } catch (IllegalArgumentException e) {
265 StoreUtil.error(CdmStore.class, e);
266 } catch (IllegalAccessException e) {
267 StoreUtil.error(CdmStore.class, e);
268 } catch (InvocationTargetException e) {
269 StoreUtil.error(CdmStore.class, e);
270 }
271 }
272 }
273
274 return service;
275 }
276
277 /**
278 * <p>
279 * getAuthenticationManager
280 * </p>
281 *
282 * @return a
283 * {@link org.springframework.security.authentication.ProviderManager}
284 * object.
285 */
286 public static ProviderManager getAuthenticationManager() {
287 return getCurrentApplicationConfiguration().getAuthenticationManager();
288 }
289
290 /**
291 * <p>
292 * getGeoService
293 * </p>
294 *
295 * @return a {@link eu.etaxonomy.cdm.ext.geo.IEditGeoService} object.
296 */
297 public static IEditGeoService getGeoService() {
298 return (IEditGeoService) getCurrentApplicationConfiguration().getBean(
299 "editGeoService");
300 }
301
302 /*
303 * LANGUAGE
304 */
305
306 /**
307 * <p>
308 * getDefaultLanguage
309 * </p>
310 *
311 * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
312 */
313 public static Language getDefaultLanguage() {
314 if (getDefault().getLanguage() == null) {
315 getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
316 }
317 return getDefault().getLanguage();
318 }
319
320 /**
321 * <p>
322 * setDefaultLanguage
323 * </p>
324 *
325 * @param language
326 * a {@link eu.etaxonomy.cdm.model.common.Language} object.
327 */
328 public static void setDefaultLanguage(Language language) {
329 getDefault().setLanguage(language);
330 }
331
332 /**
333 * @return the language
334 */
335 private Language getLanguage() {
336 return language;
337 }
338
339 /**
340 * @param language
341 * the language to set
342 */
343 private void setLanguage(Language language) {
344 this.language = language;
345 }
346
347 /*
348 * LOGIN
349 */
350
351 /**
352 * <p>
353 * Getter for the field <code>loginManager</code>.
354 * </p>
355 *
356 * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
357 */
358 public static LoginManager getLoginManager() {
359 return loginManager;
360 }
361
362 /**
363 * <p>
364 * Getter for the field <code>contextManager</code>.
365 * </p>
366 *
367 * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
368 */
369 public static ContextManager getContextManager() {
370 return contextManager;
371 }
372
373 public static TermManager getTermManager() {
374 return termManager;
375 }
376
377 public static SearchManager getSearchManager() {
378 return searchManager;
379 }
380
381 public static EditorManager getEditorManager() {
382 return editorManager;
383 }
384
385 /*
386 * IMPORT/EXPORT FACTORIES
387 */
388
389 /**
390 * <p>
391 * Getter for the field <code>importHandler</code>.
392 * </p>
393 *
394 * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
395 */
396 public static ImportManager getImportManager() {
397 return ImportManager.NewInstance(getCurrentApplicationConfiguration());
398 }
399
400 /**
401 * <p>
402 * Getter for the field <code>exportHandler</code>.
403 * </p>
404 *
405 * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
406 */
407 public static ExportManager getExportManager() {
408 return ExportManager.NewInstance(getCurrentApplicationConfiguration());
409 }
410
411 /**
412 * Whether this CdmStore is currently connected to a datasource
413 *
414 * @return a boolean.
415 */
416 public static boolean isActive() {
417 return instance != null && instance.isConnected;
418 }
419
420 /**
421 * <p>
422 * getDataSource
423 * </p>
424 *
425 * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
426 */
427 public static ICdmDataSource getDataSource() {
428 if (isActive()) {
429 return instance.getDatasource();
430 }
431 return null;
432 }
433
434 /**
435 * @return
436 */
437 private ICdmDataSource getDatasource() {
438 return cdmDatasource;
439 }
440
441 }