Project

General

Profile

Download (8.14 KB) Statistics
| Branch: | Tag: | Revision:
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.Collections;
14
import java.util.Iterator;
15
import java.util.List;
16
import java.util.Set;
17

    
18
import org.apache.log4j.Logger;
19

    
20
import eu.etaxonomy.cdm.common.Tree;
21
import eu.etaxonomy.cdm.common.TreeNode;
22
import eu.etaxonomy.cdm.model.common.Language;
23
import eu.etaxonomy.cdm.model.description.Distribution;
24
import eu.etaxonomy.cdm.model.location.NamedArea;
25
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
26

    
27
/**
28
 * TODO javadoc.
29
 * 
30
 * There is a somehow similar implementation in {@link eu.etaxonomy.cdm.model.location.NamedArea} 
31
 */
32
public class DistributionTree extends Tree<Distribution>{
33

    
34
    public static final Logger logger = Logger.getLogger(DistributionTree.class);
35

    
36
    public DistributionTree(){
37
        NamedArea area = NamedArea.NewInstance();
38
        Distribution data = Distribution.NewInstance();
39
        data.setArea(area);
40
        data.putModifyingText(Language.ENGLISH(), "test");
41
        TreeNode<Distribution> rootElement = new TreeNode<Distribution>();
42
        List<TreeNode<Distribution>> children = new ArrayList<TreeNode<Distribution>>();
43

    
44
        rootElement.setData(data);
45
        rootElement.setChildren(children);
46
        setRootElement(rootElement);
47
    }
48

    
49
    public boolean containsChild(TreeNode<Distribution> root, TreeNode<Distribution> treeNode){
50
         boolean result = false;
51
         Iterator<TreeNode<Distribution>> it = root.getChildren().iterator();
52
         while (it.hasNext() && !result) {
53
             TreeNode<Distribution> node = it.next();
54
             if (node.getData().equalsForTree(treeNode.getData())) {
55
                 result = true;
56
             }
57
         }
58
         /*
59
         while (!result && it.hasNext()) {
60
              if (it.next().data.equalsForTree(treeNode.data)){
61
                  result = true;
62
              }
63
         }
64
         */
65
         return result;
66
     }
67

    
68
    public TreeNode<Distribution> getChild(TreeNode<Distribution> root, TreeNode<Distribution> TreeNode) {
69
        boolean found = false;
70
        TreeNode<Distribution> result = null;
71
        Iterator<TreeNode<Distribution>> it = root.children.iterator();
72
        while (!found && it.hasNext()) {
73
            result = it.next();
74
            if (result.data.equalsForTree(TreeNode.data)){
75
                found = true;
76
            }
77
        }
78
        if (!found){
79
            try {
80
                throw new Exception("The node was not found in among children and that is a precondition of getChild(node) method");
81
            } catch (Exception e) {
82
                e.printStackTrace();
83
            }
84
        }
85
        return result;
86
    }
87

    
88
    private List<Distribution> orderDistributionsByLevel(List<Distribution> distList){
89

    
90
        if(distList == null){
91
            distList = new ArrayList<Distribution>();
92
        }
93
        if(distList.size() == 0){
94
            return distList;
95
        }
96

    
97
        Distribution dist;
98
        List<Distribution> orderedList = new ArrayList<Distribution>(distList.size());
99
        orderedList.addAll(distList);
100

    
101
        int length = -1;
102
        boolean flag = true;
103
        for (int i = 0; i < length && flag; i++) {
104
            flag = false;
105
            for (int j = 0; j < length-1; j++) {
106
                String level1 = orderedList.get(j).getArea().getLevel().toString();
107
                String level2 = orderedList.get(j+1).getArea().getLevel().toString();
108
                //if level from j+1 is greater than level from j
109
                if (level2.compareTo(
110
                        level1) < 0) {
111
                    dist = orderedList.get(j);
112
                    orderedList.set(j, orderedList.get(j+1));
113
                    orderedList.set(j+1, dist);
114
                    flag = true;
115
                }
116
            }
117
        }
118
        return orderedList;
119
    }
120

    
121
    /**
122
     * @param distList
123
     * @param omitLevels
124
     */
125
    public void orderAsTree(List<Distribution> distList, Set<NamedAreaLevel> omitLevels){
126

    
127
        List<Distribution> orderedDistList = orderDistributionsByLevel(distList);
128

    
129
        for (Distribution distribution : orderedDistList) {
130
            // get path through area hierarchy
131
            List<NamedArea> namedAreaPath = getAreaLevelPath(distribution.getArea(), omitLevels);
132
            // order by merging
133
            mergeAux(distribution, namedAreaPath, this.getRootElement());
134
        }
135
    }
136

    
137
    public void sortChildren(){
138
        sortChildrenAux(this.getRootElement());
139
    }
140

    
141
    private void sortChildrenAux(TreeNode<Distribution> treeNode){
142
        DistributionNodeComparator comp = new DistributionNodeComparator();
143
        if (treeNode.children == null) {
144
            //nothing => stop condition
145
            return;
146
        }else {
147
            Collections.sort(treeNode.children, comp);
148
            for (TreeNode<Distribution> child : treeNode.children) {
149
                sortChildrenAux(child);
150
            }
151
        }
152
    }
153

    
154
    private void mergeAux(Distribution distributionElement, List<NamedArea> namedAreaPath, TreeNode<Distribution> root){
155

    
156
        TreeNode<Distribution> highestDistNode;
157
        TreeNode<Distribution> child;// the new child to add or the child to follow through the tree
158

    
159
         //if the list to merge is empty finish the execution
160
        if (namedAreaPath.isEmpty()) {
161
            return;
162
        }
163

    
164
        //getting the highest area and inserting it into the tree
165
        NamedArea highestArea = namedAreaPath.get(0);
166

    
167
        boolean isOnTop = false;
168
        if(distributionElement.getArea().getLevel() == null) {
169
            // is level is null compare by area only
170
//            isOnTop = distributionElement.getArea().getUuid().equals(highestArea.getUuid());
171
            isOnTop = false;
172
        } else {
173
            // otherwise compare by level
174
            isOnTop = highestArea.getLevel().getUuid().equals((distributionElement.getArea().getLevel().getUuid()));
175
        }
176

    
177
        if (isOnTop) {
178
            highestDistNode = new TreeNode<Distribution>(distributionElement); //distribution.area comes from proxy!!!!
179
        }else{
180
            //if distribution.status is not relevant
181
            Distribution dummyDistributionElement = Distribution.NewInstance(highestArea, null);
182
            highestDistNode = new TreeNode<Distribution>(dummyDistributionElement);
183
        }
184

    
185
        if (root.getChildren().isEmpty() || !containsChild(root, highestDistNode)) {
186
            //if the highest level is not on the depth-1 of the tree we add it.
187
            //child = highestDistNode;
188
            child = new TreeNode<Distribution>(highestDistNode.data);
189
            root.addChild(child);//child.getData().getArea().getUuid().toString().equals("8cfc1722-e1e8-49d3-95a7-9879de6de490");
190
        }else {
191
            //if the depth-1 of the tree contains the highest area level
192
            //get the subtree or create it in order to continuing merging
193
            child = getChild(root,highestDistNode);
194
        }
195
        //continue merging with the next highest area of the list.
196
        List<NamedArea> newList = namedAreaPath.subList(1, namedAreaPath.size());
197
        mergeAux(distributionElement, newList, child);
198
    }
199

    
200
    /**
201
     * @param area
202
     * @param omitLevels
203
     * @return the path through area hierarchy from the <code>area</code> given as parameter to the root
204
     */
205
    private List<NamedArea> getAreaLevelPath(NamedArea area, Set<NamedAreaLevel> omitLevels){
206
        List<NamedArea> result = new ArrayList<NamedArea>();
207
        if (omitLevels == null || !omitLevels.contains(area.getLevel())){
208
            result.add(area);
209
        }
210
        while (area.getPartOf() != null) {
211
            area = area.getPartOf();
212
            if (omitLevels == null || !omitLevels.contains(area.getLevel())){
213
                result.add(0, area);
214
            }
215
        }
216
        return result;
217
    }
218
}
(18-18/84)