/**
* Copyright (C) 2007 EDIT
* European Distributed Institute of Taxonomy
* http://www.e-taxonomy.eu
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* See LICENSE.TXT at the top of this package for the full license terms.
*/
package eu.etaxonomy.taxeditor.store;
import java.util.EnumSet;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.swt.widgets.Display;
import org.slf4j.Marker;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import eu.etaxonomy.cdm.api.application.CdmApplicationException;
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
import eu.etaxonomy.cdm.api.application.ICdmRepository;
import eu.etaxonomy.cdm.api.cache.CdmServiceCachingProxy;
import eu.etaxonomy.cdm.api.service.IAgentService;
import eu.etaxonomy.cdm.api.service.IAnnotationService;
import eu.etaxonomy.cdm.api.service.IClassificationService;
import eu.etaxonomy.cdm.api.service.ICollectionService;
import eu.etaxonomy.cdm.api.service.ICommonService;
import eu.etaxonomy.cdm.api.service.IDescriptionService;
import eu.etaxonomy.cdm.api.service.IDescriptiveDataSetService;
import eu.etaxonomy.cdm.api.service.IEntityConstraintViolationService;
import eu.etaxonomy.cdm.api.service.IEntityValidationService;
import eu.etaxonomy.cdm.api.service.IGrantedAuthorityService;
import eu.etaxonomy.cdm.api.service.IGroupService;
import eu.etaxonomy.cdm.api.service.IMarkerService;
import eu.etaxonomy.cdm.api.service.IMediaService;
import eu.etaxonomy.cdm.api.service.INameService;
import eu.etaxonomy.cdm.api.service.IOccurrenceService;
import eu.etaxonomy.cdm.api.service.IPolytomousKeyNodeService;
import eu.etaxonomy.cdm.api.service.IPolytomousKeyService;
import eu.etaxonomy.cdm.api.service.IReferenceService;
import eu.etaxonomy.cdm.api.service.IRegistrationService;
import eu.etaxonomy.cdm.api.service.IRightsService;
import eu.etaxonomy.cdm.api.service.IService;
import eu.etaxonomy.cdm.api.service.ITaxonService;
import eu.etaxonomy.cdm.api.service.ITermNodeService;
import eu.etaxonomy.cdm.api.service.ITermService;
import eu.etaxonomy.cdm.api.service.ITermTreeService;
import eu.etaxonomy.cdm.api.service.IUserService;
import eu.etaxonomy.cdm.api.service.IVocabularyService;
import eu.etaxonomy.cdm.api.service.molecular.IAmplificationService;
import eu.etaxonomy.cdm.api.service.molecular.IPrimerService;
import eu.etaxonomy.cdm.cache.CdmRemoteCacheManager;
import eu.etaxonomy.cdm.config.ICdmSource;
import eu.etaxonomy.cdm.database.DbSchemaValidation;
import eu.etaxonomy.cdm.model.agent.AgentBase;
import eu.etaxonomy.cdm.model.common.Annotation;
import eu.etaxonomy.cdm.model.common.CdmBase;
import eu.etaxonomy.cdm.model.common.Language;
import eu.etaxonomy.cdm.model.description.DescriptionBase;
import eu.etaxonomy.cdm.model.description.DescriptiveDataSet;
import eu.etaxonomy.cdm.model.description.PolytomousKey;
import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;
import eu.etaxonomy.cdm.model.media.Media;
import eu.etaxonomy.cdm.model.media.Rights;
import eu.etaxonomy.cdm.model.molecular.Amplification;
import eu.etaxonomy.cdm.model.molecular.Primer;
import eu.etaxonomy.cdm.model.name.Registration;
import eu.etaxonomy.cdm.model.name.TaxonName;
import eu.etaxonomy.cdm.model.occurrence.Collection;
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
import eu.etaxonomy.cdm.model.permission.CRUD;
import eu.etaxonomy.cdm.model.permission.Group;
import eu.etaxonomy.cdm.model.reference.Reference;
import eu.etaxonomy.cdm.model.taxon.Classification;
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
import eu.etaxonomy.cdm.model.term.TermNode;
import eu.etaxonomy.cdm.model.term.TermTree;
import eu.etaxonomy.cdm.model.term.TermVocabulary;
import eu.etaxonomy.cdm.model.validation.EntityConstraintViolation;
import eu.etaxonomy.cdm.model.validation.EntityValidation;
import eu.etaxonomy.cdm.persistence.permission.ICdmPermissionEvaluator;
import eu.etaxonomy.cdm.persistence.permission.Role;
import eu.etaxonomy.taxeditor.io.ExportManager;
import eu.etaxonomy.taxeditor.io.ImportManager;
import eu.etaxonomy.taxeditor.model.MessagingUtils;
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
import eu.etaxonomy.taxeditor.util.ProgressMonitorClientManager;
/**
* This implementation of ICdmDataRepository depends on hibernate sessions to
* store the data correctly for the current session. No state is held in this
* class.
*
* Only methods that either get or manipulate data are exposed here. So this
* class acts as a facade for the methods in cdmlib-service.
*
* NOTE by AM: TODO this description is outdated since we use remoting now.
*
* @author n.hoffmann
* @created 17.03.2009
*/
public class CdmStore {
public static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource(
"/eu/etaxonomy/cdm/editorApplicationContext.xml",
TaxeditorStorePlugin.class);
public static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
protected static CdmStore instance;
private static ContextManager contextManager = new ContextManager();
private static LoginManager loginManager = new LoginManager();
private static TermManager termManager = new TermManager();
private static SearchManager searchManager = new SearchManager();
private static UseObjectStore useObjectInitializer = new UseObjectStore();
private static ProgressMonitorClientManager progressMonitorClientManager = new ProgressMonitorClientManager();
private static CdmStoreConnector job;
private Language language;
private ICdmSource cdmSource;
private boolean isConnected;
protected static CdmStore getDefault(boolean connecting){
if (instance != null && instance.isConnected()) {
return instance;
} else{// if (instance == null || !instance.isConnected) {
if (connecting){
MessagingUtils.dataSourceNotAvailableWarningDialog(instance);
}else{
MessagingUtils.noDataSourceWarningDialog(instance);
}
return null;
}
}
protected static CdmStore getDefault(){
return getDefault(false);
}
/**
* Initialize the with the last edited datasource
* @deprecated this method is not needed anymore after fully changing to remoting.
* Therefore it will be removed
*/
// @Deprecated
// public static void connect() {
// try {
// ICdmSource cdmSource = CdmDataSourceRepository.getCurrentCdmSource();
// connect(cdmSource);
// } catch (Exception e) {
// MessagingUtils.messageDialog("Connection to CDM Source Failed", CdmStore.class, "Could not connect to target CDM Source", e);
// }
// }
/**
* Initialize with a specific datasource
*
* @param datasource
* a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
*/
public static void connect(ICdmSource cdmSource) {
connect(cdmSource, DEFAULT_DB_SCHEMA_VALIDATION,
DEFAULT_APPLICATION_CONTEXT);
}
public static void connect(ICdmSource cdmSource, RemotingLoginDialog loginDialog) {
connect(cdmSource,
DEFAULT_DB_SCHEMA_VALIDATION,
DEFAULT_APPLICATION_CONTEXT,
loginDialog);
}
/**
* Initialize and provide
*
* @param datasource
* @param dbSchemaValidation
* @param applicationContextBean
*/
private static void connect(final ICdmSource cdmSource,
final DbSchemaValidation dbSchemaValidation,
final Resource applicationContextBean) {
MessagingUtils.info("Connecting to datasource: " + cdmSource);
job = new CdmStoreConnector(Display.getDefault(), cdmSource,
dbSchemaValidation, applicationContextBean);
job.setUser(true);
job.setPriority(Job.BUILD);
job.schedule();
}
private static void connect(final ICdmSource cdmSource,
final DbSchemaValidation dbSchemaValidation,
final Resource applicationContextBean,
RemotingLoginDialog remotingLoginDialog) {
RemotingLoginDialog loginDialog = remotingLoginDialog;
if(isActive()) {
// before we connect we clear the entity caches and the sessions
CdmRemoteCacheManager.removeEntityCaches();
if(getCurrentSessionManager(true) != null) {
getCurrentSessionManager(true).disposeAll();
}
}
MessagingUtils.info("Connecting to datasource: " + cdmSource);
job = new CdmStoreConnector(Display.getDefault(),
cdmSource,
dbSchemaValidation,
applicationContextBean);
job.start(loginDialog);
}
public static boolean isConnecting() {
return job != null && job.getState() == Job.RUNNING;
}
/**
* Closes the current application context
*
* @param monitor
* a {@link org.eclipse.core.runtime.IProgressMonitor} object.
*/
public static void close(final IProgressMonitor monitor) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
getContextManager().notifyContextAboutToStop(monitor);
if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
getContextManager().notifyContextStop(monitor);
instance.close();
}
}
});
}
public static void close(IProgressMonitor monitor, boolean async) {
if(async) {
close(monitor);
} else {
getContextManager().notifyContextAboutToStop(monitor);
if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
getContextManager().notifyContextStop(monitor);
instance.close();
}
}
}
private void close() {
this.setConnected(false);
this.cdmSource = null;
CdmApplicationState.dispose();
}
public static void setInstance(CdmApplicationRemoteController applicationController,
ICdmSource cdmSource) {
instance = new CdmStore(applicationController, cdmSource);
CdmApplicationState.setTermProxy(new CdmServiceCachingProxy());
}
protected CdmStore(CdmApplicationRemoteController repository,
ICdmSource cdmSource) {
CdmApplicationState.setCurrentAppConfig(repository);
CdmApplicationState.setCurrentDataChangeService(new CdmUIDataChangeService());
this.cdmSource = cdmSource;
setConnected(true);
}
/**
* All calls to the datastore require
*/
private CdmApplicationRemoteController getApplicationConfiguration() {
try {
return CdmApplicationState.getCurrentAppConfig();
} catch (Exception e) {
MessagingUtils.error(CdmStore.class, e);
}
return null;
}
public static CdmApplicationRemoteController getCurrentApplicationConfiguration() {
CdmStore defaultStore = getDefault();
if (defaultStore != null) {
return defaultStore.getApplicationConfiguration();
}
return null;
}
private ICdmEntitySessionManager getSessionManager() {
return getCurrentApplicationConfiguration().getCdmEntitySessionManager();
}
public static ICdmEntitySessionManager getCurrentSessionManager() {
return getCurrentSessionManager(false);
}
public static ICdmEntitySessionManager getCurrentSessionManager(boolean connecting) {
CdmStore cdmStore = getDefault(connecting);
if (cdmStore != null) {
return cdmStore.getSessionManager();
}
return null;
}
/**
* Generic method that will scan the getters of {@link ICdmRepository} for the given service
* interface. If a matching getter is found the according service implementation is returned by
* invoking the getter otherwise the method returns null
.
*
* @param
* @param serviceClass
* @return the configured implementation of serviceClass
or null
*/
public static T getService(Class serviceClass) {
T service = null;
try {
service = CdmApplicationState.getService(serviceClass);
} catch (CdmApplicationException cae) {
MessagingUtils.error(CdmStore.class, cae);
}
return service;
}
/**
* @see #getService(Class)
* As ICommonService is not extending IService we need a specific request here
*/
public static ICommonService getCommonService() {
return CdmApplicationState.getCommonService();
}
public static AuthenticationManager getAuthenticationManager() {
return getCurrentApplicationConfiguration().getAuthenticationManager();
}
public static ICdmPermissionEvaluator getPermissionEvaluator() {
return getCurrentApplicationConfiguration().getPermissionEvaluator();
}
/*
* SECURITY RELATED CONVENIENCE METHODS
*/
/**
* @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
*
* @param targetDomainObject
* @param permission
* @return
*/
public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet permission){
//TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
SecurityContext context = SecurityContextHolder.getContext();
boolean hasPermission = false;
try {
hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
permission);
} catch (org.springframework.security.access.AccessDeniedException e) {
/* IGNORE */
}
return hasPermission;
}
/**
* @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
*
* @param targetDomainObject
* @param permission
* @return
*/
public static boolean currentAuthentiationHasPermission(Class extends CdmBase> targetType, EnumSet permission){
boolean hasPermission = false;
try {
hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
} catch (org.springframework.security.access.AccessDeniedException e) {
/* IGNORE */
}
return hasPermission;
}
public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
boolean hasPermission = false;
try {
hasPermission = getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
} catch (org.springframework.security.access.AccessDeniedException e) {
/* IGNORE */
}
return hasPermission;
}
public static Authentication getCurrentAuthentiation() {
SecurityContext context = SecurityContextHolder.getContext();
return context.getAuthentication();
}
/*
* LANGUAGE
*/
/**
* Provides access to the global default language set in the application preferences.
*
* @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
*/
public static Language getDefaultLanguage() {
if (getDefault().getLanguage() == null) {
getDefault().setLanguage(PreferencesUtil.getPreferredDefaultLanguage());
}
return getDefault().getLanguage();
}
public static void setDefaultLanguage(Language language) {
getDefault().setLanguage(language);
}
private Language getLanguage() {
return language;
}
private void setLanguage(Language language) {
this.language = language;
}
/*
* LOGIN
*/
public static LoginManager getLoginManager() {
return loginManager;
}
public static ContextManager getContextManager() {
return contextManager;
}
public static TermManager getTermManager() {
return termManager;
}
public static SearchManager getSearchManager() {
return searchManager;
}
public static ProgressMonitorClientManager getProgressMonitorClientManager() {
return progressMonitorClientManager;
}
/*
* IMPORT/EXPORT FACTORIES
*/
public static ImportManager getImportManager() {
return ImportManager.NewInstance(getCurrentApplicationConfiguration());
}
public static ExportManager getExportManager() {
return ExportManager.NewInstance(getCurrentApplicationConfiguration());
}
/**
* Whether this CdmStore is currently connected to a datasource
*
* @return a boolean.
*/
public static boolean isActive() {
return instance != null && instance.isConnected();
}
public static ICdmSource getActiveCdmSource() {
if (isActive()) {
return instance.getCdmSource();
}
return null;
}
private ICdmSource getCdmSource() {
return cdmSource;
}
@SuppressWarnings("unchecked")
public static IService getService(T cdmBase){
IService service = null;
if(cdmBase!=null){
//get corresponding service
if(cdmBase.isInstanceOf(Reference.class)){
service = (IService) getService(IReferenceService.class);
}
else if (cdmBase.isInstanceOf(AgentBase.class)){
service = (IService) getService(IAgentService.class);
}
else if (cdmBase instanceof TaxonName) {
service = (IService) getService(INameService.class);
}
else if (cdmBase instanceof TaxonBase) {
service = (IService) getService(ITaxonService.class);
}
else if (cdmBase instanceof SpecimenOrObservationBase) {
service = (IService) getService(IOccurrenceService.class);
}
else if (cdmBase instanceof Media) {
service = (IService) getService(IMediaService.class);
}
else if (cdmBase instanceof Collection) {
service = (IService) getService(ICollectionService.class);
}
else if (cdmBase instanceof eu.etaxonomy.cdm.model.permission.User) {
service = (IService) getService(IUserService.class);
}
else if (cdmBase instanceof Group) {
service = (IService) getService(IGroupService.class);
}
else if (cdmBase instanceof DescriptiveDataSet) {
service = (IService) getService(IDescriptiveDataSetService.class);
}
else if (cdmBase instanceof TermVocabulary>) {
service = (IService) getService(IVocabularyService.class);
}
else if (cdmBase instanceof DefinedTermBase>) {
service = (IService) getService(ITermService.class);
}
else if (cdmBase instanceof Primer) {
service = (IService) getService(IPrimerService.class);
}
else if (cdmBase instanceof Amplification) {
service = (IService) getService(IAmplificationService.class);
}
else if (cdmBase instanceof PolytomousKey) {
service = (IService) getService(IPolytomousKeyService.class);
}
else if (cdmBase instanceof PolytomousKeyNode) {
service = (IService) getService(IPolytomousKeyNodeService.class);
}
else if (cdmBase instanceof Annotation) {
service = (IService) getService(IAnnotationService.class);
}
else if (cdmBase instanceof Classification) {
service = (IService) getService(IClassificationService.class);
}
else if (cdmBase instanceof DescriptionBase>) {
service = (IService) getService(IDescriptionService.class);
}
else if (cdmBase instanceof EntityConstraintViolation) {
service = (IService) getService(IEntityConstraintViolationService.class);
}
else if (cdmBase instanceof EntityValidation) {
service = (IService) getService(IEntityValidationService.class);
}
else if (cdmBase instanceof TermNode) {
service = (IService) getService(ITermNodeService.class);
}
else if (cdmBase instanceof TermTree) {
service = (IService) getService(ITermTreeService.class);
}
else if (cdmBase instanceof GrantedAuthority) {
service = (IService) getService(IGrantedAuthorityService.class);
}
else if (cdmBase instanceof Marker) {
service = (IService) getService(IMarkerService.class);
}
else if (cdmBase instanceof Registration) {
service = (IService) getService(IRegistrationService.class);
}
else if (cdmBase instanceof Rights) {
service = (IService) getService(IRightsService.class);
}
else{
String message = "Service for entity of class %s not yet implemented in TaxEditor";
message = String.format(message, cdmBase.getClass().getSimpleName());
throw new RuntimeException(message);
}
}
return service;
}
public boolean isConnected() {
return isConnected;
}
public void setConnected(boolean isConnected) {
this.isConnected = isConnected;
}
}