ref #1445: improve search for identical names
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / PolytomousKeyServiceImpl.java
index be67683ed218fe90f3b92e55af0f815a5adfb0c5..14c15247f2656446c249d46e133cac81d203f6d0 100644 (file)
@@ -5,98 +5,90 @@
 *\r
 * The contents of this file are subject to the Mozilla Public License Version 1.1\r
 * See LICENSE.TXT at the top of this package for the full license terms.\r
-*/ \r
+*/\r
 \r
 package eu.etaxonomy.cdm.api.service;\r
 \r
 import java.util.ArrayList;\r
+import java.util.Iterator;\r
 import java.util.List;\r
+import java.util.Set;\r
 import java.util.UUID;\r
 \r
 import org.springframework.beans.factory.annotation.Autowired;\r
 import org.springframework.stereotype.Service;\r
-import org.springframework.transaction.annotation.Propagation;\r
 import org.springframework.transaction.annotation.Transactional;\r
 \r
+import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;\r
+import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;\r
 import eu.etaxonomy.cdm.api.service.pager.Pager;\r
 import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;\r
 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;\r
-import eu.etaxonomy.cdm.common.IProgressMonitor;\r
+import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;\r
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;\r
+import eu.etaxonomy.cdm.model.common.CdmBase;\r
 import eu.etaxonomy.cdm.model.description.PolytomousKey;\r
+import eu.etaxonomy.cdm.model.description.PolytomousKeyNode;\r
 import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
 import eu.etaxonomy.cdm.persistence.dao.description.IIdentificationKeyDao;\r
 import eu.etaxonomy.cdm.persistence.dao.description.IPolytomousKeyDao;\r
-import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;\r
 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;\r
 \r
 @Service\r
-@Transactional(propagation = Propagation.SUPPORTS, readOnly = false)\r
+@Transactional(readOnly = false)\r
 public class PolytomousKeyServiceImpl extends IdentifiableServiceBase<PolytomousKey, IPolytomousKeyDao> implements IPolytomousKeyService {\r
 \r
        private IIdentificationKeyDao identificationKeyDao;\r
-       private ITaxonDao taxonDao;\r
-\r
 \r
        @Autowired\r
+       private IPolytomousKeyNodeService nodeService;\r
+\r
+\r
+       @Override\r
+    @Autowired\r
        protected void setDao(IPolytomousKeyDao dao) {\r
                this.dao = dao;\r
        }\r
-       \r
+\r
        @Autowired\r
        protected void setDao(IIdentificationKeyDao identificationKeyDao) {\r
                this.identificationKeyDao = identificationKeyDao;\r
        }\r
-       \r
-       @Autowired\r
-       protected void setDao(ITaxonDao taxonDao) {\r
-               this.taxonDao = taxonDao;\r
-       }\r
 \r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.api.service.IIdentifiableEntityService#updateTitleCache(java.lang.Integer, eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy)\r
-        */\r
        @Override\r
-       public void updateTitleCache(Class<? extends PolytomousKey> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<PolytomousKey> cacheStrategy, IProgressMonitor monitor) {\r
+       public UpdateResult updateCaches(Class<? extends PolytomousKey> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<PolytomousKey> cacheStrategy, IProgressMonitor monitor) {\r
                if (clazz == null){\r
                        clazz = PolytomousKey.class;\r
                }\r
-               super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);\r
+               return super.updateCachesImpl(clazz, stepSize, cacheStrategy, monitor);\r
        }\r
-       \r
 \r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.api.service.IFeatureTreeService#loadWithNodes(java.util.UUID, java.util.List, java.util.List)\r
-        */\r
-       public PolytomousKey loadWithNodes(UUID uuid, List<String> propertyPaths, List<String> nodePaths) {\r
-               \r
+       @Override\r
+    public PolytomousKey loadWithNodes(UUID uuid, List<String> propertyPaths, List<String> nodePaths) {\r
+\r
                if(nodePaths == null){\r
                        nodePaths = new ArrayList<String>();\r
                }\r
                nodePaths.add("children");\r
-               \r
+\r
                List<String> rootPaths = new ArrayList<String>();\r
                rootPaths.add("root");\r
                for(String path : nodePaths) {\r
                        rootPaths.add("root." + path);\r
                }\r
-               \r
-               if(propertyPaths != null) { \r
+\r
+               if(propertyPaths != null) {\r
                    rootPaths.addAll(propertyPaths);\r
                }\r
-               \r
+\r
                PolytomousKey polytomousKey = load(uuid, rootPaths);\r
                dao.loadNodes(polytomousKey.getRoot(),nodePaths);\r
                return polytomousKey;\r
        }\r
-       \r
+\r
        /**\r
         * Returns the polytomous key specified by the given <code>uuid</code>.\r
-        * The specified polytomous key either can be one of those stored in the CDM database or can be the \r
-        * DefaultFeatureTree (contains all Features in use). \r
-        * The uuid of the DefaultFeatureTree is defined in {@link IFeatureTreeService#DefaultFeatureTreeUuid}.\r
-        * The DefaultFeatureTree is also returned if no feature tree at all is stored in the cdm database.\r
-        *  \r
+        *\r
         * @see eu.etaxonomy.cdm.api.service.ServiceBase#load(java.util.UUID, java.util.List)\r
         */\r
        @Override\r
@@ -104,23 +96,101 @@ public class PolytomousKeyServiceImpl extends IdentifiableServiceBase<Polytomous
                return super.load(uuid, propertyPaths);\r
        }\r
 \r
-\r
-       /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.api.service.IPolytomousKeyService#findByTaxonomicScope(eu.etaxonomy.cdm.model.taxon.TaxonBase, java.lang.Class, java.lang.Integer, java.lang.Integer, java.util.List)\r
-        */\r
        @Override\r
        public Pager<PolytomousKey> findByTaxonomicScope(\r
                        TaxonBase taxon, Integer pageSize,\r
-                       Integer pageNumber, List<String> propertyPaths) {\r
-               \r
+                       Integer pageNumber, List<String> propertyPaths, List<String> nodePaths) {\r
+\r
                List<PolytomousKey> list = new ArrayList<PolytomousKey>();\r
-               taxon = taxonDao.findById(taxon.getId());\r
-               Integer numberOfResults = identificationKeyDao.countByTaxonomicScope(taxon, PolytomousKey.class).intValue();\r
+               Long numberOfResults = identificationKeyDao.countByTaxonomicScope(taxon.getUuid(), PolytomousKey.class);\r
                if(AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)){\r
-                       list = identificationKeyDao.findByTaxonomicScope(taxon, PolytomousKey.class, pageSize, pageNumber, propertyPaths);\r
+                       list = identificationKeyDao.findByTaxonomicScope(taxon.getUuid(), PolytomousKey.class, pageSize, pageNumber, propertyPaths);\r
+               }\r
+               if (nodePaths != null) {\r
+                       for (PolytomousKey polytomousKey : list) {\r
+                               dao.loadNodes(polytomousKey.getRoot(), nodePaths);\r
+                       }\r
                }\r
                Pager<PolytomousKey> pager = new DefaultPagerImpl<PolytomousKey>(pageNumber, numberOfResults, pageSize, list);\r
+\r
                return pager;\r
        }\r
-       \r
+\r
+       @Override\r
+       public UpdateResult updateAllNodeNumberings(UUID polytomousKeyUuid) {\r
+           UpdateResult result = new UpdateResult();\r
+           PolytomousKey polytomousKey = dao.load(polytomousKeyUuid);\r
+           polytomousKey.getRoot().refreshNodeNumbering();\r
+           return result;\r
+       }\r
+\r
+       @Override\r
+       public UpdateResult updateAllNodeNumberings() {\r
+           UpdateResult result = new UpdateResult();\r
+           List<PolytomousKey> polytomousKeys = dao.list();\r
+           for(PolytomousKey polytomousKey : polytomousKeys) {\r
+               polytomousKey.getRoot().refreshNodeNumbering();\r
+           }\r
+           return result;\r
+       }\r
+\r
+       @Override\r
+       public DeleteResult delete(PolytomousKey key){\r
+           //DeleteResult result = new DeleteResult();\r
+           PolytomousKeyNode root = key.getRoot();\r
+\r
+\r
+           DeleteResult result = isDeletable(key.getUuid(), null);\r
+           DeleteResult resultRoot = new DeleteResult();\r
+           if (result.isOk()){\r
+           try{\r
+               if (root != null){\r
+                  // root.setKey(null);\r
+                   resultRoot = nodeService.delete(root.getUuid(), true);\r
+\r
+               }\r
+           }catch(Exception e){\r
+               result.addException(e);\r
+               result.setAbort();\r
+               return result;\r
+           }\r
+           try{\r
+               if (resultRoot.isOk()){\r
+                   dao.delete(key);\r
+                   result.addDeletedObject(key);\r
+                   result.includeResult(resultRoot);\r
+               }\r
+           }catch(Exception e){\r
+                result.addException(e);\r
+                result.setAbort();\r
+                return result;\r
+            }\r
+           }\r
+        return result;\r
+       }\r
+\r
+       @Override\r
+    public DeleteResult isDeletable(UUID keyUuid, DeleteConfiguratorBase config){\r
+        DeleteResult result = new DeleteResult();\r
+        PolytomousKey key = this.load(keyUuid);\r
+        Set<CdmBase> references = commonService.getReferencingObjectsForDeletion(key);\r
+        if (references != null){\r
+           Iterator<CdmBase> iterator = references.iterator();\r
+           CdmBase ref;\r
+           while (iterator.hasNext()){\r
+               ref = iterator.next();\r
+               if ((ref instanceof PolytomousKeyNode) ){\r
+                   PolytomousKeyNode node = HibernateProxyHelper.deproxy(ref, PolytomousKeyNode.class);\r
+                   if (!node.getKey().equals(key)){\r
+                       String message = "The key is a subkey of " + node.getKey() + ", referenced in node with id: " + node.getId() + ". Please remove the subkey reference first and then delete the key. " ;\r
+                       result.addException(new ReferencedObjectUndeletableException(message));\r
+                       result.setAbort();\r
+                       result.addRelatedObject(ref);\r
+                   }\r
+               }\r
+           }\r
+        }\r
+        return result;\r
+    }\r
+\r
 }\r