implement list find method for user and group services (#2283 and #2284). Tests are...
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / DistributionTree.java
1 package eu.etaxonomy.cdm.api.service;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.Iterator;
6 import java.util.List;
7 import java.util.Set;
8
9 import eu.etaxonomy.cdm.common.Tree;
10 import eu.etaxonomy.cdm.common.TreeNode;
11 import eu.etaxonomy.cdm.model.common.Language;
12 import eu.etaxonomy.cdm.model.description.Distribution;
13 import eu.etaxonomy.cdm.model.location.NamedArea;
14 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
15
16 public class DistributionTree extends Tree<Distribution>{
17
18 public DistributionTree(){
19 NamedArea area = new NamedArea();
20 Distribution data = Distribution.NewInstance();
21 data.setArea(area);
22 data.putModifyingText(Language.ENGLISH(), "test");
23 TreeNode<Distribution> rootElement = new TreeNode<Distribution>();
24 List<TreeNode<Distribution>> children = new ArrayList<TreeNode<Distribution>>();
25
26 rootElement.setData(data);
27 rootElement.setChildren(children);
28 setRootElement(rootElement);
29 }
30
31 public boolean containsChild(TreeNode<Distribution> root, TreeNode<Distribution> treeNode){
32 boolean result = false;
33 Iterator<TreeNode<Distribution>> it = root.getChildren().iterator();
34 while (it.hasNext() && !result) {
35 TreeNode<Distribution> node = (TreeNode<Distribution>) it.next();
36 if (node.getData().equalsForTree(treeNode.getData())) {
37 result = true;
38 }
39 }
40 /*
41 while (!result && it.hasNext()) {
42 if (it.next().data.equalsForTree(treeNode.data)){
43 result = true;
44 }
45 }
46 */
47 return result;
48 }
49
50 public TreeNode<Distribution> getChild(TreeNode<Distribution> root, TreeNode<Distribution> TreeNode) {
51 boolean found = false;
52 TreeNode<Distribution> result = null;
53 Iterator<TreeNode<Distribution>> it = root.children.iterator();
54 while (!found && it.hasNext()) {
55 result = (TreeNode<Distribution>) it.next();
56 if (result.data.equalsForTree(TreeNode.data)){
57 found = true;
58 }
59 }
60 if (!found){
61 try {
62 throw new Exception("The node was not found in among children and that is a precondition of getChild(node) method");
63 } catch (Exception e) {
64 e.printStackTrace();
65 }
66 }
67 return result;
68 }
69
70 private List<Distribution> orderDistributionsByLevel(List<Distribution> distList){
71 boolean flag = true;
72 int length = distList.size()-1;
73 Distribution dist;
74 List<Distribution> orderedList = new ArrayList<Distribution>(length);
75 orderedList.addAll(distList);
76
77 for (int i = 0; i < length && flag; i++) {
78 flag = false;
79 for (int j = 0; j < length-1; j++) {
80 String level1 = orderedList.get(j).getArea().getLevel().toString();
81 String level2 = orderedList.get(j+1).getArea().getLevel().toString();
82 //if level from j+1 is greater than level from j
83 if (level2.compareTo(
84 level1) < 0) {
85 dist = orderedList.get(j);
86 orderedList.set(j, orderedList.get(j+1));
87 orderedList.set(j+1, dist);
88 flag = true;
89 }
90 }
91 }
92 return orderedList;
93 }
94
95 public void merge(List<Distribution> distList, Set<NamedAreaLevel> omitLevels){
96 List<Distribution> orderedDistList = orderDistributionsByLevel(distList);
97
98 for (Distribution distribution : orderedDistList) {
99 List<NamedArea> levelList =
100 this.getAreaLevelPathList(distribution.getArea(), omitLevels);
101 mergeAux(distribution, distribution.getArea().getLevel(), levelList, this.getRootElement());
102 }
103 }
104
105 public void sortChildren(){
106 sortChildrenAux(this.getRootElement());
107 }
108
109 private void sortChildrenAux(TreeNode<Distribution> treeNode){
110 DistributionNodeComparator comp = new DistributionNodeComparator();
111 if (treeNode.children == null) {
112 //nothing => stop condition
113 return;
114 }else {
115 Collections.sort(treeNode.children, comp);
116 for (TreeNode<Distribution> child : treeNode.children) {
117 sortChildrenAux(child);
118 }
119 }
120 }
121
122 private void mergeAux(Distribution distribution,
123 NamedAreaLevel level,
124 List<NamedArea> areaHierarchieList,
125 TreeNode<Distribution> root){
126 TreeNode<Distribution> highestDistNode;
127 TreeNode<Distribution> child;// the new child to add or the child to follow through the tree
128
129 //if the list to merge is empty finish the execution
130 if (areaHierarchieList.isEmpty()) {
131 return;
132 }
133 //getting the highest area and inserting it into the tree
134 NamedArea highestArea = areaHierarchieList.get(0);
135 //NamedAreaLevel highestAreaLevel = (NamedAreaLevel) HibernateProxyHelper.deproxy(highestArea.getLevel());
136 //NamedAreaLevel currentLevel = (NamedAreaLevel) HibernateProxyHelper.deproxy(level);
137 //if (highestAreaLevel.compareTo(currentLevel) == 0){//if distribution.status is relevant
138
139 if (highestArea.getLevel().getLabel().compareTo(level.getLabel()) == 0){
140 highestDistNode = new TreeNode<Distribution>(distribution);//distribution.area comes from proxy!!!!
141 }else{ //if distribution.status is not relevant
142 Distribution data = Distribution.NewInstance(highestArea, null);
143 highestDistNode = new TreeNode<Distribution>(data);
144 }
145 if(highestDistNode.data.getModifyingText().isEmpty()){
146 highestDistNode.data.putModifyingText(Language.ENGLISH(), "test");
147 }
148
149 if (root.getChildren().isEmpty() || !containsChild(root, highestDistNode)) {
150 //if the highest level is not on the depth-1 of the tree we add it.
151 //child = highestDistNode;
152 child = new TreeNode<Distribution>(highestDistNode.data);
153 root.addChild(child);//child.getData().getArea().getUuid().toString().equals("8cfc1722-e1e8-49d3-95a7-9879de6de490");
154 }else {
155 //if the deepth-1 of the tree contains the highest area level
156 //get the subtree or create it in order to continuing merging
157 child = getChild(root,highestDistNode);
158 }
159 //continue merging with the next highest area of the list.
160 List<NamedArea> newList = areaHierarchieList.subList(1, areaHierarchieList.size());
161 mergeAux(distribution, level, newList, child);
162 }
163
164 private List<NamedArea> getAreaLevelPathList(NamedArea area, Set<NamedAreaLevel> omitLevels){
165 List<NamedArea> result = new ArrayList<NamedArea>();
166 if (omitLevels == null || !omitLevels.contains(area.getLevel())){
167 result.add(area);
168 }
169 while (area.getPartOf() != null) {
170 area = area.getPartOf();
171 if (omitLevels == null || !omitLevels.contains(area.getLevel())){
172 result.add(0, area);
173 }
174 }
175 return result;
176 }
177 }