1 package org.lsst.ccs.utilities.structs;
2
3 import javax.swing.tree.TreeNode;
4 import java.beans.ConstructorProperties;
5 import java.io.Serializable;
6 import java.util.*;
7
8
9
10
11
12
13
14
15 public class TreeBranch<T extends Serializable> implements Serializable, TreeNode, Iterable<T> {
16
17 private static final long serialVersionUID = -8299651867210784530L;
18
19
20
21 private TreeBranch<T> parent;
22
23
24
25 private ArrayList<TreeBranch<T>> children;
26
27
28
29 private T content;
30
31
32
33
34 private int currentIndex = -1;
35
36
37
38
39
40
41 public TreeBranch(T content) {
42 this.content = content;
43 }
44
45
46
47
48
49 protected TreeBranch() {
50 }
51
52
53
54
55
56
57
58
59 @ConstructorProperties({"realParent", "content"})
60 public TreeBranch(TreeBranch<T> parent, T content) {
61
62 this.content = content;
63 if (parent != null) {
64 parent.addChild(this);
65 }
66 }
67
68
69
70
71
72
73
74 public synchronized void addChild(TreeBranch<T> child) {
75 if (child == null) {
76 throw new IllegalArgumentException("null child");
77 }
78 if (child.parent != null) {
79 throw new IllegalArgumentException(this + " node " + child + " already part of another tree " + child.parent);
80 }
81 if (children == null) {
82 children = new ArrayList<>();
83 }
84 int index = children.size();
85 children.add(child);
86 child.currentIndex = index;
87 child.parent = this;
88 }
89
90
91
92
93 public T getContent() {
94 return content;
95 }
96
97
98
99
100
101 public int getCurrentIndex() {
102 return currentIndex;
103 }
104
105
106
107
108 @Override
109 public Iterator<T> iterator() {
110 return new PreOrderIterator<T>(this);
111 }
112
113
114
115
116 public Iterator<TreeBranch<T>> nodeIterator() {
117 return new PreOrderNodeIterator<T>(this);
118 }
119
120
121
122
123 public List<TreeBranch<T>> getChildren() {
124 if (children != null) {
125 return children;
126 }
127 return Collections.emptyList();
128 }
129
130
131
132
133 public Iterator<TreeBranch<T>> getChildIterator() {
134 if (children != null) {
135 return children.iterator();
136 }
137 return Collections.emptyIterator();
138 }
139
140
141
142
143
144 public List<TreeBranch<T>> getPath() {
145 ArrayList<TreeBranch<T>> res = new ArrayList<>();
146 TreeBranch<T> curNode = this;
147 while (null != (curNode = curNode.getRealParent())) {
148 res.add(curNode);
149 }
150 Collections.reverse(res);
151 return res;
152 }
153
154
155
156
157
158
159
160 @Override
161 public TreeNode getChildAt(int childIndex) {
162 if (children != null) {
163 if (childIndex >= children.size() || childIndex < 0) {
164 return null;
165 }
166 TreeBranch<T> res = children.get(childIndex);
167 assert childIndex == res.currentIndex;
168 return res;
169 }
170 return null;
171 }
172
173
174
175
176 @Override
177 public int getChildCount() {
178 if (children == null) return 0;
179 return children.size();
180 }
181
182
183
184
185
186 @Override
187 public TreeNode getParent() {
188 return parent;
189 }
190
191
192
193
194
195
196
197 public TreeBranch<T> getRealParent() {
198 return parent;
199 }
200
201
202
203
204
205
206 @Override
207 public int getIndex(TreeNode node) {
208 if (node.getParent() != this) {
209 return -1;
210 }
211 if (children != null) {
212 TreeBranch<T> branch = (TreeBranch<T>) node;
213 return branch.currentIndex;
214 }
215 return -1;
216 }
217
218
219
220
221
222
223
224 @Override
225 public boolean getAllowsChildren() {
226 return children != null;
227 }
228
229
230
231
232 @Override
233 public boolean isLeaf() {
234 return children == null;
235 }
236
237
238
239
240 public boolean isRootNode() {
241 return parent == null;
242 }
243
244
245
246
247
248 @Override
249 public Enumeration children() {
250
251 return new Enumeration() {
252 final Iterator iter = children.iterator();
253
254 @Override
255 public boolean hasMoreElements() {
256 return iter.hasNext();
257 }
258
259 @Override
260 public Object nextElement() {
261 return iter.next();
262 }
263 };
264 }
265
266
267
268
269
270 @Override
271 public String toString() {
272 return String.valueOf(content);
273 }
274
275
276
277
278
279
280
281 protected static class PreOrderIterator<X extends Serializable> implements Iterator<X> {
282 private final PreOrderNodeIterator<X> preOrderNodeIterator;
283
284 public PreOrderIterator(TreeBranch<X> rootNode) {
285 preOrderNodeIterator = new PreOrderNodeIterator<>(rootNode);
286 }
287
288
289 @Override
290 public X next() {
291 TreeBranch<X> node = preOrderNodeIterator.next();
292 return node.getContent();
293 }
294
295
296 @Override
297 public boolean hasNext() {
298 return preOrderNodeIterator.hasNext();
299 }
300
301
302 @Override
303 public void remove() {
304 throw new UnsupportedOperationException("remove");
305 }
306 }
307
308
309
310
311
312
313 protected static class PreOrderNodeIterator<X extends Serializable> implements Iterator<TreeBranch<X>> {
314 private final Stack<Iterator<TreeBranch<X>>> stack = new Stack<>();
315
316 public PreOrderNodeIterator(TreeBranch<X> rootNode) {
317
318 ArrayList<TreeBranch<X>> edenChildList = new ArrayList<>(1);
319 edenChildList.add(rootNode);
320 stack.push(edenChildList.iterator());
321 }
322
323
324 @Override
325 public TreeBranch<X> next() {
326
327
328 Iterator<TreeBranch<X>> iter = stack.peek();
329
330 TreeBranch<X> node = iter.next();
331
332 Iterator<TreeBranch<X>> itChildren = node.getChildIterator();
333
334 if (!iter.hasNext()) {
335 stack.pop();
336 }
337
338 if (itChildren.hasNext()) {
339 stack.push(itChildren);
340 }
341 return node;
342 }
343
344
345
346
347
348
349
350
351 @Override
352 public boolean hasNext() {
353 return (!stack.empty() && stack.peek().hasNext());
354 }
355
356
357 @Override
358 public void remove() {
359 throw new UnsupportedOperationException("remove");
360 }
361 }
362 }