Added listByReferenceTitle() to search in 'title'
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / IdentifiableServiceBase.java
index f4e010ed2cfa1894a0045c4c97e4ada711ecaa26..a80ac51fbb53e2112a4d58e321b9a0b4564a2a2c 100644 (file)
@@ -27,18 +27,20 @@ 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;
 
-@Transactional(readOnly = true)
 public abstract class IdentifiableServiceBase<T extends IdentifiableEntity,DAO extends IIdentifiableDao<T>> extends AnnotatableServiceBase<T,DAO> 
                                                implements IIdentifiableEntityService<T>{
-       @SuppressWarnings("unused")
-       protected
-       static final  Logger logger = Logger.getLogger(IdentifiableServiceBase.class);
-
        
+       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);
                
@@ -49,7 +51,8 @@ public abstract class IdentifiableServiceBase<T extends IdentifiableEntity,DAO e
                
                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);
                        
@@ -61,11 +64,17 @@ public abstract class IdentifiableServiceBase<T extends IdentifiableEntity,DAO e
                        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
@@ -75,13 +84,16 @@ public abstract class IdentifiableServiceBase<T extends IdentifiableEntity,DAO e
         * @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);
        }
@@ -91,6 +103,7 @@ public abstract class IdentifiableServiceBase<T extends IdentifiableEntity,DAO e
         *  (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;
 
@@ -104,10 +117,12 @@ public abstract class IdentifiableServiceBase<T extends IdentifiableEntity,DAO e
        /* (non-Javadoc)
         * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#getUuidAndTitleCache()
         */
+       @Transactional(readOnly = true)
        public List<UuidAndTitleCache<T>> getUuidAndTitleCache() {
                return dao.getUuidAndTitleCache();
        }\r
-       \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
@@ -119,8 +134,98 @@ public abstract class IdentifiableServiceBase<T extends IdentifiableEntity,DAO e
                  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