package eu.etaxonomy.taxeditor.store;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.UUID;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
-import org.apache.log4j.Logger;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.swt.widgets.Display;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.security.authentication.ProviderManager;
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
+import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
-import eu.etaxonomy.cdm.api.service.ILocationService;
-import eu.etaxonomy.cdm.api.service.INameService;
-import eu.etaxonomy.cdm.api.service.IReferenceService;
-import eu.etaxonomy.cdm.api.service.ITaxonService;
-import eu.etaxonomy.cdm.api.service.ITermService;
-import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;
-import eu.etaxonomy.cdm.api.service.config.impl.TaxonServiceConfiguratorImpl;
+import eu.etaxonomy.cdm.api.service.IService;
import eu.etaxonomy.cdm.database.DbSchemaValidation;
import eu.etaxonomy.cdm.database.ICdmDataSource;
-import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
-import eu.etaxonomy.cdm.model.common.CdmBase;
-import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
+import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
import eu.etaxonomy.cdm.model.common.Language;
-import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
-import eu.etaxonomy.cdm.model.common.TermVocabulary;
-import eu.etaxonomy.cdm.model.common.VocabularyEnum;
-import eu.etaxonomy.cdm.model.description.Feature;
-import eu.etaxonomy.cdm.model.name.NameRelationshipType;
-import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
-import eu.etaxonomy.cdm.model.name.Rank;
-import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
-import eu.etaxonomy.cdm.model.name.TaxonNameBase;
-import eu.etaxonomy.cdm.model.reference.Article;
-import eu.etaxonomy.cdm.model.reference.Book;
-import eu.etaxonomy.cdm.model.reference.BookSection;
-import eu.etaxonomy.cdm.model.reference.Generic;
-import eu.etaxonomy.cdm.model.reference.ReferenceBase;
-import eu.etaxonomy.cdm.model.taxon.Taxon;
-import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
-import eu.etaxonomy.cdm.persistence.query.MatchMode;
import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
+import eu.etaxonomy.taxeditor.io.ExportManager;
+import eu.etaxonomy.taxeditor.io.ImportManager;
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
+import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
+import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
/**
- * This implementation of ICdmDataRepository depends on hibernate sessions to store the data correctly
+ * 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.
- *
- *
+ *
+ * Only methods that either get or manipulate data are exposed here. So this class acts as a facade
+ * for the methods in cdmlib-service.
+ *
* @author n.hoffmann
* @created 17.03.2009
* @version 1.0
*/
public class CdmStore{
- private static final Logger logger = Logger.getLogger(CdmStore.class);
- // FIXME change this to ClassPathResources as soon as it is included into the plugin
- private static String DEFAULT_APPLICATION_CONTEXT = null;
- private static DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.UPDATE;
+ private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource("/eu/etaxonomy/cdm/editorApplicationContext.xml", TaxeditorStorePlugin.class);
+ private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
private static CdmStore instance;
-
+
private CdmApplicationController applicationController;
+
+ private static LoginManager loginManager;
+
+ private static ImportManager importManager;
+
+ private static ExportManager exportManager;
+
+ private static ContextManager contextManager;
+
+ private static TermManager termManager = new TermManager();
+
+ private static SearchManager searchManager;
+
+ private static EditorManager editorManager;
- private ConversationHolder globalReadOnlyConversation;
+ private static CdmStoreConnector job;
- private static DbSchemaValidation dbSchemaValidation;
+ private Language language;
+
+ private ICdmDataSource cdmDatasource;
+
+ private boolean isConnected;
/**
- *
- * @return
+ * <p>getDefault</p>
+ *
+ * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
*/
- public static CdmStore getDefault(){
- return getDefault(DEFAULT_APPLICATION_CONTEXT);
+ protected static CdmStore getDefault(){
+ if(instance != null && instance.isConnected){
+ return instance;
+ }else if(instance == null || !instance.isConnected){
+
+ StoreUtil.warningDialog("Application is not connected to a datastore", instance, "The requested operation is only available when " +
+ "connected to a datasource. You may choose a datasource to connect to or create a new one in the datasource view.");
+
+ StoreUtil.showView(CdmDataSourceViewPart.ID);
+
+ }
+
+ throw new RuntimeException();
}
/**
- *
- * @param applicationContextBean
- * @return
+ * Initialize the with the last edited datasource
*/
- public static CdmStore getDefault(String applicationContextBean){
- if(instance == null){
- logger.info("Initializing application context ...");
- ICdmDataSource cdmDatasource = CdmDataSourceRepository.getDefault().
- getCurrentDataSource();
-
- instance = new CdmStore(cdmDatasource, getDbSchemaValidation(), applicationContextBean);
-
- logger.info("Application context initialized.");
- }
- return instance;
+ public static void connect() {
+
+ ICdmDataSource datasource = CdmDataSourceRepository.getCurrentDataSource();
+
+ connect(datasource);
}
-
+
/**
- * @return
+ * Initialize with a specific datasource
+ *
+ * @param datasource a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
*/
- private static DbSchemaValidation getDbSchemaValidation() {
- return (dbSchemaValidation == null) ? DEFAULT_DB_SCHEMA_VALIDATION : dbSchemaValidation;
+ public static void connect(ICdmDataSource datasource) {
+ connect(datasource, DEFAULT_DB_SCHEMA_VALIDATION, DEFAULT_APPLICATION_CONTEXT);
}
-
+
/**
+ * Initialize and provide
*
+ * @param datasource
+ * @param dbSchemaValidation
+ * @param applicationContextBean
*/
- private CdmStore(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, String applicationContextBean) {
- // TODO application context bean is not honored by application controller at the moment.
- // cdmDefaultApplicationController bean gets loaded per default always.
-
- try {
- CdmStore.DEFAULT_APPLICATION_CONTEXT = applicationContextBean;
-// applicationController = CdmApplicationController.NewInstance(applicationContextBean, dataSource, dbSchemaValidation, false);
+ private static void connect(final ICdmDataSource datasource, final DbSchemaValidation dbSchemaValidation, final Resource applicationContextBean){
+ StoreUtil.info("Connecting to datasource: " + datasource);
+
+ job = new CdmStoreConnector(Display.getDefault(), datasource, dbSchemaValidation, applicationContextBean);
+ job.setUser(true);
+ job.setPriority(Job.BUILD);
+ job.schedule();
-// logger.warn("OMITTING TERM LOADING FOR DEBUGGING");
-// applicationController = CdmApplicationController.NewInstance(dataSource, dbSchemaValidation, true);
- applicationController = CdmApplicationController.NewInstance(dataSource, dbSchemaValidation);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- public Set<TaxonRelationshipType> getConceptRelationshipTypes() {
- Set<TaxonRelationshipType> conceptRelationshipTypes = getTaxonRelationshipTypes().getTerms();
- // remove these two relations as they are considered standard taxon relations
- conceptRelationshipTypes.remove(TaxonRelationshipType.MISAPPLIED_NAME_FOR());
- conceptRelationshipTypes.remove(TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN());
-
- return conceptRelationshipTypes;
- }
-
- public ReferenceBase<?> getDefaultSec() {
- // TODO why is this returning null? and of course, replace w the real deal
- return applicationController.getReferenceService().getReferenceByUuid(
- UUID.fromString("f3593c18-a8d2-4e51-bdad-0befbf8fb2d1"));
}
- private TermVocabulary<Feature> getFeaturesInternal() {
- return applicationController.getTermService().getVocabulary(VocabularyEnum.Feature);
- }
-
- public static TermVocabulary<Feature> getFeatures() {
- return getDefault().getFeaturesInternal();
+ public static boolean isConnecting(){
+ return job != null && job.getState() == Job.RUNNING;
}
- public SortedSet<NameRelationshipType> getNameRelationshipTypes() {
- return applicationController.getTermService().getVocabulary(VocabularyEnum.NameRelationshipType).getTermsOrderedByLabels(Language.DEFAULT());
+ /**
+ * 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(){
+ /* (non-Javadoc)
+ * @see java.lang.Runnable#run()
+ */
+ @Override
+ public void run() {
+ getContextManager().notifyContextAboutToStop(monitor);
+ if((monitor == null || (!monitor.isCanceled()) && isActive())){
+ getContextManager().notifyContextStop(monitor);
+ if(instance.getApplicationController() != null){
+ instance.getApplicationController().close();
+ }
+ instance.close();
+ }
+ }
+ });
}
- public TermVocabulary<NomenclaturalStatusType> getNomenclaturalStatusTypesInternal() {
- return applicationController.getTermService().getVocabulary(VocabularyEnum.NomenclaturalStatusType);
- }
-
- public static Set<NomenclaturalStatusType> getNomenclaturalStatusTypes(){
- // TODO sort types
- return getDefault().getNomenclaturalStatusTypesInternal().getTerms();
+ private void close() {
+ isConnected = false;
+ cdmDatasource = null;
}
- public OrderedTermVocabulary<Rank> getRanksInternal(){
- TermVocabulary<Rank> vocabulary = applicationController.getTermService().getVocabulary(VocabularyEnum.Rank);
- return HibernateProxyHelper.deproxy(vocabulary, OrderedTermVocabulary.class);
+ static void setInstance(CdmApplicationController applicationController, ICdmDataSource dataSource){
+ instance = new CdmStore(applicationController, dataSource);
}
- public static List<Rank> getPreferredRanks(){
- return PreferencesUtil.getPreferredRanks();
- }
-
- public List<Taxon> getRootTaxa() {
- boolean onlyWithChildren = false;
- boolean withMisapplications = true;
-
- return applicationController.getTaxonService().getRootTaxa(
- getDefaultSec(), onlyWithChildren, withMisapplications);
- }
-
- public OrderedTermVocabulary<TaxonRelationshipType> getTaxonRelationshipTypes() {
- TermVocabulary vocabulary = HibernateProxyHelper.deproxy
- (applicationController.getTermService().getVocabulary(VocabularyEnum.TaxonRelationshipType), TermVocabulary.class);
- return (OrderedTermVocabulary<TaxonRelationshipType>) vocabulary;
+ private CdmStore(CdmApplicationController applicationController, ICdmDataSource dataSource){
+ this.applicationController = applicationController;
+ this.cdmDatasource = dataSource;
+ isConnected = true;
}
- public TermVocabulary<SpecimenTypeDesignationStatus> getSpecimenTypeDesignationStatus() {
- return applicationController.getTermService().getVocabulary(VocabularyEnum.SpecimenTypeDesignationStatus);
+ /**
+ * All calls to the datastore require
+ *
+ * @return
+ */
+ private CdmApplicationController getApplicationController(){
+ try{
+ return applicationController;
+ }catch(Exception e){
+ StoreUtil.error(CdmStore.class, e);
+ }
+ return null;
}
-
- public UUID saveTaxon(Taxon taxon) {
- return applicationController.getTaxonService().save(taxon);
+ /**
+ * <p>getCurrentApplicationController</p>
+ *
+ * @return a {@link eu.etaxonomy.cdm.api.application.CdmApplicationController} object.
+ */
+ public static CdmApplicationController getCurrentApplicationController(){
+ if(getDefault() != null){
+ return getDefault().getApplicationController();
+ }
+ return null;
}
- public void setApplicationController(
- CdmApplicationController applicationController) {
- this.applicationController = applicationController;
- }
-
- public CdmApplicationController getApplicationController(){
- return applicationController;
- }
+ /*
+ * CONVERSATIONS
+ */
-
/**
- * Create a new conversation and bind resources to it
- *
- * @return
+ * Creates a new conversation, binds resources to the conversation and
+ * start a transaction for this conversation.
+ *
+ * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
*/
- public static ConversationHolder NewConversation(){
+ public static ConversationHolder createConversation() {
+ ConversationHolder conversation = getCurrentApplicationController().NewConversation();
- CdmStore store = getDefault();
- CdmApplicationController controller = store.getApplicationController();
-
- ConversationHolder conversation = controller.NewConversation();
-
+ conversation.startTransaction();
return conversation;
}
-
+
/**
- * Creates a new conversation, binds resources to the conversation and
- * start a transaction for this conversation.
+ * Generic method that will return an implementation of the given service interface
+ * or <code>null</code> if the
*
+ * @param <T>
+ * @param serviceClass
* @return
*/
- public static ConversationHolder NewTransactionalConversation() {
- ConversationHolder conversation = NewConversation();
+ public static <T extends IService> T getService(Class<T> serviceClass){
+ ICdmApplicationConfiguration controller = getCurrentApplicationController();
- conversation.startTransaction();
- return conversation;
+ Method[] methods = ICdmApplicationConfiguration.class.getDeclaredMethods();
+
+ T service = null;
+
+ for(Method method : methods){
+ Type type = method.getGenericReturnType();
+
+ if(type.equals(serviceClass)){
+ try {
+ service = (T) method.invoke(controller, null);
+ break;
+ } catch (IllegalArgumentException e) {
+ StoreUtil.error(CdmStore.class, e);
+ } catch (IllegalAccessException e) {
+ StoreUtil.error(CdmStore.class, e);
+ } catch (InvocationTargetException e) {
+ StoreUtil.error(CdmStore.class, e);
+ }
+ }
+ }
+
+ return service;
}
+ /**
+ * <p>getAuthenticationManager</p>
+ *
+ * @return a {@link org.springframework.security.authentication.ProviderManager} object.
+ */
+ public static ProviderManager getAuthenticationManager() { return getCurrentApplicationController().getAuthenticationManager();}
- private ConversationHolder getGlobalReadOnlyConversation() {
- ConversationHolder conversation = globalReadOnlyConversation == null
- ? NewConversation()
- : globalReadOnlyConversation;
- conversation.bind();
- return conversation;
+ /**
+ * <p>getGeoService</p>
+ *
+ * @return a {@link eu.etaxonomy.cdm.ext.geo.IEditGeoService} object.
+ */
+ public static IEditGeoService getGeoService(){
+ return (IEditGeoService) getCurrentApplicationController().getBean("editGeoService");
}
- public static ConversationHolder getGlobalConversation(){
- return getDefault().getGlobalReadOnlyConversation();
- }
+ /*
+ * LANGUAGE
+ */
- public static ITaxonService getTaxonService(){
- return getDefault().getApplicationController().getTaxonService();
+ /**
+ * <p>getDefaultLanguage</p>
+ *
+ * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
+ */
+ public static Language getDefaultLanguage(){
+ if(getDefault().getLanguage() == null){
+ getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
+ }
+ return getDefault().getLanguage();
}
-
- public static INameService getNameService(){
- return getDefault().getApplicationController().getNameService();
+
+ /**
+ * <p>setDefaultLanguage</p>
+ *
+ * @param language a {@link eu.etaxonomy.cdm.model.common.Language} object.
+ */
+ public static void setDefaultLanguage(Language language){
+ getDefault().setLanguage(language);
}
- public static IReferenceService getReferenceService(){
- return getDefault().getApplicationController().getReferenceService();
+ /**
+ * @return the language
+ */
+ private Language getLanguage() {
+ return language;
}
-
- public static ILocationService getLocationService(){
- return getDefault().getApplicationController().getLocationService();
+
+ /**
+ * @param language the language to set
+ */
+ private void setLanguage(Language language) {
+ this.language = language;
}
+ /*
+ * LOGIN
+ */
+
/**
- * @param searchText
- * @return
+ * <p>Getter for the field <code>loginManager</code>.</p>
+ *
+ * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
*/
- @SuppressWarnings("unchecked")
- public static List<TaxonNameBase> searchNameString(String searchText) {
- List<TaxonNameBase> resultSet = new ArrayList<TaxonNameBase>();
- resultSet.addAll(getNameService()
- .getNamesByName(searchText.replace("*", "%")));
- return resultSet;
+ public static LoginManager getLoginManager(){
+ if(loginManager == null){
+ loginManager = new LoginManager();
+ }
+ return loginManager;
}
- private List<IdentifiableEntity> findTaxaByName(String queryString, boolean restrictToTaxonObjs) {
-
- ITaxonServiceConfigurator configurator = new TaxonServiceConfiguratorImpl();
-
- configurator.setSearchString(queryString);
- configurator.setDoTaxa(true);
- configurator.setMatchMode(MatchMode.BEGINNING);
- if (restrictToTaxonObjs) {
- configurator.setDoNamesWithoutTaxa(false);
- configurator.setDoSynonyms(false);
- } else {
- configurator.setDoNamesWithoutTaxa(true);
- configurator.setDoSynonyms(true);
+ /**
+ * <p>Getter for the field <code>contextManager</code>.</p>
+ *
+ * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
+ */
+ public static ContextManager getContextManager(){
+ if(contextManager == null){
+ contextManager = new ContextManager();
}
- configurator.setReferenceBase(null);
- configurator.setPageNumber(0);
- // TODO currently limit results to 1000
- configurator.setPageSize(1000);
-
- List<IdentifiableEntity> result = getTaxonService().findTaxaAndNames(configurator).getRecords();
-
- return result;
+ return contextManager;
}
- public static List<IdentifiableEntity> searchTaxaByName(String queryString){
- return getDefault().findTaxaByName(queryString, false);
+ public static TermManager getTermManager(){
+ return termManager;
}
-
- public static List<IdentifiableEntity> searchTaxaByName(String queryString, boolean restrictToTaxonObjs){
- return getDefault().findTaxaByName(queryString, restrictToTaxonObjs);
+
+ public static SearchManager getSearchManager(){
+ if(searchManager == null){
+ searchManager = new SearchManager();
+ }
+ return searchManager;
+ }
+
+ public static EditorManager getEditorManager() {
+ if(editorManager == null){
+ editorManager = new EditorManager();
+ }
+
+ return editorManager;
}
+ /*
+ * IMPORT/EXPORT FACTORIES
+ */
+
/**
- * Searches for references by string. "%" is used as a wildcard.
- *
- * @param text
- * @return
+ * <p>Getter for the field <code>importHandler</code>.</p>
+ *
+ * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
*/
- public static List<ReferenceBase> getReferencesByTitle(String reference) {
-
- reference = reference.replace("*", "%");
- List<ReferenceBase> resultsList = null;
- try {
- resultsList = getReferenceService().getReferencesByTitle(reference);
- } catch (RuntimeException e) {
-// MessageDialog.openError(GlobalController.getShell(), "Search reference error",
-// "Reference search returned an error. This could be a Hibernate concurrency problem. " +
-// "Please try saving your work, then searching again.");
- e.printStackTrace();
+ public static ImportManager getImportManager(){
+ if(importManager == null){
+ importManager = ImportManager.NewInstance(getCurrentApplicationController());
}
- return resultsList;
+ return importManager;
}
-
-
- public static List<Language> getLanguages() {
- ITermService termService = getDefault().getApplicationController().getTermService();
- ArrayList<Language> languages = new ArrayList<Language>();
- for (Language language : termService.getLanguageVocabulary()) {
- languages.add(language);
+
+ /**
+ * <p>Getter for the field <code>exportHandler</code>.</p>
+ *
+ * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
+ */
+ public static ExportManager getExportManager(){
+ if(exportManager == null){
+ exportManager = ExportManager.NewInstance(getCurrentApplicationController());
}
-
- // TODO sort languages
-
-// languages.add(Language.ENGLISH());
-// languages.add(Language.GERMAN());
- return languages;
+ return exportManager;
}
/**
- * FIXME mock
- *
- * @return
+ * Whether this CdmStore is currently connected to a datasource
+ *
+ * @return a boolean.
*/
- public static Language getDefaultLanguage(){
- return Language.ENGLISH();
+ public static boolean isActive(){
+ return instance != null && instance.isConnected;
}
/**
- * @return
+ * <p>getDataSource</p>
+ *
+ * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
*/
- private static String getApplicationContextBean() {
- return DEFAULT_APPLICATION_CONTEXT;
+ public static ICdmDataSource getDataSource(){
+ if(isActive()){
+ return instance.getDatasource();
+ }
+ return null;
}
-
+
/**
* @return
*/
- public static LinkedHashMap<Class<?>, String> getReferenceTypes() {
- LinkedHashMap<Class<?>, String> nomReferenceTypeMap = new LinkedHashMap<Class<?>, String>();
-
-// referenceTypeMap.put(BibtexReference.class, "BibTeX Reference");
- nomReferenceTypeMap.put(Article.class, "Article");
- nomReferenceTypeMap.put(Generic.class, "Generic");
- nomReferenceTypeMap.put(Book.class, "Book");
- nomReferenceTypeMap.put(BookSection.class, "Book Section");
-
- return nomReferenceTypeMap;
+ private ICdmDataSource getDatasource() {
+ return cdmDatasource;
}
+
}