import javax.persistence.FetchType;\r
import javax.persistence.ManyToOne;\r
import javax.persistence.OneToMany;\r
+import javax.persistence.Transient;\r
import javax.xml.bind.annotation.XmlAccessType;\r
import javax.xml.bind.annotation.XmlAccessorType;\r
import javax.xml.bind.annotation.XmlElement;\r
@XmlSchemaType(name = "IDREF")\r
@OneToMany(mappedBy="parent", fetch=FetchType.LAZY)\r
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})\r
- private List<TaxonNode> childNodes = new ArrayList<TaxonNode>();\r
+ private Set<TaxonNode> childNodes = new HashSet<TaxonNode>();\r
\r
@XmlElement(name = "reference")\r
@XmlIDREF\r
protected void setTaxonomicView(TaxonomicTree taxonomicTree) {\r
this.taxonomicTree = taxonomicTree;\r
}\r
- public List<TaxonNode> getChildNodes() {\r
+ public Set<TaxonNode> getChildNodes() {\r
return childNodes;\r
}\r
\r
* @return\r
*/\r
public boolean isRootNode(){\r
- return getParent() == null;\r
+ return parent == null;\r
}\r
\r
/**\r
* @param possibleParent\r
* @return true if this is a descendant\r
*/\r
+ @Transient\r
public boolean isDescendant(TaxonNode possibleParent){\r
return possibleParent.getAllNodes().contains(this);\r
}\r
\r
package eu.etaxonomy.cdm.model.taxon;\r
\r
+import java.util.ArrayList;\r
import java.util.HashSet;\r
+import java.util.List;\r
import java.util.Set;\r
\r
import javax.persistence.Entity;\r
import javax.persistence.ManyToOne;\r
import javax.persistence.OneToMany;\r
import javax.persistence.OneToOne;\r
+import javax.persistence.Transient;\r
import javax.xml.bind.annotation.XmlAccessType;\r
import javax.xml.bind.annotation.XmlAccessorType;\r
import javax.xml.bind.annotation.XmlElement;\r
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
import eu.etaxonomy.cdm.model.common.Language;\r
import eu.etaxonomy.cdm.model.common.LanguageString;\r
+import eu.etaxonomy.cdm.model.name.Rank;\r
import eu.etaxonomy.cdm.model.reference.ReferenceBase;\r
\r
/**\r
}\r
\r
\r
-\r
+ @Transient\r
public ReferenceBase getCitation() {\r
return reference;\r
}\r
* \r
* @return\r
*/\r
+ @Transient\r
@Deprecated\r
public Set<TaxonNode> getAllNodes() {\r
Set<TaxonNode> allNodes = new HashSet<TaxonNode>();\r
public int compareTo(Object o) {\r
return 0;\r
}\r
+ \r
+ /**\r
+ * Returns all TaxonNodes of the tree for a given Rank.\r
+ * If a branch does not contain a TaxonNode with a TaxonName at the given\r
+ * Rank the node associated with the next lower Rank is taken as root node.\r
+ * If the <code>rank</code> is null the absolute root nodes will be returned.\r
+ * \r
+ * @param rank may be null\r
+ * @return\r
+ */\r
+ public List<TaxonNode> getRankSpecificRootNodes(Rank rank) {\r
+ List<TaxonNode> baseNodes = new ArrayList<TaxonNode>();\r
+ if(rank != null){\r
+ findNodesForRank(rank, getRootNodes(), baseNodes);\r
+ } else {\r
+ baseNodes.addAll(getRootNodes());\r
+ }\r
+ return baseNodes;\r
+ }\r
+\r
+ /**\r
+ * findRankSpecificRootNodes\r
+ * @param rank\r
+ * @param nodeSet\r
+ * @param rootNodes\r
+ */\r
+ private List<TaxonNode> findNodesForRank(Rank rank, Set<TaxonNode> nodeSet, List<TaxonNode> rootNodes) {\r
+ for(TaxonNode node : nodeSet){\r
+ Rank thisRank = node.getTaxon().getName().getRank();\r
+ if(thisRank.isHigher(rank)){\r
+ // iterate deeper into tree\r
+ rootNodes.addAll(findNodesForRank(rank, node.getChildNodes(), rootNodes));\r
+ } else {\r
+ // gotsha! It is a base node of this level\r
+ rootNodes.add(node);\r
+ }\r
+ }\r
+ return rootNodes;\r
+ }\r
\r
}\r