remove deprecated method
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / DistributionTree.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.api.service;
11
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Set;
18
19 import org.apache.log4j.Logger;
20 import org.hibernate.proxy.HibernateProxy;
21 import org.hibernate.proxy.HibernateProxyHelper;
22
23 import eu.etaxonomy.cdm.common.Tree;
24 import eu.etaxonomy.cdm.common.TreeNode;
25 import eu.etaxonomy.cdm.model.description.Distribution;
26 import eu.etaxonomy.cdm.model.location.NamedArea;
27 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
28
29 /**
30 * TODO javadoc.
31 *
32 * There is a somehow similar implementation in {@link eu.etaxonomy.cdm.model.location.NamedArea}
33 */
34 public class DistributionTree extends Tree<Set<Distribution>, NamedArea>{
35
36 public static final Logger logger = Logger.getLogger(DistributionTree.class);
37
38 public DistributionTree(){
39 TreeNode<Set<Distribution>, NamedArea> rootElement = new TreeNode<Set<Distribution>, NamedArea>();
40 List<TreeNode<Set<Distribution>, NamedArea>> children = new ArrayList<TreeNode<Set<Distribution>, NamedArea>>();
41 rootElement.setChildren(children);
42 setRootElement(rootElement);
43 }
44
45 /**
46 * @param parentNode
47 * @param nodeToFind
48 * @return false if the node was not found
49 */
50 public boolean hasChildNode(TreeNode<Set<Distribution>, NamedArea> parentNode, NamedArea nodeID) {
51 return findChildNode(parentNode, nodeID) != null;
52 }
53
54 /**
55 * @param parentNode
56 * @param nodeToFind
57 * @return the found node or null
58 */
59 public TreeNode<Set<Distribution>, NamedArea> findChildNode(TreeNode<Set<Distribution>, NamedArea> parentNode, NamedArea nodeID) {
60 if (parentNode.getChildren() == null) {
61 return null;
62 }
63
64 for (TreeNode<Set<Distribution>, NamedArea> node : parentNode.getChildren()) {
65 if (node.getNodeId().equals(nodeID)) {
66 return node;
67 }
68 }
69 return null;
70 }
71
72 /**
73 * @param distList
74 * @param omitLevels
75 */
76 public void orderAsTree(Collection<Distribution> distList, Set<NamedAreaLevel> omitLevels){
77
78 for (Distribution distribution : distList) {
79 // get path through area hierarchy
80 List<NamedArea> namedAreaPath = getAreaLevelPath(distribution.getArea(), omitLevels);
81 addDistributionToSubTree(distribution, namedAreaPath, this.getRootElement());
82 }
83 }
84
85 public void recursiveSortChildrenByLabel(){
86 _recursiveSortChildrenByLabel(this.getRootElement());
87 }
88
89 private void _recursiveSortChildrenByLabel(TreeNode<Set<Distribution>, NamedArea> treeNode){
90 DistributionNodeByAreaLabelComparator comp = new DistributionNodeByAreaLabelComparator();
91 if (treeNode.children == null) {
92 //nothing => stop condition
93 return;
94 }else {
95 Collections.sort(treeNode.children, comp);
96 for (TreeNode<Set<Distribution>, NamedArea> child : treeNode.children) {
97 _recursiveSortChildrenByLabel(child);
98 }
99 }
100 }
101
102 /**
103 * Adds the given <code>distributionElement</code> to the sub tree defined by
104 * the <code>root</code>.
105 *
106 * @param distribution
107 * the {@link Distribution} to add to the tree at the position
108 * according to the NamedArea hierarchy.
109 * @param namedAreaPath
110 * the path to the root of the NamedArea hierarchy starting the
111 * area used in the given <code>distributionElement</code>. The
112 * hierarchy is defined by the {@link NamedArea#getPartOf()}
113 * relationships
114 * @param root
115 * root element of the sub tree to which the
116 * <code>distributionElement</code> is to be added
117 */
118 private void addDistributionToSubTree(Distribution distribution, List<NamedArea> namedAreaPath, TreeNode<Set<Distribution>, NamedArea> root){
119
120
121 //if the list to merge is empty finish the execution
122 if (namedAreaPath.isEmpty()) {
123 return;
124 }
125
126 //getting the highest area and inserting it into the tree
127 NamedArea highestArea = namedAreaPath.get(0);
128
129
130 TreeNode<Set<Distribution>, NamedArea> child = findChildNode(root, highestArea);
131 if (child == null) {
132 // the highestDistNode is not yet in the set of children, so we add it
133 child = new TreeNode<Set<Distribution>, NamedArea>(highestArea);
134 child.setData(new HashSet<Distribution>());
135 root.addChild(child);
136 }
137
138 // add another element to the list of data
139 if(namedAreaPath.get(0).equals(distribution.getArea())){
140 if(namedAreaPath.size() > 1){
141 logger.error("there seems to be something wrong with the area hierarchy");
142 }
143 child.getData().add(distribution);
144 return; // done!
145 }
146
147 // Recursively proceed into the namedAreaPath to merge the next node
148 List<NamedArea> newList = namedAreaPath.subList(1, namedAreaPath.size());
149 addDistributionToSubTree(distribution, newList, child);
150 }
151
152
153 /**
154 * @param area
155 * @param omitLevels
156 * @return the path through area hierarchy from the <code>area</code> given as parameter to the root
157 */
158 private List<NamedArea> getAreaLevelPath(NamedArea area, Set<NamedAreaLevel> omitLevels){
159 List<NamedArea> result = new ArrayList<NamedArea>();
160 if (omitLevels == null || !omitLevels.contains(area.getLevel())){
161 result.add(area);
162 }
163 // logging special case in order to help solving ticket #3891 (ordered distributions provided by portal/description/${uuid}/DistributionTree randomly broken)
164
165 if(area.getPartOf() == null) {
166 StringBuilder hibernateInfo = new StringBuilder();
167 hibernateInfo.append(", area is of type: ").append(area.getClass());
168 if(area instanceof HibernateProxy){
169 hibernateInfo.append(" target object is ").append(HibernateProxyHelper.getClassWithoutInitializingProxy(area));
170 }
171 logger.warn("area.partOf is NULL for " + area.getLabel() + hibernateInfo.toString());
172 }
173 while (area.getPartOf() != null) {
174 area = area.getPartOf();
175 if (omitLevels == null || !omitLevels.contains(area.getLevel())){
176 result.add(0, area);
177 }
178 }
179
180
181 return result;
182 }
183 }