some changes for object deletion, especially the implementation of the childhandling.
authorKatja Luther <k.luther@bgbm.org>
Tue, 23 Jul 2013 09:17:00 +0000 (09:17 +0000)
committerKatja Luther <k.luther@bgbm.org>
Tue, 23 Jul 2013 09:17:00 +0000 (09:17 +0000)
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/TaxonNameBase.java
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Classification.java
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/Taxon.java
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/TaxonNode.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/NameServiceImpl.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/TaxonServiceImplTest.java
cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/BlankDataSet.xml

index 93e7da432a30aaaabde9872904e9f049876a5f0f..f27778152a6dee8eca437362e38a96971e4d208b 100644 (file)
@@ -647,6 +647,24 @@ public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INam
         }
         return false;
     }
         }
         return false;
     }
+    
+    /**
+     * Indicates <i>this</i> taxon name is a {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonym}
+     * of any other taxon name. Returns "true", if a replaced
+     * synonym {@link NameRelationship relationship} from <i>this</i> taxon name to another taxon name exists,
+     * false otherwise (also in case <i>this</i> taxon name is the only one in the
+     * homotypical group).
+     */
+    @Transient
+    public boolean isReplacedSynonym(){
+        Set<NameRelationship> relationsFromThisName = this.getRelationsFromThisName();
+        for (NameRelationship relation : relationsFromThisName) {
+            if (relation.getType().isReplacedSynonymRelation()) {
+                return true;
+            }
+        }
+        return false;
+    }
 
     /**
      * Returns the taxon name which is the {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name.
 
     /**
      * Returns the taxon name which is the {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name.
@@ -724,6 +742,23 @@ public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INam
             return null;
         }
     }
             return null;
         }
     }
+    
+    /**
+     * Returns the set of taxon names which are the {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonyms} of <i>this</i> taxon name.
+     *  
+     */
+    @Transient
+    public Set<TaxonNameBase> getReplacedSynonyms(){
+        Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
+        Set<NameRelationship> rels = this.getRelationsToThisName();
+        for (NameRelationship rel : rels){
+            if (rel.getType().isReplacedSynonymRelation()){
+                TaxonNameBase replacedSynonym = rel.getFromName();
+                result.add(replacedSynonym);
+            }
+        }
+        return result;
+    }
 
     /**
      * Assigns a taxon name as {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonym} of <i>this</i> taxon name
 
     /**
      * Assigns a taxon name as {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonym} of <i>this</i> taxon name
index b08a8f0938025c420faacae4cae5c8cc700d1e11..09752d61a1a69a57397d3e46ef594d062962d883 100644 (file)
@@ -168,6 +168,23 @@ public class Classification extends IdentifiableEntity implements IReferencedEnt
                return result;\r
        }\r
        \r
                return result;\r
        }\r
        \r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.model.taxon.ITreeNode#removeChildNode(eu.etaxonomy.cdm.model.taxon.TaxonNode)\r
+        */\r
+       public boolean deleteChildNode(TaxonNode node, boolean deleteChildren) {\r
+               boolean result = removeChildNode(node);\r
+               \r
+               //node.getTaxon().removeTaxonNode(node);\r
+               node.setTaxon(null);    \r
+               if (deleteChildren){\r
+                       ArrayList<TaxonNode> childNodes = new ArrayList<TaxonNode>(node.getChildNodes()); \r
+                       for (TaxonNode childNode : childNodes){\r
+                               node.deleteChildNode(childNode);\r
+                       }\r
+               }\r
+               return result;\r
+       }\r
+       \r
        /**\r
         * \r
         * @param node\r
        /**\r
         * \r
         * @param node\r
index d63bfedac070f5d2513ff381b465a0c6aac4abd3..80a768d6fa1a24eb906cad126b6eced7bf5d9d77 100644 (file)
@@ -306,35 +306,63 @@ public class Taxon extends TaxonBase<IIdentifiableEntityCacheStrategy<Taxon>> im
         taxonNodes.add(taxonNode);
     }
     public void removeTaxonNode(TaxonNode taxonNode){
         taxonNodes.add(taxonNode);
     }
     public void removeTaxonNode(TaxonNode taxonNode){
-        taxonNodes.remove(taxonNode);
+        TaxonNode parent = taxonNode.getParent();
+        if (parent != null){
+               parent.removeChildNode(taxonNode);
+        }
+       taxonNodes.remove(taxonNode);
+        
+    }
+    
+    public void removeTaxonNode(TaxonNode taxonNode, boolean deleteChildren){
+       TaxonNode parent = taxonNode.getParent();
+       //taxonNode.setTaxon(null);
+               if ((!taxonNode.getChildNodes().isEmpty() && deleteChildren) || (taxonNode.getChildNodes().isEmpty()) ){
+                       
+                       taxonNode.delete();
+                       
+               } else if (!taxonNode.isTopmostNode()){
+                       Set<TaxonNode> children = taxonNode.getChildNodes();
+                       Iterator<TaxonNode> childrenIterator = children.iterator();
+                       while (childrenIterator.hasNext()){
+                               TaxonNode childNode = childrenIterator.next();
+                               childrenIterator.remove();
+                               parent.addChildNode(childNode, null, null, null);
+                               
+                       }       
+                       //parent.removeChildNode(taxonNode);
+                       taxonNode.delete();
+               } else if (taxonNode.isTopmostNode()){
+                       
+               }
+               
     }
     
     public void removeTaxonNodes(boolean deleteChildren){
        Iterator<TaxonNode> nodesIterator = taxonNodes.iterator();
        TaxonNode node;
     }
     
     public void removeTaxonNodes(boolean deleteChildren){
        Iterator<TaxonNode> nodesIterator = taxonNodes.iterator();
        TaxonNode node;
+       TaxonNode parent;
        while (nodesIterator.hasNext()){
                node = nodesIterator.next();
        while (nodesIterator.hasNext()){
                node = nodesIterator.next();
-               TaxonNode parent = node.getParent();
-               if ((!node.getChildNodes().isEmpty() && deleteChildren) || (node.getChildNodes().isEmpty())){
-                       node.setTaxon(null);
-               } else if (!node.isTopmostNode()){
+               if (!deleteChildren){
                        Set<TaxonNode> children = node.getChildNodes();
                        Iterator<TaxonNode> childrenIterator = children.iterator();
                        Set<TaxonNode> children = node.getChildNodes();
                        Iterator<TaxonNode> childrenIterator = children.iterator();
+                       parent = node.getParent();
                        while (childrenIterator.hasNext()){
                                TaxonNode childNode = childrenIterator.next();
                                childrenIterator.remove();
                                parent.addChildNode(childNode, null, null, null);
                        while (childrenIterator.hasNext()){
                                TaxonNode childNode = childrenIterator.next();
                                childrenIterator.remove();
                                parent.addChildNode(childNode, null, null, null);
-                               node.setTaxon(null);
                                
                                
-                       }
-               } else {
-                       //what to do if the node is topmost node??
-               }
-               if (!node.isTopmostNode()){
-                       parent.removeChildNode(node);
+                       }       
+                       
+                       
                }
                }
+               
+               node.delete(deleteChildren);
+               node.setTaxon(null);
+                       nodesIterator.remove();
        }
        }
-       taxonNodes = null;
+       
     }
 
 
     }
 
 
index 1451932ed7a5a843f097905b8f7ab47238a4bf6b..77a8cc3e708e4f9c848a9fa996a183699412742f 100644 (file)
@@ -208,8 +208,8 @@ public class TaxonNode extends AnnotatableEntity implements ITreeNode, Cloneable
      */\r
     public boolean deleteChildNode(TaxonNode node) {\r
         boolean result = removeChildNode(node);\r
      */\r
     public boolean deleteChildNode(TaxonNode node) {\r
         boolean result = removeChildNode(node);\r
-\r
-        node.getTaxon().removeTaxonNode(node);\r
+        Taxon taxon = node.getTaxon();\r
+        taxon.removeTaxonNode(node);\r
         node.setTaxon(null);\r
 \r
         ArrayList<TaxonNode> childNodes = new ArrayList<TaxonNode>(node.getChildNodes());\r
         node.setTaxon(null);\r
 \r
         ArrayList<TaxonNode> childNodes = new ArrayList<TaxonNode>(node.getChildNodes());\r
@@ -217,6 +217,31 @@ public class TaxonNode extends AnnotatableEntity implements ITreeNode, Cloneable
             node.deleteChildNode(childNode);\r
         }\r
 \r
             node.deleteChildNode(childNode);\r
         }\r
 \r
+//             // two iterations because of ConcurrentModificationErrors\r
+//        Set<TaxonNode> removeNodes = new HashSet<TaxonNode>();\r
+//        for (TaxonNode grandChildNode : node.getChildNodes()) {\r
+//                removeNodes.add(grandChildNode);\r
+//        }\r
+//        for (TaxonNode childNode : removeNodes) {\r
+//                childNode.deleteChildNode(node);\r
+//        }\r
+\r
+        return result;\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see eu.etaxonomy.cdm.model.taxon.ITreeNode#removeChildNode(eu.etaxonomy.cdm.model.taxon.TaxonNode)\r
+     */\r
+    public boolean deleteChildNode(TaxonNode node, boolean deleteChildren) {\r
+        boolean result = removeChildNode(node);\r
+               \r
+        if (deleteChildren){\r
+               ArrayList<TaxonNode> childNodes = new ArrayList<TaxonNode>(node.getChildNodes());\r
+               for(TaxonNode childNode : childNodes){\r
+                   node.deleteChildNode(childNode);\r
+               }\r
+        }\r
+\r
 //             // two iterations because of ConcurrentModificationErrors\r
 //        Set<TaxonNode> removeNodes = new HashSet<TaxonNode>();\r
 //        for (TaxonNode grandChildNode : node.getChildNodes()) {\r
 //             // two iterations because of ConcurrentModificationErrors\r
 //        Set<TaxonNode> removeNodes = new HashSet<TaxonNode>();\r
 //        for (TaxonNode grandChildNode : node.getChildNodes()) {\r
@@ -270,6 +295,19 @@ public class TaxonNode extends AnnotatableEntity implements ITreeNode, Cloneable
             return getParent().deleteChildNode(this);\r
         }\r
     }\r
             return getParent().deleteChildNode(this);\r
         }\r
     }\r
+    \r
+    /**\r
+     * Remove this taxonNode From its taxonomic parent\r
+     *\r
+     * @return true on success\r
+     */\r
+    public boolean delete(boolean deleteChildren){\r
+        if(isTopmostNode()){\r
+            return classification.deleteChildNode(this, deleteChildren);\r
+        }else{\r
+            return getParent().deleteChildNode(this, deleteChildren);\r
+        }\r
+    }\r
 \r
 //*********** GETTER / SETTER ***********************************/\r
 \r
 \r
 //*********** GETTER / SETTER ***********************************/\r
 \r
index d72f20488ffa7b9f020123c5a738642e17c2862c..6c5995d0c0bca2dbb0d42c28159930627922f41e 100644 (file)
@@ -144,7 +144,7 @@ public class NameServiceImpl extends IdentifiableServiceBase<TaxonNameBase,ITaxo
         //check if this name is still used somewhere\r
 \r
         //name relationships\r
         //check if this name is still used somewhere\r
 \r
         //name relationships\r
-        if (! name.getNameRelations().isEmpty()){\r
+        if (! name.getNameRelations().isEmpty() && !config.isRemoveAllNameRelationships()){\r
             String message = "Name can't be deleted as it is used in name relationship(s). Remove name relationships prior to deletion.";\r
             throw new ReferencedObjectUndeletableException(message);\r
 //                     return null;\r
             String message = "Name can't be deleted as it is used in name relationship(s). Remove name relationships prior to deletion.";\r
             throw new ReferencedObjectUndeletableException(message);\r
 //                     return null;\r
@@ -206,6 +206,25 @@ public class NameServiceImpl extends IdentifiableServiceBase<TaxonNameBase,ITaxo
         }\r
 \r
         //TODO inline references\r
         }\r
 \r
         //TODO inline references\r
+             \r
+       if (!config.isIgnoreIsBasionymFor() && name.isGroupsBasionym()){\r
+               String message = "Name can't be deleted as it is a basionym.";\r
+            throw new ReferencedObjectUndeletableException(message);\r
+       }\r
+       if (!config.isIgnoreHasBasionym() && (name.getBasionyms().size()>0)){\r
+               String message = "Name can't be deleted as it has a basionym.";\r
+            throw new ReferencedObjectUndeletableException(message);\r
+       }\r
+       if (!config.isIgnoreIsReplacedSynonymFor() && name.isReplacedSynonym()){\r
+               String message = "Name can't be deleted as it is a replaced synonym.";\r
+            throw new ReferencedObjectUndeletableException(message);\r
+       }\r
+       if (!config.isIgnoreHasReplacedSynonym() && (name.getReplacedSynonyms().size()>0)){\r
+               String message = "Name can't be deleted as it has a replaced synonym.";\r
+            throw new ReferencedObjectUndeletableException(message);\r
+       }\r
+       \r
+    \r
 \r
         dao.delete(name);\r
         return name.getUuid();\r
 \r
         dao.delete(name);\r
         return name.getUuid();\r
index d46461946de1d4d0c3ba2e9aae66ae0c3efc9306..205e263d48dd954e855a2785652b7b74aa8e81b8 100644 (file)
@@ -919,34 +919,35 @@ public class TaxonServiceImpl extends IdentifiableServiceBase<TaxonBase,ITaxonDa
         }\r
 \r
             //         TaxonNode\r
         }\r
 \r
             //         TaxonNode\r
-            if (! config.isDeleteTaxonNodes()){\r
+            if (! config.isDeleteTaxonNodes() || (!config.isDeleteInAllClassifications() && classification == null )){\r
                 if (taxon.getTaxonNodes().size() > 0){\r
                 if (taxon.getTaxonNodes().size() > 0){\r
-                    String message = "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion.";\r
+                    String message = "Taxon can't be deleted as it is used in a classification node. Remove taxon from all classifications prior to deletion or define a classification where it should be deleted or adapt the taxon deletion configurator.";\r
                     throw new ReferencedObjectUndeletableException(message);\r
                 }\r
             }else{\r
                Set<TaxonNode> nodes = taxon.getTaxonNodes();\r
                Iterator<TaxonNode> iterator = nodes.iterator();\r
                     throw new ReferencedObjectUndeletableException(message);\r
                 }\r
             }else{\r
                Set<TaxonNode> nodes = taxon.getTaxonNodes();\r
                Iterator<TaxonNode> iterator = nodes.iterator();\r
-               TaxonNode node;\r
-               if (config.isDeleteInAllClassifications()){\r
-                       boolean deleteChildren;\r
-                       if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)){\r
-                               deleteChildren = true;\r
-                       }else {\r
-                               deleteChildren = false;\r
-                       }\r
-               \r
-                       taxon.removeTaxonNodes(deleteChildren);\r
-               }else {\r
+               TaxonNode node = null;\r
+               boolean deleteChildren;\r
+                       if (config.getTaxonNodeConfig().getChildHandling().equals(ChildHandling.DELETE)){\r
+                               deleteChildren = true;\r
+                       }else {\r
+                               deleteChildren = false;\r
+                       }\r
+               if (!config.isDeleteInAllClassifications() && !(classification == null)){\r
                        while (iterator.hasNext()){\r
                                node = iterator.next();\r
                                if (node.getClassification().equals(classification)){\r
                        while (iterator.hasNext()){\r
                                node = iterator.next();\r
                                if (node.getClassification().equals(classification)){\r
-                                       node.delete();\r
-                                       return;\r
+                                       break;\r
                                }\r
                                }\r
+                               node = null;\r
                        }\r
                        }\r
-               }\r
-               \r
+                       if (node != null){\r
+                               taxon.removeTaxonNode(node, deleteChildren);\r
+                       }\r
+               } else if (config.isDeleteInAllClassifications()){\r
+                       taxon.removeTaxonNodes(deleteChildren);\r
+               } \r
                \r
             }\r
 \r
                \r
             }\r
 \r
@@ -1039,7 +1040,12 @@ public class TaxonServiceImpl extends IdentifiableServiceBase<TaxonBase,ITaxonDa
                         }\r
                     }\r
                 }\r
                         }\r
                     }\r
                 }\r
-            dao.delete(taxon);\r
+            if (taxon.getTaxonNodes() == null || taxon.getTaxonNodes().size()== 0){\r
+               dao.delete(taxon);\r
+            } else{\r
+               String message = "Taxon can't be deleted as it is used in a Taxonnode";\r
+                    throw new ReferencedObjectUndeletableException(message);\r
+            }\r
             \r
 \r
     }\r
             \r
 \r
     }\r
index 06e9892f707d283e719a9e6ffb4782120439d3e0..f6beeabf69a857ca4729ba37bc79b2482d5616ad 100644 (file)
@@ -1055,6 +1055,7 @@ public class TaxonServiceImplTest extends CdmTransactionalIntegrationTest {
        @Test\r
        @DataSet(value="BlankDataSet.xml")\r
        public final void testDeleteTaxonNameUsedInTwoClassificationsDeleteAllNodes(){\r
        @Test\r
        @DataSet(value="BlankDataSet.xml")\r
        public final void testDeleteTaxonNameUsedInTwoClassificationsDeleteAllNodes(){\r
+               commitAndStartNewTransaction(null);\r
                TaxonDeletionConfigurator config = new TaxonDeletionConfigurator();\r
                //create a small classification\r
                Taxon testTaxon = TaxonGenerator.getTestTaxon();\r
                TaxonDeletionConfigurator config = new TaxonDeletionConfigurator();\r
                //create a small classification\r
                Taxon testTaxon = TaxonGenerator.getTestTaxon();\r
@@ -1112,7 +1113,7 @@ public class TaxonServiceImplTest extends CdmTransactionalIntegrationTest {
                                e.printStackTrace();\r
                        }\r
                                \r
                                e.printStackTrace();\r
                        }\r
                                \r
-               commitAndStartNewTransaction(null);\r
+               //commitAndStartNewTransaction(null);\r
                Taxon tax = (Taxon)service.find(uuid);\r
                assertNotNull(tax);\r
                Taxon childTaxon = (Taxon)service.find(childUUID);\r
                Taxon tax = (Taxon)service.find(uuid);\r
                assertNotNull(tax);\r
                Taxon childTaxon = (Taxon)service.find(childUUID);\r
index 32520e54b64a527f93c10691ab55fb279a2b91d1..d4209032810921e85b2c69ab52324f5f442a1926 100644 (file)
@@ -4,5 +4,6 @@
 <NAMERELATIONSHIP/>\r
 <TAXONNAMEBASE/>\r
 <TAXONBASE/>\r
 <NAMERELATIONSHIP/>\r
 <TAXONNAMEBASE/>\r
 <TAXONBASE/>\r
+<TAXONNODE/>\r
 </dataset>\r
 \r
 </dataset>\r
 \r