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