Added listByReferenceTitle() to search in 'title'
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / IdentifiableServiceBase.java
index 58539896a155ba55cddd701f16e84670fc5f633e..a80ac51fbb53e2112a4d58e321b9a0b4564a2a2c 100644 (file)
@@ -1,3 +1,4 @@
+// $Id$
 /**
 * Copyright (C) 2007 EDIT
 * European Distributed Institute of Taxonomy 
 
 package eu.etaxonomy.cdm.api.service;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.log4j.Logger;
+import org.hibernate.criterion.Criterion;
+import org.springframework.transaction.annotation.Transactional;
 
+import eu.etaxonomy.cdm.api.service.config.IIdentifiableEntityServiceConfigurator;
+import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
 import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.common.ISourceable;
 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
-import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;
+import eu.etaxonomy.cdm.model.common.IdentifiableSource;
+import eu.etaxonomy.cdm.model.common.LSID;
+import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;
+import eu.etaxonomy.cdm.model.media.Rights;
+import eu.etaxonomy.cdm.model.reference.ReferenceBase;
+import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
 import eu.etaxonomy.cdm.persistence.dao.common.IIdentifiableDao;
+import eu.etaxonomy.cdm.persistence.query.MatchMode;
+import eu.etaxonomy.cdm.persistence.query.OrderHint;
+import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
 
-public abstract class IdentifiableServiceBase<T extends IdentifiableEntity> extends ServiceBase<T
+public abstract class IdentifiableServiceBase<T extends IdentifiableEntity,DAO extends IIdentifiableDao<T>> extends AnnotatableServiceBase<T,DAO
                                                implements IIdentifiableEntityService<T>{
-       static Logger logger = Logger.getLogger(IdentifiableServiceBase.class);
-//     protected IIdentifiableDao<T> dao;
-//
-//     protected void setEntityDao(IIdentifiableDao<T> dao){
-//             this.dao=dao;
-//     }
+       
+       protected static final int UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE = 1000;
+       protected static final  Logger logger = Logger.getLogger(IdentifiableServiceBase.class);
+
+       @Transactional(readOnly = true)
+       public Pager<Rights> getRights(T t, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+        Integer numberOfResults = dao.countRights(t);
+               
+               List<Rights> results = new ArrayList<Rights>();
+               if(numberOfResults > 0) { // no point checking again
+                       results = dao.getRights(t, pageSize, pageNumber,propertyPaths); 
+               }
+               
+               return new DefaultPagerImpl<Rights>(pageNumber, numberOfResults, pageSize, results);
+       }
+       
+       @Transactional(readOnly = true)
+       public Pager<IdentifiableSource> getSources(T t, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
+                Integer numberOfResults = dao.countSources(t);
+                       
+                       List<IdentifiableSource> results = new ArrayList<IdentifiableSource>();
+                       if(numberOfResults > 0) { // no point checking again
+                               results = dao.getSources(t, pageSize, pageNumber,propertyPaths); 
+                       }
+                       
+                       return new DefaultPagerImpl<IdentifiableSource>(pageNumber, numberOfResults, pageSize, results);
+       }
 
+       @Transactional(readOnly = true)
+       protected List<T> findByTitle(IIdentifiableEntityServiceConfigurator config){
+               return ((IIdentifiableDao)dao).findByTitle(config.getTitleSearchString(),
+                               config.getMatchMode(), 0, -1, null);
+               // TODO: Implement parameters pageSize, pageNumber, and criteria
+       }
+       
+       @Transactional(readOnly = false)
+       public T replace(T x, T y) {
+               return dao.replace(x, y);
+       }
+       /**
+        * FIXME Candidate for harmonization
+        * Given that this method is strongly typed, and generic, could we not simply expose it as
+        * List<T> findByTitle(String title) as it is somewhat less cumbersome. Admittedly, I don't 
+        * understand what is going on with the configurators etc. so maybe there is a good reason for
+        * the design of this method. 
+        * @param title
+        * @return
+        */
+       @Transactional(readOnly = true)
        protected List<T> findCdmObjectsByTitle(String title){
                return ((IIdentifiableDao)dao).findByTitle(title);
        }
        
+       @Transactional(readOnly = true)
+       protected List<T> findCdmObjectsByTitle(String title, Class<T> clazz){
+               return ((IIdentifiableDao)dao).findByTitleAndClass(title, clazz);
+       }
+       @Transactional(readOnly = true)
        protected List<T> findCdmObjectsByTitle(String title, CdmBase sessionObject){
                return ((IIdentifiableDao)dao).findByTitle(title, sessionObject);
        }
-}
+       
+       /*
+        * TODO - Migrated from CommonServiceBase
+        *  (non-Javadoc)
+        * @see eu.etaxonomy.cdm.api.service.ICommonService#getSourcedObjectById(java.lang.String, java.lang.String)
+        */
+       @Transactional(readOnly = true)
+       public ISourceable getSourcedObjectByIdInSource(Class clazz, String idInSource, String idNamespace) {
+               ISourceable result = null;
+
+               List<T> list = dao.findOriginalSourceByIdInSource(idInSource, idNamespace);
+               if (! list.isEmpty()){
+                       result = list.get(0);
+               }
+               return result;
+       }
+       
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#getUuidAndTitleCache()
+        */
+       @Transactional(readOnly = true)
+       public List<UuidAndTitleCache<T>> getUuidAndTitleCache() {
+               return dao.getUuidAndTitleCache();
+       }\r
+       
+       @Transactional(readOnly = true)\r
+       public Pager<T> findByTitle(Class<? extends T> clazz, String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
+                Integer numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria);\r
+                       \r
+                List<T> results = new ArrayList<T>();\r
+                if(numberOfResults > 0) { // no point checking again\r
+                               results = dao.findByTitle(clazz, queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths); \r
+                }\r
+                       \r
+                 return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);\r
+       }
+       
+       @Transactional(readOnly = true)
+       public List<T> listByTitle(Class<? extends T> clazz, String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
+                Integer numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria);
+                       
+                List<T> results = new ArrayList<T>();
+                if(numberOfResults > 0) { // no point checking again
+                               results = dao.findByTitle(clazz, queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths); 
+                }
+                return results;
+       }
+
+       @Transactional(readOnly = true)
+       public List<T> listByReferenceTitle(Class<? extends T> clazz, String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
+                Integer numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria);
+                       
+                List<T> results = new ArrayList<T>();
+                if(numberOfResults > 0) { // no point checking again
+                               results = dao.findByReferenceTitle(clazz, queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths); 
+                }
+                return results;
+       }
+       
+       @Transactional(readOnly = true)
+       public T find(LSID lsid) {
+               return dao.find(lsid);
+       }
+       
+       @Transactional(readOnly = true)
+       public Pager<T> search(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
+        Integer numberOfResults = dao.count(clazz,queryString);
+               
+               List<T> results = new ArrayList<T>();
+               if(numberOfResults > 0) { // no point checking again
+                       results = dao.search(clazz,queryString, pageSize, pageNumber, orderHints, propertyPaths); 
+               }
+               
+               return new DefaultPagerImpl<T>(pageNumber, numberOfResults, pageSize, results);
+       }
+       
+       @Transactional(readOnly = false)
+       public void updateTitleCache(Class<? extends T> clazz) {
+               IIdentifiableEntityCacheStrategy<T> cacheStrategy = null;
+               updateTitleCache(clazz, UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE, cacheStrategy);
+       }
+
+       
+       @Transactional(readOnly = false)  //TODO check transactional behaviour, e.g. what happens with the session if count is very large 
+       public void updateTitleCache(Class<? extends T> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<T> cacheStrategy) {
+               if (stepSize == null){
+                       stepSize = UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE;
+               }
+                
+               int count = dao.count(clazz);
+               for(int i = 0 ; i < count ; i = i + stepSize){
+                       // not sure if such strict ordering is necessary here, but for safety reasons I do it
+                       ArrayList<OrderHint> orderHints = new ArrayList<OrderHint>();
+                       orderHints.add( new OrderHint("id", OrderHint.SortOrder.ASCENDING));
+                       List<T> list = this.list(clazz, stepSize, i, orderHints, null);
+                       List<T> entitiesToUpdate = new ArrayList<T>();
+                       for (T entity : list){
+                               if (entity.isProtectedTitleCache() == false){
+                                       IIdentifiableEntityCacheStrategy entityCacheStrategy = cacheStrategy;
+                                       if (entityCacheStrategy == null){
+                                               entityCacheStrategy = entity.getCacheStrategy();
+                                               //FIXME find out why the wrong cache strategy is loaded here, see #1876 
+                                               if (entity instanceof ReferenceBase){
+                                                       entityCacheStrategy = ReferenceFactory.newReference(((ReferenceBase)entity).getType()).getCacheStrategy();
+                                               }
+                                       }
+                                       entity.setCacheStrategy(entityCacheStrategy);
+                                       //TODO this won't work for those classes that always generate the title cache new
+                                       String titleCache = entity.getTitleCache();
+                                       setOtherCachesNull(entity); //TODO find better solution
+                                       String newTitleCache = entityCacheStrategy.getTitleCache(entity);
+                                       if (titleCache == null || titleCache != null && ! titleCache.equals(newTitleCache)){
+                                               entity.setTitleCache(null, false);
+                                               entity.getTitleCache();
+                                               entitiesToUpdate.add(entity);
+                                       }
+                               }
+                       }
+                       saveOrUpdate(entitiesToUpdate);
+                       
+               }
+       }
+
+       /**
+        * Needs override if not only the title cache should be set to null to
+        * generate the correct new title cache
+        */
+       protected void setOtherCachesNull(T entity) {
+               return;
+       }
+}\r
+