Project

General

Profile

Download (5.24 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 stringList
40
     * @return
41
     */
42
    public static List<TreeIndex> NewListInstance(List<String> stringList) {
43
        List<TreeIndex> result = new ArrayList<>();
44
        for (String string: stringList){
45
            result.add(new TreeIndex(string));
46
        }
47
        return result;
48
    }
49

    
50
    private static String regEx = "#[a-z](\\d+#)+";
51
    private static Pattern pattern = Pattern.compile(regEx);
52

    
53
    private static TreeIndexComparator comparator = new TreeIndexComparator();
54

    
55
    private String treeIndex;
56

    
57
    private TreeIndex(String treeIndex){
58
        if (! pattern.matcher(treeIndex).matches()){
59
            throw new IllegalArgumentException("Given string is not a valid tree index");
60
        }
61
        this.treeIndex = treeIndex;
62
    }
63

    
64
// ************** METHODS ***************************************/
65

    
66
    /**
67
     * @param taxonTreeIndex
68
     * @return
69
     */
70
    public boolean hasChild(TreeIndex childCandidateTreeIndex) {
71
        return childCandidateTreeIndex.treeIndex.startsWith(treeIndex);
72
    }
73

    
74

    
75
    /**
76
     * Returns a new TreeIndex instance which represents the parent of this tree index.
77
     * Returns null if this tree index already represents the root node of the tree.
78
     * @return
79
     */
80
    public TreeIndex parent(){
81
        int index = treeIndex.substring(0, treeIndex.length()-1).lastIndexOf(ITreeNode.separator);
82
        try {
83
            TreeIndex result = index < 0 ? null : NewInstance(treeIndex.substring(0, index+1));
84
            return result;
85
        } catch (Exception e) {
86
            //it is not a valid treeindex anymore
87
            return null;
88
        }
89
    }
90

    
91
// ********************** STATIC METHODS  *****************************/
92

    
93
    /**
94
     * Creates a list for the given tree indexes and sorts them in ascending
95
     * order.
96
     * @param treeIndexSet
97
     * @return
98
     */
99
    public static List<TreeIndex> sort(Collection<TreeIndex> treeIndexSet) {
100
        List<TreeIndex> result = new ArrayList<>(treeIndexSet);
101
        Collections.sort(result, comparator);
102
        return result;
103
    }
104

    
105

    
106
    /**
107
     * Creates a list for the given tree indexes and sorts them in descending
108
     * order.
109
     * @param treeIndexSet
110
     * @return
111
     */
112
    public static List<TreeIndex> sortDesc(Collection<TreeIndex> treeIndexSet) {
113
        List<TreeIndex> result = sort(treeIndexSet);
114
        Collections.reverse(result);
115
        return result;
116
    }
117

    
118
    public static Map<TreeIndex, TreeIndex> group(Collection<TreeIndex> groupingIndexes, Collection<TreeIndex> toBeGroupedIndexes){
119

    
120
        //for larger groupingIndexes we could optimize this by sorting both collections
121
        //prior to loop. This way we do traverse both lists once
122
        Map<TreeIndex, TreeIndex> result = new HashMap<>();
123
        List<TreeIndex> descSortedGroupingIndexes = sortDesc(groupingIndexes);
124

    
125
        for (TreeIndex toBeGrouped : toBeGroupedIndexes) {
126
            boolean groupFound = false;
127
            for (TreeIndex groupingIndex : descSortedGroupingIndexes){
128
                if (groupingIndex.hasChild(toBeGrouped)){
129
                    result.put(toBeGrouped, groupingIndex);
130
                    groupFound = true;
131
                    break;
132
                }
133
            }
134
            if (!groupFound){
135
                result.put(toBeGrouped, null);
136
            }
137
        }
138
        return result;
139
    }
140

    
141

    
142
// **************************** EQUALS *****************************/
143

    
144
    @Override
145
    public int hashCode() {
146
        return treeIndex.hashCode();
147
    }
148

    
149
    @Override
150
    public boolean equals(Object obj) {
151
        if (obj instanceof TreeIndex){
152
            return treeIndex.equals(((TreeIndex)obj).treeIndex);
153
        }else{
154
            return false;
155
        }
156
    }
157

    
158
// *************************** toString() ***********************
159

    
160

    
161

    
162
    @Override
163
    public String toString(){
164
        return treeIndex;
165
    }
166

    
167
    /**
168
     * Null save toString method.
169
     * @param treeIndex
170
     * @return
171
     */
172
    public static String toString(TreeIndex treeIndex) {
173
        return treeIndex == null? null: treeIndex.toString();
174
    }
175

    
176

    
177
    /**
178
     * @param treeIndexes
179
     * @return
180
     */
181
    public static List<String> toString(Collection<TreeIndex> treeIndexes) {
182
        List<String> result = new ArrayList<>();
183
        for (TreeIndex treeIndex : treeIndexes){
184
            result.add(treeIndex.toString());
185
        }
186
        return result;
187
    }
188

    
189
}
(72-72/79)