improving loadRankSpecificRootNodes
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / taxon / TaxonomicTree.java
index cf9b0112bdae76b37357398e626e9cfb9bd186bb..6fbe47eb4c444190619e9f4e92910abf4e7370c2 100644 (file)
@@ -17,6 +17,7 @@ import java.util.Set;
 \r
 import javax.persistence.Entity;\r
 import javax.persistence.FetchType;\r
+import javax.persistence.JoinColumn;\r
 import javax.persistence.ManyToOne;\r
 import javax.persistence.OneToMany;\r
 import javax.persistence.OneToOne;\r
@@ -34,6 +35,7 @@ import org.apache.log4j.Logger;
 import org.hibernate.annotations.Cascade;\r
 import org.hibernate.annotations.CascadeType;\r
 import org.hibernate.envers.Audited;\r
+import org.hibernate.search.annotations.IndexedEmbedded;\r
 \r
 import eu.etaxonomy.cdm.model.common.IReferencedEntity;\r
 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
@@ -57,15 +59,15 @@ import eu.etaxonomy.cdm.model.reference.ReferenceBase;
 @XmlRootElement(name = "TaxonomicTree")\r
 @Entity\r
 @Audited\r
-public class TaxonomicTree extends IdentifiableEntity implements IReferencedEntity{\r
+public class TaxonomicTree extends IdentifiableEntity implements IReferencedEntity, ITreeNode{\r
        private static final long serialVersionUID = -753804821474209635L;\r
        private static final Logger logger = Logger.getLogger(TaxonomicTree.class);\r
        \r
-       @XmlElement(name = "name")\r
-       @XmlIDREF\r
-       @XmlSchemaType(name = "IDREF")\r
+       @XmlElement(name = "Name")\r
        @OneToOne(fetch = FetchType.LAZY)\r
        @Cascade({CascadeType.SAVE_UPDATE})\r
+       @JoinColumn(name = "name_id", referencedColumnName = "id")\r
+       @IndexedEmbedded\r
        private LanguageString name;\r
        \r
 //     @XmlElementWrapper(name = "allNodes")\r
@@ -130,42 +132,96 @@ public class TaxonomicTree extends IdentifiableEntity implements IReferencedEnti
                super();\r
        }\r
        \r
-       \r
+\r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.model.taxon.ITreeNode#addChildNode(eu.etaxonomy.cdm.model.taxon.TaxonNode, eu.etaxonomy.cdm.model.reference.ReferenceBase, java.lang.String, eu.etaxonomy.cdm.model.taxon.Synonym)\r
+        */\r
+       public TaxonNode addChildNode(TaxonNode childNode, ReferenceBase citation,\r
+                       String microCitation, Synonym synonymToBeUsed) {\r
+               \r
+               rootNodes.add(childNode);\r
+               childNode.setParent(null);\r
+               childNode.setTaxonomicTree(this);\r
+               childNode.setReference(citation);\r
+               childNode.setMicroReference(microCitation);\r
+               childNode.setSynonymToBeUsed(synonymToBeUsed);\r
+               \r
+               return childNode;\r
+       }\r
+\r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.model.taxon.ITreeNode#addChildTaxon(eu.etaxonomy.cdm.model.taxon.Taxon, eu.etaxonomy.cdm.model.reference.ReferenceBase, java.lang.String, eu.etaxonomy.cdm.model.taxon.Synonym)\r
+        */\r
+       public TaxonNode addChildTaxon(Taxon taxon, ReferenceBase citation,\r
+                       String microCitation, Synonym synonymToBeUsed) {\r
+               return addChildNode(new TaxonNode(taxon), citation, microCitation, synonymToBeUsed);\r
+       }\r
        \r
        /**\r
         * Adds a taxon to the taxonomic tree and makes it one of the root nodes.\r
         * @param taxon\r
         * @param synonymUsed\r
         * @return\r
+        * @deprecated use addChildNode() or addChildTaxon() instead\r
         */\r
        public TaxonNode addRoot(Taxon taxon, Synonym synonymUsed, ReferenceBase reference){\r
                TaxonNode newRoot = new TaxonNode(taxon, this);\r
                rootNodes.add(newRoot);\r
                newRoot.setParent(null);\r
-               newRoot.setTaxonomicView(this);\r
+               newRoot.setTaxonomicTree(this);\r
                newRoot.setTaxon(taxon);\r
                newRoot.setReferenceForParentChildRelation(reference);\r
                newRoot.setSynonymToBeUsed(synonymUsed);\r
                return newRoot;\r
        }\r
        \r
-       public boolean removeRoot(TaxonNode node){\r
-               boolean result = false;\r
-               if(node.isRootNode()){\r
 \r
-                       for (TaxonNode childNode : node.getChildNodes()){\r
-                               node.removeChild(childNode);\r
-                       }\r
-                       result = rootNodes.remove(node);\r
-\r
-                       node.getTaxon().removeTaxonNode(node);\r
-                       node.setParent(null);\r
-                       node.setTaxonomicView(null);\r
-                       node.setTaxon(null);                    \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) {\r
+               boolean result = removeChildNode(node);\r
+               \r
+               node.getTaxon().removeTaxonNode(node);\r
+               node.setTaxon(null);    \r
+               \r
+               ArrayList<TaxonNode> childNodes = new ArrayList<TaxonNode>(node.getChildNodes()); \r
+               for (TaxonNode childNode : childNodes){\r
+                       node.deleteChildNode(childNode);\r
+               }\r
+               return result;\r
+       }\r
+       \r
+       /**\r
+        * \r
+        * @param node\r
+        * @return\r
+        */\r
+       protected boolean removeChildNode(TaxonNode node){\r
+               boolean result = false;\r
+               \r
+               if(!rootNodes.contains(node)){\r
+                       throw new IllegalArgumentException("TaxonNode is a not a root node of this taxonomic tree");\r
                }\r
+               \r
+               result = rootNodes.remove(node);\r
+\r
+               node.setParent(null);\r
+               node.setTaxonomicTree(null);\r
+               \r
                return result;\r
        }\r
        \r
+       /**\r
+        * \r
+        * @param node\r
+        * @return\r
+        * @deprecated use removeChildNode() instead\r
+        */\r
+       public boolean removeRoot(TaxonNode node){\r
+               return deleteChildNode(node);\r
+       }\r
+       \r
        /**\r
         * Appends an existing root node to another node of this tree. The existing root node becomes \r
         * an ordinary node.\r
@@ -189,8 +245,8 @@ public class TaxonomicTree extends IdentifiableEntity implements IReferencedEnti
                if (otherNode.equals(root)){\r
                        throw new IllegalArgumentException("root node and other node must not be the same");\r
                }\r
-               otherNode.addChildNote(root, ref, microReference, null);\r
-               getRootNodes().remove(root);\r
+               otherNode.addChildNode(root, ref, microReference, null);\r
+               //getRootNodes().remove(root);\r
        }\r
        \r
 //     public void makeThisNodePartOfOtherView(TaxonNode oldRoot, TaxonNode replacedNodeInOtherView, ReferenceBase reference, String microReference){\r
@@ -282,6 +338,13 @@ public class TaxonomicTree extends IdentifiableEntity implements IReferencedEnti
         * one parent. <Br>\r
         * If the parent-child relationship between these two taxa already exists nothing is changed. Only \r
         * citation and microcitation are overwritten by the new values if these values are not null.\r
+        * \r
+        * TODO this looks like very specialized functionality. Upon examination, it turned out that it is used\r
+        * solely in imports and it also looks like it is very tightly coupled with the way the imports are implemented.\r
+        * As an advocat for a clean API, I would very much recommend not having this in the library itself as I can \r
+        * not really see who else will be needing this.\r
+        * - n.hoffmann\r
+        * \r
         * @param parent\r
         * @param child\r
         * @param citation\r
@@ -299,8 +362,8 @@ public class TaxonomicTree extends IdentifiableEntity implements IReferencedEnti
                        //no multiple parents are allowed in the tree\r
                        if (childNode != null && childNode.getParent() != null){\r
                                //...different to the parent taxon  throw exception\r
-                               if (! childNode.getParent().getTaxon().equals(parent) ){\r
-                                       throw new IllegalStateException("The child taxon is already part of the tree but has an other parent taxon than the one than the parent to be added. Child: " + child.toString() + ", new parent:" + parent.toString() + ", old parent: " + childNode.getParent().getTaxon().toString()) ;\r
+                               if ((childNode.getParent() instanceof TaxonNode) && !((TaxonNode)childNode.getParent()).getTaxon().equals(parent) ){\r
+                                       throw new IllegalStateException("The child taxon is already part of the tree but has an other parent taxon than the one than the parent to be added. Child: " + child.toString() + ", new parent:" + parent.toString() + ", old parent: " + ((TaxonNode) childNode.getParent()).getTaxon().toString()) ;\r
                                //... same as the parent taxon do nothing but overwriting citation and microCitation\r
                                }else{\r
                                        handleCitationOverwrite(childNode, citation, microCitation);\r
@@ -310,12 +373,12 @@ public class TaxonomicTree extends IdentifiableEntity implements IReferencedEnti
                        \r
                        //add parent node if not exist\r
                        if (parentNode == null){\r
-                               parentNode = this.addRoot(parent, null, null);\r
+                               parentNode = this.addChildTaxon(parent, null, null, null);\r
                        }\r
                        \r
                        //add child if not exists\r
                        if (childNode == null){\r
-                               parentNode.addChild(child, citation, microCitation);\r
+                               parentNode.addChildTaxon(child, citation, microCitation, null);\r
                        }else{\r
                                //child is still root\r
                                //TODO test if child is rootNode otherwise thrwo IllegalStateException\r
@@ -355,12 +418,11 @@ public class TaxonomicTree extends IdentifiableEntity implements IReferencedEnti
         * @return\r
         */\r
        @Transient\r
-       @Deprecated\r
        public Set<TaxonNode> getAllNodes() {\r
                Set<TaxonNode> allNodes = new HashSet<TaxonNode>();\r
                \r
                for(TaxonNode rootNode : getRootNodes()){\r
-                       allNodes.addAll(rootNode.getAllNodes());\r
+                       allNodes.addAll(rootNode.getDescendants());\r
                }\r
                \r
                return allNodes;\r
@@ -417,7 +479,9 @@ public class TaxonomicTree extends IdentifiableEntity implements IReferencedEnti
         * \r
         * @param rank may be null\r
         * @return\r
+        * @deprecated use {@link ITaxonTreeService.loadRankSpecificRootNode} or {@link ITaxonomicTreeDao.loadRankSpecificRootNode} instead\r
         */\r
+       @Deprecated\r
        public List<TaxonNode> getRankSpecificRootNodes(Rank rank) {\r
                List<TaxonNode> baseNodes = new ArrayList<TaxonNode>();\r
                if(rank != null){\r
@@ -454,4 +518,10 @@ public class TaxonomicTree extends IdentifiableEntity implements IReferencedEnti
                return rootNodes;\r
        }\r
 \r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.model.taxon.ITreeNode#hasChildNodes()\r
+        */\r
+       public boolean hasChildNodes() {\r
+               return getRootNodes().size() > 0;\r
+       }\r
 }\r