X-Git-Url: https://dev.e-taxonomy.eu/gitweb/cdmlib.git/blobdiff_plain/f197a58908aaf60a945894ac21aa34282899cd6e..6509418e98662e6311710bad9cc87046c102eac7:/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IdentifiableServiceBase.java diff --git a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IdentifiableServiceBase.java b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IdentifiableServiceBase.java index 6f71feaa62..8d0d728cf4 100644 --- a/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IdentifiableServiceBase.java +++ b/cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IdentifiableServiceBase.java @@ -12,20 +12,22 @@ package eu.etaxonomy.cdm.api.service; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.hibernate.criterion.Criterion; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Propagation; 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.common.IProgressMonitor; +import eu.etaxonomy.cdm.common.monitor.DefaultProgressMonitor; +import eu.etaxonomy.cdm.common.monitor.IProgressMonitor; +import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper; import eu.etaxonomy.cdm.model.common.CdmBase; import eu.etaxonomy.cdm.model.common.ISourceable; import eu.etaxonomy.cdm.model.common.IdentifiableEntity; @@ -33,9 +35,12 @@ 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.name.NonViralName; import eu.etaxonomy.cdm.model.reference.Reference; import eu.etaxonomy.cdm.model.reference.ReferenceFactory; import eu.etaxonomy.cdm.persistence.dao.common.IIdentifiableDao; +import eu.etaxonomy.cdm.persistence.dao.hibernate.HibernateBeanInitializer; +import eu.etaxonomy.cdm.persistence.dao.initializer.AutoPropertyInitializer; import eu.etaxonomy.cdm.persistence.query.MatchMode; import eu.etaxonomy.cdm.persistence.query.OrderHint; import eu.etaxonomy.cdm.persistence.query.OrderHint.SortOrder; @@ -50,14 +55,12 @@ import eu.etaxonomy.cdm.strategy.merge.MergeException; public abstract class IdentifiableServiceBase> extends AnnotatableServiceBase implements IIdentifiableEntityService{ - - @Autowired - protected ICommonService commonService; protected static final int UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE = 1000; protected static final Logger logger = Logger.getLogger(IdentifiableServiceBase.class); + @Override @Transactional(readOnly = true) public Pager getRights(T t, Integer pageSize, Integer pageNumber, List propertyPaths) { Integer numberOfResults = dao.countRights(t); @@ -70,6 +73,7 @@ public abstract class IdentifiableServiceBase(pageNumber, numberOfResults, pageSize, results); } + @Override @Transactional(readOnly = true) public Pager getSources(T t, Integer pageSize, Integer pageNumber, List propertyPaths) { Integer numberOfResults = dao.countSources(t); @@ -82,14 +86,9 @@ public abstract class IdentifiableServiceBase(pageNumber, numberOfResults, pageSize, results); } - @Transactional(readOnly = true) - protected List findByTitle(IIdentifiableEntityServiceConfigurator config){ - return ((IIdentifiableDao)dao).findByTitle(config.getTitleSearchString(), - config.getMatchMode(), 0, -1, null); - // TODO: Implement parameters pageSize, pageNumber, and criteria - } @Transactional(readOnly = false) + @Override public T replace(T x, T y) { return dao.replace(x, y); } @@ -122,6 +121,7 @@ public abstract class IdentifiableServiceBase> getUuidAndTitleCache() { return dao.getUuidAndTitleCache(); } @Transactional(readOnly = true) + @Override public Pager findByTitle(Class clazz, String queryString,MatchMode matchmode, List criteria, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { Integer numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria); @@ -153,6 +152,13 @@ public abstract class IdentifiableServiceBase findByTitle(IIdentifiableEntityServiceConfigurator config){ + return findByTitle(config.getClazz(), config.getTitleSearchStringSqlized(), config.getMatchMode(), config.getCriteria(), config.getPageSize(), config.getPageNumber(), config.getOrderHints(), config.getPropertyPaths()); + } + + @Transactional(readOnly = true) + @Override public List listByTitle(Class clazz, String queryString,MatchMode matchmode, List criteria, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { Integer numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria); @@ -162,8 +168,24 @@ public abstract class IdentifiableServiceBase findTitleCache(Class clazz, String queryString, Integer pageSize, Integer pageNumber, List orderHints, MatchMode matchMode){ + long numberOfResults = dao.countTitleCache(clazz, queryString, matchMode); + + List results = new ArrayList(); + if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize) + results = dao.findTitleCache(clazz, queryString, pageSize, pageNumber, orderHints, matchMode); + } + int r = 0; + r += numberOfResults; + + return new DefaultPagerImpl(pageNumber, r , pageSize, results); + } @Transactional(readOnly = true) + @Override public List listByReferenceTitle(Class clazz, String queryString,MatchMode matchmode, List criteria, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { Integer numberOfResults = dao.countByReferenceTitle(clazz, queryString, matchmode, criteria); @@ -175,11 +197,13 @@ public abstract class IdentifiableServiceBase search(Class clazz, String queryString, Integer pageSize, Integer pageNumber, List orderHints, List propertyPaths) { Integer numberOfResults = dao.count(clazz,queryString); @@ -191,53 +215,209 @@ public abstract class IdentifiableServiceBase(pageNumber, numberOfResults, pageSize, results); } - - /* (non-Javadoc) - * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache() - */ @Override + @Transactional(readOnly = false) public void updateTitleCache() { updateTitleCache(null, null, null, null); } @Transactional(readOnly = false) //TODO check transactional behaviour, e.g. what happens with the session if count is very large - protected void updateTitleCacheImpl(Class clazz, Integer stepSize, IIdentifiableEntityCacheStrategy cacheStrategy, IProgressMonitor monitor) { + protected void updateTitleCacheImpl(Class clazz, Integer stepSize, IIdentifiableEntityCacheStrategy cacheStrategy, IProgressMonitor monitor) { if (stepSize == null){ stepSize = UPDATE_TITLE_CACHE_DEFAULT_STEP_SIZE; } - + if (monitor == null){ + monitor = DefaultProgressMonitor.NewInstance(); + } + int count = dao.count(clazz); + monitor.beginTask("update titles", count); + int worked = 0; 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 orderHints = new ArrayList(); orderHints.add( new OrderHint("id", OrderHint.SortOrder.ASCENDING)); - List list = this.list(clazz, stepSize, i, orderHints, null); + + + Map, AutoPropertyInitializer> oldAutoInit = switchOfAutoinitializer(); + List list = this.list(clazz, stepSize, i, orderHints, null); + switchOnOldAutoInitializer(oldAutoInit); + List entitiesToUpdate = new ArrayList(); for (T entity : list){ + HibernateProxyHelper.deproxy(entity, clazz); 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 Reference){ - entityCacheStrategy = ReferenceFactory.newReference(((Reference)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); - } + updateTitleCacheForSingleEntity(cacheStrategy, entitiesToUpdate, entity); + } + worked++; + } + for (T entity: entitiesToUpdate){ + if (entity.getTitleCache() != null){ + //System.err.println(entity.getTitleCache()); + }else{ + //System.err.println("no titleCache" + ((NonViralName)entity).getNameCache()); } } saveOrUpdate(entitiesToUpdate); + monitor.worked(list.size()); + if (monitor.isCanceled()){ + monitor.done(); + return; + } + } + monitor.done(); + } + + /** + * Brings back all auto initializers to the bean initializer + * @see #switchOfAutoinitializer() + * @param oldAutoInit + */ + protected void switchOnOldAutoInitializer( + Map, AutoPropertyInitializer> oldAutoInit) { + HibernateBeanInitializer initializer = (HibernateBeanInitializer)this.appContext.getBean("defaultBeanInitializer"); + initializer.setBeanAutoInitializers(oldAutoInit); + } + + /** + * Removes all auto initializers from the bean initializer + * + * @see #switchOnOldAutoInitializer(Map) + * @return + */ + protected Map, AutoPropertyInitializer> switchOfAutoinitializer() { + HibernateBeanInitializer initializer = (HibernateBeanInitializer)this.appContext.getBean("defaultBeanInitializer"); + Map, AutoPropertyInitializer> oldAutoInitializers = initializer.getBeanAutoInitializers(); + Map, AutoPropertyInitializer> map = new HashMap, AutoPropertyInitializer>(); + initializer.setBeanAutoInitializers(map); + return oldAutoInitializers; + } + + /** + * @param cacheStrategy + * @param entitiesToUpdate + * @param entity + */ + /** + * @param cacheStrategy + * @param entitiesToUpdate + * @param entity + */ + private void updateTitleCacheForSingleEntity( + IIdentifiableEntityCacheStrategy cacheStrategy, + List entitiesToUpdate, T entity) { + + assert (entity.isProtectedTitleCache() == false ); + + //exclude recursive inreferences + if (entity.isInstanceOf(Reference.class)){ + Reference ref = CdmBase.deproxy(entity, Reference.class); + if (ref.getInReference() != null && ref.getInReference().equals(ref)){ + return; + } + } + + + //define the correct cache strategy + 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 Reference){ + entityCacheStrategy = ReferenceFactory.newReference(((Reference)entity).getType()).getCacheStrategy(); + } + } + entity.setCacheStrategy(entityCacheStrategy); + + + //old titleCache + entity.setProtectedTitleCache(true); + String oldTitleCache = entity.getTitleCache(); + entity.setTitleCache(oldTitleCache, false); //before we had entity.setProtectedTitleCache(false) but this deleted the titleCache itself + + //NonViralNames and Reference have more caches //TODO handle in NameService + String oldNameCache = null; + String oldFullTitleCache = null; + String oldAbbrevTitleCache = null; + if (entity instanceof NonViralName ){ + + try{ + NonViralName nvn = (NonViralName) entity; + if (!nvn.isProtectedNameCache()){ + nvn.setProtectedNameCache(true); + oldNameCache = nvn.getNameCache(); + nvn.setProtectedNameCache(false); + } + if (!nvn.isProtectedFullTitleCache()){ + nvn.setProtectedFullTitleCache(true); + oldFullTitleCache = nvn.getFullTitleCache(); + nvn.setProtectedFullTitleCache(false); + } + }catch(ClassCastException e){ + System.out.println("entity: " + entity.getTitleCache()); + } + }else if (entity instanceof Reference){ + Reference ref = (Reference) entity; + if (!ref.isProtectedAbbrevTitleCache()){ + ref.setProtectedAbbrevTitleCache(true); + oldAbbrevTitleCache = ref.getAbbrevTitleCache(); + ref.setProtectedAbbrevTitleCache(false); + } } + setOtherCachesNull(entity); + String newTitleCache= null; + NonViralName nvn = null;//TODO find better solution + try{ + if (entity instanceof NonViralName){ + nvn = (NonViralName) entity; + newTitleCache = entityCacheStrategy.getTitleCache(nvn); + } else{ + newTitleCache = entityCacheStrategy.getTitleCache(entity); + } + }catch (ClassCastException e){ + nvn = HibernateProxyHelper.deproxy(entity, NonViralName.class); + newTitleCache = entityCacheStrategy.getTitleCache(nvn); + //System.out.println("titleCache: " +entity.getTitleCache()); + } + + if ( oldTitleCache == null || oldTitleCache != null && ! oldTitleCache.equals(newTitleCache) ){ + entity.setTitleCache(null, false); + String newCache = entity.getTitleCache(); + if (newCache == null){ + logger.warn("newCache should never be null"); + } + if (oldTitleCache == null){ + logger.info("oldTitleCache should never be null"); + } + if (nvn != null){ + //NonViralName nvn = (NonViralName) entity; + nvn.getNameCache(); + nvn.getFullTitleCache(); + } + if (entity instanceof Reference){ + Reference ref = (Reference) entity; + ref.getAbbrevTitleCache(); + } + entitiesToUpdate.add(entity); + }else if (nvn != null){ + //NonViralName nvn = (NonViralName) entity; + String newNameCache = nvn.getNameCache(); + String newFullTitleCache = nvn.getFullTitleCache(); + if ((oldNameCache == null && !nvn.isProtectedNameCache()) || (oldNameCache != null && !oldNameCache.equals(newNameCache))){ + entitiesToUpdate.add(entity); + }else if ((oldFullTitleCache == null && !nvn.isProtectedFullTitleCache()) || (oldFullTitleCache != null && !oldFullTitleCache.equals(newFullTitleCache))){ + entitiesToUpdate.add(entity); + } + }else if (entity instanceof Reference){ + Reference ref = (Reference) entity; + String newAbbrevTitleCache = ref.getAbbrevTitleCache(); + if ( (oldAbbrevTitleCache == null && !ref.isProtectedAbbrevTitleCache() ) || (oldAbbrevTitleCache != null && !oldAbbrevTitleCache.equals(newAbbrevTitleCache))){ + entitiesToUpdate.add(entity); + } + } + + } @@ -261,11 +441,8 @@ public abstract class IdentifiableServiceBase clazz, IMatchStrategy matchStrategy, IMergeStrategy mergeStrategy) { DeduplicateState dedupState = new DeduplicateState(); @@ -372,6 +549,25 @@ public abstract class IdentifiableServiceBase clazz, String queryString,MatchMode matchmode, List criteria){ + Integer numberOfResults = dao.countByTitle(clazz, queryString, matchmode, criteria); + + return numberOfResults; + } + + @Transactional(readOnly = true) + @Override + public Integer countByTitle(IIdentifiableEntityServiceConfigurator config){ + return countByTitle(config.getClazz(), config.getTitleSearchStringSqlized(), + config.getMatchMode(), config.getCriteria()); + + } + + + }