Project

General

Profile

Download (6.04 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2016 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
package eu.etaxonomy.cdm.model.common;
10

    
11
import java.util.ArrayList;
12
import java.util.Collection;
13
import java.util.Collections;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.regex.Pattern;
18

    
19
import eu.etaxonomy.cdm.model.description.FeatureNode;
20
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
21

    
22
/**
23
 * A class to handle tree indexes as used in {@link TaxonNode}, {@link FeatureNode}
24
 * etc.<BR>
25
 * Might be come a hibernate user type in future.
26
 *
27
 * @author a.mueller
28
 * @since 02.12.2016
29
 *
30
 */
31
public class TreeIndex {
32

    
33
    public static TreeIndex NewInstance(String treeIndex){
34
        return new TreeIndex(treeIndex);
35
    }
36

    
37

    
38
    /**
39
     * @param subtree
40
     * @return
41
     */
42
    public static TreeIndex NewInstance(TaxonNode node) {
43
        if (node == null){
44
            return null;
45
        }else{
46
            return new TreeIndex(node.treeIndex());
47
        }
48
    }
49

    
50

    
51
    /**
52
     * @param stringList
53
     * @return
54
     */
55
    public static List<TreeIndex> NewListInstance(List<String> stringList) {
56
        List<TreeIndex> result = new ArrayList<>();
57
        for (String string: stringList){
58
            result.add(new TreeIndex(string));
59
        }
60
        return result;
61
    }
62

    
63
    //regEx, we also allow the tree itself to have a tree index (e.g. #t1#)
64
    //this may change in future as not necessarily needed
65
    private static String regEx = "#[a-z](\\d+#)+";
66
    private static Pattern pattern = Pattern.compile(regEx);
67

    
68
    private static TreeIndexComparator comparator = new TreeIndexComparator();
69

    
70
    private String treeIndex;
71

    
72
    private TreeIndex(String treeIndex){
73
        if (! pattern.matcher(treeIndex).matches()){
74
            throw new IllegalArgumentException("Given string is not a valid tree index");
75
        }
76
        this.treeIndex = treeIndex;
77
    }
78

    
79
// ************** METHODS ***************************************/
80

    
81
    /**
82
     * @param taxonTreeIndex
83
     * @return
84
     */
85
    public boolean hasChild(TreeIndex childCandidateTreeIndex) {
86
        return childCandidateTreeIndex.treeIndex.startsWith(treeIndex);
87
    }
88

    
89

    
90
    /**
91
     * Returns a new TreeIndex instance which represents the parent of this tree index.
92
     * Returns null if this tree index already represents the root node of the tree.
93
     * @return
94
     */
95
    public TreeIndex parent(){
96
        int index = treeIndex.substring(0, treeIndex.length()-1).lastIndexOf(ITreeNode.separator);
97
        try {
98
            TreeIndex result = index < 0 ? null : NewInstance(treeIndex.substring(0, index+1));
99
            return result;
100
        } catch (Exception e) {
101
            //it is not a valid treeindex anymore
102
            return null;
103
        }
104
    }
105

    
106
    public boolean isTreeRoot(){
107
        int count = 0;
108
        for (char c : this.treeIndex.toCharArray()){
109
            if (c == '#') {
110
                count++;
111
            }
112
        }
113
        return count == 3;
114
    }
115

    
116
    public boolean isTree(){
117
        int count = 0;
118
        for (char c : this.treeIndex.toCharArray()){
119
            if (c == '#') {
120
                count++;
121
            }
122
        }
123
        return count == 2;
124
    }
125

    
126
// ********************** STATIC METHODS  *****************************/
127

    
128
    /**
129
     * Creates a list for the given tree indexes and sorts them in ascending
130
     * order.
131
     * @param treeIndexSet
132
     * @return
133
     */
134
    public static List<TreeIndex> sort(Collection<TreeIndex> treeIndexSet) {
135
        List<TreeIndex> result = new ArrayList<>(treeIndexSet);
136
        Collections.sort(result, comparator);
137
        return result;
138
    }
139

    
140

    
141
    /**
142
     * Creates a list for the given tree indexes and sorts them in descending
143
     * order.
144
     * @param treeIndexSet
145
     * @return
146
     */
147
    public static List<TreeIndex> sortDesc(Collection<TreeIndex> treeIndexSet) {
148
        List<TreeIndex> result = sort(treeIndexSet);
149
        Collections.reverse(result);
150
        return result;
151
    }
152

    
153
    public static Map<TreeIndex, TreeIndex> group(Collection<TreeIndex> groupingIndexes, Collection<TreeIndex> toBeGroupedIndexes){
154

    
155
        //for larger groupingIndexes we could optimize this by sorting both collections
156
        //prior to loop. This way we do traverse both lists once
157
        Map<TreeIndex, TreeIndex> result = new HashMap<>();
158
        List<TreeIndex> descSortedGroupingIndexes = sortDesc(groupingIndexes);
159

    
160
        for (TreeIndex toBeGrouped : toBeGroupedIndexes) {
161
            boolean groupFound = false;
162
            for (TreeIndex groupingIndex : descSortedGroupingIndexes){
163
                if (groupingIndex.hasChild(toBeGrouped)){
164
                    result.put(toBeGrouped, groupingIndex);
165
                    groupFound = true;
166
                    break;
167
                }
168
            }
169
            if (!groupFound){
170
                result.put(toBeGrouped, null);
171
            }
172
        }
173
        return result;
174
    }
175

    
176

    
177
// **************************** EQUALS *****************************/
178

    
179
    @Override
180
    public int hashCode() {
181
        return treeIndex.hashCode();
182
    }
183

    
184
    @Override
185
    public boolean equals(Object obj) {
186
        if (obj instanceof TreeIndex){
187
            return treeIndex.equals(((TreeIndex)obj).treeIndex);
188
        }else{
189
            return false;
190
        }
191
    }
192

    
193
// *************************** toString() ***********************
194

    
195

    
196

    
197
    @Override
198
    public String toString(){
199
        return treeIndex;
200
    }
201

    
202
    /**
203
     * Null save toString method.
204
     * @param treeIndex
205
     * @return
206
     */
207
    public static String toString(TreeIndex treeIndex) {
208
        return treeIndex == null? null: treeIndex.toString();
209
    }
210

    
211

    
212
    /**
213
     * @param treeIndexes
214
     * @return
215
     */
216
    public static List<String> toString(Collection<TreeIndex> treeIndexes) {
217
        List<String> result = new ArrayList<>();
218
        for (TreeIndex treeIndex : treeIndexes){
219
            result.add(treeIndex.toString());
220
        }
221
        return result;
222
    }
223

    
224

    
225

    
226
}
(75-75/83)