OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [tree/] [DefaultMutableTreeNode.java] - Blame information for rev 775

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* DefaultMutableTreeNode.java --
2
   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing.tree;
40
 
41
import gnu.java.util.EmptyEnumeration;
42
 
43
import java.io.IOException;
44
import java.io.ObjectInputStream;
45
import java.io.ObjectOutputStream;
46
import java.io.Serializable;
47
import java.util.ArrayList;
48
import java.util.Enumeration;
49
import java.util.LinkedList;
50
import java.util.NoSuchElementException;
51
import java.util.Stack;
52
import java.util.Vector;
53
 
54
 
55
/**
56
 * A default implementation of the {@link MutableTreeNode} interface.
57
 *
58
 * @author Andrew Selkirk
59
 * @author Robert Schuster (robertschuster@fsfe.org)
60
 */
61
public class DefaultMutableTreeNode
62
  implements Cloneable, MutableTreeNode, Serializable
63
{
64
  private static final long serialVersionUID = -4298474751201349152L;
65
 
66
  /**
67
   * An empty enumeration, returned by {@link #children()} if a node has no
68
   * children.
69
   */
70
  public static final Enumeration<TreeNode> EMPTY_ENUMERATION =
71
    new EmptyEnumeration<TreeNode>();
72
 
73
  /**
74
   * The parent of this node (possibly <code>null</code>).
75
   */
76
  protected MutableTreeNode parent;
77
 
78
  /**
79
   * The child nodes for this node (may be empty).
80
   */
81
  protected Vector<MutableTreeNode> children = new Vector<MutableTreeNode>();
82
 
83
  /**
84
   * userObject
85
   */
86
  protected transient Object userObject;
87
 
88
  /**
89
   * allowsChildren
90
   */
91
  protected boolean allowsChildren;
92
 
93
  /**
94
   * Creates a <code>DefaultMutableTreeNode</code> object.
95
   * This is equivalent to <code>DefaultMutableTreeNode(null, true)</code>.
96
   */
97
  public DefaultMutableTreeNode()
98
  {
99
    this(null, true);
100
  }
101
 
102
  /**
103
   * Creates a <code>DefaultMutableTreeNode</code> object with the given
104
   * user object attached to it. This is equivalent to
105
   * <code>DefaultMutableTreeNode(userObject, true)</code>.
106
   *
107
   * @param userObject the user object (<code>null</code> permitted).
108
   */
109
  public DefaultMutableTreeNode(Object userObject)
110
  {
111
    this(userObject, true);
112
  }
113
 
114
  /**
115
   * Creates a <code>DefaultMutableTreeNode</code> object with the given
116
   * user object attached to it.
117
   *
118
   * @param userObject the user object (<code>null</code> permitted).
119
   * @param allowsChildren <code>true</code> if the code allows to add child
120
   * nodes, <code>false</code> otherwise
121
   */
122
  public DefaultMutableTreeNode(Object userObject, boolean allowsChildren)
123
  {
124
    this.userObject = userObject;
125
    this.allowsChildren = allowsChildren;
126
  }
127
 
128
  /**
129
   * Returns a clone of the node.  The clone contains a shallow copy of the
130
   * user object, and does not copy the parent node or the child nodes.
131
   *
132
   * @return A clone of the node.
133
   */
134
  public Object clone()
135
  {
136
    return new DefaultMutableTreeNode(this.userObject, this.allowsChildren);
137
  }
138
 
139
  /**
140
   * Returns a string representation of the node.  This implementation returns
141
   * <code>getUserObject().toString()</code>, or <code>null</code> if there
142
   * is no user object.
143
   *
144
   * @return A string representation of the node (possibly <code>null</code>).
145
   */
146
  public String toString()
147
  {
148
    if (userObject == null)
149
      return null;
150
 
151
    return userObject.toString();
152
  }
153
 
154
  /**
155
   * Adds a new child node to this node and sets this node as the parent of
156
   * the child node.  The child node must not be an ancestor of this node.
157
   * If the tree uses the {@link DefaultTreeModel}, you must subsequently
158
   * call {@link DefaultTreeModel#reload(TreeNode)}.
159
   *
160
   * @param child the child node (<code>null</code> not permitted).
161
   *
162
   * @throws IllegalStateException if {@link #getAllowsChildren()} returns
163
   *     <code>false</code>.
164
   * @throws IllegalArgumentException if {@link #isNodeAncestor} returns
165
   *     <code>true</code>.
166
   * @throws IllegalArgumentException if <code>child</code> is
167
   *     <code>null</code>.
168
   */
169
  public void add(MutableTreeNode child)
170
  {
171
    if (! allowsChildren)
172
      throw new IllegalStateException();
173
 
174
    if (child == null)
175
      throw new IllegalArgumentException();
176
 
177
    if (isNodeAncestor(child))
178
      throw new IllegalArgumentException("Cannot add ancestor node.");
179
 
180
    children.add(child);
181
    child.setParent(this);
182
  }
183
 
184
  /**
185
   * Returns the parent node of this node.
186
   *
187
   * @return The parent node (possibly <code>null</code>).
188
   */
189
  public TreeNode getParent()
190
  {
191
    return parent;
192
  }
193
 
194
  /**
195
   * Removes the child with the given index from this node.
196
   *
197
   * @param index the index (in the range <code>0</code> to
198
   *     <code>getChildCount() - 1</code>).
199
   *
200
   * @throws ArrayIndexOutOfBoundsException if <code>index</code> is outside
201
   *         the valid range.
202
   */
203
  public void remove(int index)
204
  {
205
    MutableTreeNode child = children.remove(index);
206
    child.setParent(null);
207
  }
208
 
209
  /**
210
   * Removes the given child from this node and sets its parent to
211
   * <code>null</code>.
212
   *
213
   * @param node the child node (<code>null</code> not permitted).
214
   *
215
   * @throws IllegalArgumentException if <code>node</code> is not a child of
216
   *     this node.
217
   * @throws IllegalArgumentException if <code>node</code> is null.
218
   */
219
  public void remove(MutableTreeNode node)
220
  {
221
    if (node == null)
222
      throw new IllegalArgumentException("Null 'node' argument.");
223
    if (node.getParent() != this)
224
      throw new IllegalArgumentException(
225
          "The given 'node' is not a child of this node.");
226
    children.remove(node);
227
    node.setParent(null);
228
  }
229
 
230
  /**
231
   * writeObject
232
   *
233
   * @param stream the output stream
234
   *
235
   * @exception IOException If an error occurs
236
   */
237
  private void writeObject(ObjectOutputStream stream)
238
    throws IOException
239
  {
240
    // TODO: Implement me.
241
  }
242
 
243
  /**
244
   * readObject
245
   *
246
   * @param stream the input stream
247
   *
248
   * @exception IOException If an error occurs
249
   * @exception ClassNotFoundException TODO
250
   */
251
  private void readObject(ObjectInputStream stream)
252
    throws IOException, ClassNotFoundException
253
  {
254
    // TODO: Implement me.
255
  }
256
 
257
  /**
258
   * Inserts given child node at the given index.
259
   *
260
   * @param node the child node (<code>null</code> not permitted).
261
   * @param index the index.
262
   *
263
   * @throws IllegalArgumentException if <code>node</code> is
264
   *     </code>null</code>.
265
   */
266
  public void insert(MutableTreeNode node, int index)
267
  {
268
    if (! allowsChildren)
269
      throw new IllegalStateException();
270
 
271
    if (node == null)
272
      throw new IllegalArgumentException("Null 'node' argument.");
273
 
274
    if (isNodeAncestor(node))
275
      throw new IllegalArgumentException("Cannot insert ancestor node.");
276
 
277
    children.insertElementAt(node, index);
278
  }
279
 
280
  /**
281
   * Returns a path to this node from the root.
282
   *
283
   * @return an array of tree nodes
284
   */
285
  public TreeNode[] getPath()
286
  {
287
    return getPathToRoot(this, 0);
288
  }
289
 
290
  /**
291
   * Returns an enumeration containing all children of this node.
292
   * <code>EMPTY_ENUMERATION</code> is returned if this node has no children.
293
   *
294
   * @return an enumeration of tree nodes
295
   */
296
  @SuppressWarnings("unchecked") // Required for API compatibility
297
  public Enumeration children()
298
  {
299
    if (children.size() == 0)
300
      return EMPTY_ENUMERATION;
301
 
302
    return children.elements();
303
  }
304
 
305
  /**
306
   * Set the parent node for this node.
307
   *
308
   * @param node the parent node
309
   */
310
  public void setParent(MutableTreeNode node)
311
  {
312
    parent = node;
313
  }
314
 
315
  /**
316
   * Returns the child node at a given index.
317
   *
318
   * @param index the index
319
   *
320
   * @return the child node
321
   */
322
  public TreeNode getChildAt(int index)
323
  {
324
    return children.elementAt(index);
325
  }
326
 
327
  /**
328
   * Returns the number of children of this node.
329
   *
330
   * @return the number of children
331
   */
332
  public int getChildCount()
333
  {
334
    return children.size();
335
  }
336
 
337
  /**
338
   * Returns the index of the specified child node, or -1 if the node is not
339
   * in fact a child of this node.
340
   *
341
   * @param node  the node (<code>null</code> not permitted).
342
   *
343
   * @return The index of the specified child node, or -1.
344
   *
345
   * @throws IllegalArgumentException if <code>node</code> is <code>null</code>.
346
   */
347
  public int getIndex(TreeNode node)
348
  {
349
    if (node == null)
350
      throw new IllegalArgumentException("Null 'node' argument.");
351
    return children.indexOf(node);
352
  }
353
 
354
  /**
355
   * Sets the flag that controls whether or not this node allows the addition /
356
   * insertion of child nodes.  If the flag is set to <code>false</code>, any
357
   * existing children are removed.
358
   *
359
   * @param allowsChildren  the flag.
360
   */
361
  public void setAllowsChildren(boolean allowsChildren)
362
  {
363
    if (!allowsChildren)
364
      removeAllChildren();
365
    this.allowsChildren = allowsChildren;
366
  }
367
 
368
  /**
369
   * getAllowsChildren
370
   *
371
   * @return boolean
372
   */
373
  public boolean getAllowsChildren()
374
  {
375
    return allowsChildren;
376
  }
377
 
378
  /**
379
   * Sets the user object for this node
380
   *
381
   * @param userObject the user object
382
   */
383
  public void setUserObject(Object userObject)
384
  {
385
    this.userObject = userObject;
386
  }
387
 
388
  /**
389
   * Returns the user object attached to this node. <code>null</code> is
390
   * returned when no user object is set.
391
   *
392
   * @return the user object
393
   */
394
  public Object getUserObject()
395
  {
396
    return userObject;
397
  }
398
 
399
  /**
400
   * Removes this node from its parent.
401
   */
402
  public void removeFromParent()
403
  {
404
    parent.remove(this);
405
    parent = null;
406
  }
407
 
408
  /**
409
   * Removes all child nodes from this node.
410
   */
411
  public void removeAllChildren()
412
  {
413
    for (int i = getChildCount() - 1; i >= 0; i--)
414
      remove(i);
415
  }
416
 
417
  /**
418
   * Returns <code>true</code> if <code>node</code> is an ancestor of this
419
   * tree node, and <code>false</code> otherwise.  An ancestor node is any of:
420
   * <ul>
421
   * <li>this tree node;</li>
422
   * <li>the parent node (if there is one);</li>
423
   * <li>any ancestor of the parent node;</li>
424
   * </ul>
425
   * If <code>node</code> is <code>null</code>, this method returns
426
   * <code>false</code>.
427
   *
428
   * @param node  the node (<code>null</code> permitted).
429
   *
430
   * @return A boolean.
431
   */
432
  public boolean isNodeAncestor(TreeNode node)
433
  {
434
    if (node == null)
435
      return false;
436
 
437
    TreeNode current = this;
438
 
439
    while (current != null && current != node)
440
      current = current.getParent();
441
 
442
    return current == node;
443
  }
444
 
445
  /**
446
   * Returns <code>true</code> if <code>node</code> is a descendant of this
447
   * tree node, and <code>false</code> otherwise.  A descendant node is any of:
448
   * <ul>
449
   * <li>this tree node;</li>
450
   * <li>the child nodes belonging to this tree node, if there are any;</li>
451
   * <li>any descendants of the child nodes;</li>
452
   * </ul>
453
   * If <code>node</code> is <code>null</code>, this method returns
454
   * <code>false</code>.
455
   *
456
   * @param node  the node (<code>null</code> permitted).
457
   *
458
   * @return A boolean.
459
   */
460
  public boolean isNodeDescendant(DefaultMutableTreeNode node)
461
  {
462
    if (node == null)
463
      return false;
464
 
465
    TreeNode current = node;
466
 
467
    while (current != null
468
           && current != this)
469
      current = current.getParent();
470
 
471
    return current == this;
472
  }
473
 
474
  /**
475
   * getSharedAncestor
476
   *
477
   * @param node TODO
478
   *
479
   * @return TreeNode
480
   */
481
  public TreeNode getSharedAncestor(DefaultMutableTreeNode node)
482
  {
483
    TreeNode current = this;
484
    ArrayList<TreeNode> list = new ArrayList<TreeNode>();
485
 
486
    while (current != null)
487
      {
488
        list.add(current);
489
        current = current.getParent();
490
      }
491
 
492
    current = node;
493
 
494
    while (current != null)
495
      {
496
        if (list.contains(current))
497
          return current;
498
 
499
        current = current.getParent();
500
      }
501
 
502
    return null;
503
  }
504
 
505
  /**
506
   * isNodeRelated
507
   *
508
   * @param node TODO
509
   *
510
   * @return boolean
511
   */
512
  public boolean isNodeRelated(DefaultMutableTreeNode node)
513
  {
514
    if (node == null)
515
      return false;
516
 
517
    return node.getRoot() == getRoot();
518
  }
519
 
520
  /**
521
   * getDepth
522
   *
523
   * @return int
524
   */
525
  public int getDepth()
526
  {
527
    if ((! allowsChildren)
528
        || children.size() == 0)
529
      return 0;
530
 
531
    Stack<Integer> stack = new Stack<Integer>();
532
    stack.push(new Integer(0));
533
    TreeNode node = getChildAt(0);
534
    int depth = 0;
535
    int current = 1;
536
 
537
    while (! stack.empty())
538
      {
539
        if (node.getChildCount() != 0)
540
          {
541
            node = node.getChildAt(0);
542
            stack.push(new Integer(0));
543
            current++;
544
          }
545
        else
546
          {
547
            if (current > depth)
548
              depth = current;
549
 
550
            int size;
551
            int index;
552
 
553
            do
554
              {
555
                node = node.getParent();
556
                size = node.getChildCount();
557
                index = stack.pop().intValue() + 1;
558
                current--;
559
              }
560
            while (index >= size
561
                   && node != this);
562
 
563
            if (index < size)
564
              {
565
                node = node.getChildAt(index);
566
                stack.push(new Integer(index));
567
                current++;
568
              }
569
          }
570
      }
571
 
572
    return depth;
573
  }
574
 
575
  /**
576
   * getLevel
577
   *
578
   * @return int
579
   */
580
  public int getLevel()
581
  {
582
    int count = -1;
583
    TreeNode current = this;
584
 
585
    do
586
      {
587
        current = current.getParent();
588
        count++;
589
      }
590
    while (current != null);
591
 
592
    return count;
593
  }
594
 
595
  /**
596
   * getPathToRoot
597
   *
598
   * @param node TODO
599
   * @param depth TODO
600
   *
601
   * @return TreeNode[]
602
   */
603
  protected TreeNode[] getPathToRoot(TreeNode node, int depth)
604
  {
605
    if (node == null)
606
      {
607
        if (depth == 0)
608
          return null;
609
 
610
        return new TreeNode[depth];
611
      }
612
 
613
    TreeNode[] path = getPathToRoot(node.getParent(), depth + 1);
614
    path[path.length - depth - 1] = node;
615
    return path;
616
  }
617
 
618
  /**
619
   * getUserObjectPath
620
   *
621
   * @return Object[]
622
   */
623
  public Object[] getUserObjectPath()
624
  {
625
    TreeNode[] path = getPathToRoot(this, 0);
626
    Object[] object = new Object[path.length];
627
 
628
    for (int index = 0; index < path.length; ++index)
629
      object[index] = ((DefaultMutableTreeNode) path[index]).getUserObject();
630
 
631
    return object;
632
  }
633
 
634
  /**
635
   * Returns the root node by iterating the parents of this node.
636
   *
637
   * @return the root node
638
   */
639
  public TreeNode getRoot()
640
  {
641
    TreeNode current = this;
642
    TreeNode check = current.getParent();
643
 
644
    while (check != null)
645
      {
646
        current = check;
647
        check = current.getParent();
648
      }
649
 
650
    return current;
651
  }
652
 
653
  /**
654
   * Tells whether this node is the root node or not.
655
   *
656
   * @return <code>true</code> if this is the root node,
657
   * <code>false</code>otherwise
658
   */
659
  public boolean isRoot()
660
  {
661
    return parent == null;
662
  }
663
 
664
  /**
665
   * getNextNode
666
   *
667
   * @return DefaultMutableTreeNode
668
   */
669
  public DefaultMutableTreeNode getNextNode()
670
  {
671
    // Return first child.
672
    if (getChildCount() != 0)
673
      return (DefaultMutableTreeNode) getChildAt(0);
674
 
675
    // Return next sibling (if needed the sibling of some parent).
676
    DefaultMutableTreeNode node = this;
677
    DefaultMutableTreeNode sibling;
678
 
679
    do
680
      {
681
        sibling = node.getNextSibling();
682
        node = (DefaultMutableTreeNode) node.getParent();
683
      }
684
    while (sibling == null &&
685
           node != null);
686
 
687
    // Return sibling.
688
    return sibling;
689
  }
690
 
691
  /**
692
   * getPreviousNode
693
   *
694
   * @return DefaultMutableTreeNode
695
   */
696
  public DefaultMutableTreeNode getPreviousNode()
697
  {
698
    // Return null if no parent.
699
    if (parent == null)
700
      return null;
701
 
702
    DefaultMutableTreeNode sibling = getPreviousSibling();
703
 
704
    // Return parent if no sibling.
705
    if (sibling == null)
706
      return (DefaultMutableTreeNode) parent;
707
 
708
    // Return last leaf of sibling.
709
    if (sibling.getChildCount() != 0)
710
      return sibling.getLastLeaf();
711
 
712
    // Return sibling.
713
    return sibling;
714
  }
715
 
716
  /**
717
   * preorderEnumeration
718
   *
719
   * @return Enumeration
720
   */
721
  @SuppressWarnings("unchecked") // Required for API compatibility
722
  public Enumeration preorderEnumeration()
723
  {
724
    return new PreorderEnumeration(this);
725
  }
726
 
727
  /**
728
   * postorderEnumeration
729
   *
730
   * @return Enumeration
731
   */
732
  @SuppressWarnings("unchecked") // Required for API compatibility
733
  public Enumeration postorderEnumeration()
734
  {
735
    return new PostorderEnumeration(this);
736
  }
737
 
738
  /**
739
   * breadthFirstEnumeration
740
   *
741
   * @return Enumeration
742
   */
743
  @SuppressWarnings("unchecked") // Required for API compatibility
744
  public Enumeration breadthFirstEnumeration()
745
  {
746
    return new BreadthFirstEnumeration(this);
747
  }
748
 
749
  /**
750
   * depthFirstEnumeration
751
   *
752
   * @return Enumeration
753
   */
754
  @SuppressWarnings("unchecked") // Required for API compatibility
755
  public Enumeration depthFirstEnumeration()
756
  {
757
    return postorderEnumeration();
758
  }
759
 
760
  /**
761
   * pathFromAncestorEnumeration
762
   *
763
   * @param node TODO
764
   *
765
   * @return Enumeration
766
   */
767
  @SuppressWarnings("unchecked") // Required for API compatibility
768
  public Enumeration pathFromAncestorEnumeration(TreeNode node)
769
  {
770
    if (node == null)
771
      throw new IllegalArgumentException();
772
 
773
    TreeNode parent = this;
774
    Vector<TreeNode> nodes = new Vector<TreeNode>();
775
    nodes.add(this);
776
 
777
    while (parent != node && parent != null)
778
      {
779
        parent = parent.getParent();
780
        nodes.add(0, parent);
781
      }
782
 
783
    if (parent != node)
784
      throw new IllegalArgumentException();
785
 
786
    return nodes.elements();
787
  }
788
 
789
  /**
790
   * Returns <code>true</code> if <code>node</code> is a child of this tree
791
   * node, and <code>false</code> otherwise.  If <code>node</code> is
792
   * <code>null</code>, this method returns <code>false</code>.
793
   *
794
   * @param node  the node (<code>null</code> permitted).
795
   *
796
   * @return A boolean.
797
   */
798
  public boolean isNodeChild(TreeNode node)
799
  {
800
    if (node == null)
801
      return false;
802
 
803
    return node.getParent() == this;
804
  }
805
 
806
  /**
807
   * Returns the first child node belonging to this tree node.
808
   *
809
   * @return The first child node.
810
   *
811
   * @throws NoSuchElementException if this tree node has no children.
812
   */
813
  public TreeNode getFirstChild()
814
  {
815
    return children.firstElement();
816
  }
817
 
818
  /**
819
   * Returns the last child node belonging to this tree node.
820
   *
821
   * @return The last child node.
822
   *
823
   * @throws NoSuchElementException if this tree node has no children.
824
   */
825
  public TreeNode getLastChild()
826
  {
827
    return children.lastElement();
828
  }
829
 
830
  /**
831
   * Returns the next child after the specified <code>node</code>, or
832
   * <code>null</code> if there is no child after the specified
833
   * <code>node</code>.
834
   *
835
   * @param node  a child of this node (<code>null</code> not permitted).
836
   *
837
   * @return The next child, or <code>null</code>.
838
   *
839
   * @throws IllegalArgumentException if <code>node</code> is not a child of
840
   *     this node, or is <code>null</code>.
841
   */
842
  public TreeNode getChildAfter(TreeNode node)
843
  {
844
    if (node == null || node.getParent() != this)
845
      throw new IllegalArgumentException();
846
 
847
    int index = getIndex(node) + 1;
848
 
849
    if (index == getChildCount())
850
      return null;
851
 
852
    return getChildAt(index);
853
  }
854
 
855
  /**
856
   * Returns the previous child before the specified <code>node</code>, or
857
   * <code>null</code> if there is no child before the specified
858
   * <code>node</code>.
859
   *
860
   * @param node  a child of this node (<code>null</code> not permitted).
861
   *
862
   * @return The previous child, or <code>null</code>.
863
   *
864
   * @throws IllegalArgumentException if <code>node</code> is not a child of
865
   *     this node, or is <code>null</code>.
866
   */
867
  public TreeNode getChildBefore(TreeNode node)
868
  {
869
    if (node == null || node.getParent() != this)
870
      throw new IllegalArgumentException();
871
 
872
    int index = getIndex(node) - 1;
873
 
874
    if (index < 0)
875
      return null;
876
 
877
    return getChildAt(index);
878
  }
879
 
880
  /**
881
   * Returns <code>true</code> if this tree node and <code>node</code> share
882
   * the same parent.  If <code>node</code> is this tree node, the method
883
   * returns <code>true</code> and if <code>node</code> is <code>null</code>
884
   * this method returns <code>false</code>.
885
   *
886
   * @param node  the node (<code>null</code> permitted).
887
   *
888
   * @return A boolean.
889
   */
890
  public boolean isNodeSibling(TreeNode node)
891
  {
892
    if (node == null)
893
      return false;
894
    if (node == this)
895
      return true;
896
    return node.getParent() == getParent() && getParent() != null;
897
  }
898
 
899
  /**
900
   * Returns the number of siblings for this tree node.  If the tree node has
901
   * a parent, this method returns the child count for the parent, otherwise
902
   * it returns <code>1</code>.
903
   *
904
   * @return The sibling count.
905
   */
906
  public int getSiblingCount()
907
  {
908
    if (parent == null)
909
      return 1;
910
 
911
    return parent.getChildCount();
912
  }
913
 
914
  /**
915
   * Returns the next sibling for this tree node.  If this node has no parent,
916
   * or this node is the last child of its parent, this method returns
917
   * <code>null</code>.
918
   *
919
   * @return The next sibling, or <code>null</code>.
920
   */
921
  public DefaultMutableTreeNode getNextSibling()
922
  {
923
    if (parent == null)
924
      return null;
925
 
926
    int index = parent.getIndex(this) + 1;
927
 
928
    if (index == parent.getChildCount())
929
      return null;
930
 
931
    return (DefaultMutableTreeNode) parent.getChildAt(index);
932
  }
933
 
934
  /**
935
   * Returns the previous sibling for this tree node.  If this node has no
936
   * parent, or this node is the first child of its parent, this method returns
937
   * <code>null</code>.
938
   *
939
   * @return The previous sibling, or <code>null</code>.
940
   */
941
  public DefaultMutableTreeNode getPreviousSibling()
942
  {
943
    if (parent == null)
944
      return null;
945
 
946
    int index = parent.getIndex(this) - 1;
947
 
948
    if (index < 0)
949
      return null;
950
 
951
    return (DefaultMutableTreeNode) parent.getChildAt(index);
952
  }
953
 
954
  /**
955
   * Returns <code>true</code> if this tree node is a lead node (that is, it
956
   * has no children), and <code>false</otherwise>.
957
   *
958
   * @return A boolean.
959
   */
960
  public boolean isLeaf()
961
  {
962
    return children.size() == 0;
963
  }
964
 
965
  /**
966
   * Returns the first leaf node that is a descendant of this node.  Recall
967
   * that a node is its own descendant, so if this node has no children then
968
   * it is returned as the first leaf.
969
   *
970
   * @return The first leaf node.
971
   */
972
  public DefaultMutableTreeNode getFirstLeaf()
973
  {
974
    TreeNode current = this;
975
 
976
    while (current.getChildCount() > 0)
977
      current = current.getChildAt(0);
978
 
979
    return (DefaultMutableTreeNode) current;
980
  }
981
 
982
  /**
983
   * Returns the last leaf node that is a descendant of this node.  Recall
984
   * that a node is its own descendant, so if this node has no children then
985
   * it is returned as the last leaf.
986
   *
987
   * @return The first leaf node.
988
   */
989
  public DefaultMutableTreeNode getLastLeaf()
990
  {
991
    TreeNode current = this;
992
    int size = current.getChildCount();
993
 
994
    while (size > 0)
995
      {
996
        current = current.getChildAt(size - 1);
997
        size = current.getChildCount();
998
      }
999
 
1000
    return (DefaultMutableTreeNode) current;
1001
  }
1002
 
1003
  /**
1004
   * Returns the next leaf node after this tree node.
1005
   *
1006
   * @return The next leaf node, or <code>null</code>.
1007
   */
1008
  public DefaultMutableTreeNode getNextLeaf()
1009
  {
1010
    // if there is a next sibling, return its first leaf
1011
    DefaultMutableTreeNode sibling = getNextSibling();
1012
    if (sibling != null)
1013
      return sibling.getFirstLeaf();
1014
    // otherwise move up one level and try again...
1015
    if (parent != null)
1016
      return ((DefaultMutableTreeNode) parent).getNextLeaf();
1017
    return null;
1018
  }
1019
 
1020
  /**
1021
   * Returns the previous leaf node before this tree node.
1022
   *
1023
   * @return The previous leaf node, or <code>null</code>.
1024
   */
1025
  public DefaultMutableTreeNode getPreviousLeaf()
1026
  {
1027
    // if there is a previous sibling, return its last leaf
1028
    DefaultMutableTreeNode sibling = getPreviousSibling();
1029
    if (sibling != null)
1030
      return sibling.getLastLeaf();
1031
    // otherwise move up one level and try again...
1032
    if (parent != null)
1033
      return ((DefaultMutableTreeNode) parent).getPreviousLeaf();
1034
    return null;
1035
  }
1036
 
1037
  /**
1038
   * getLeafCount
1039
   *
1040
   * @return int
1041
   */
1042
  public int getLeafCount()
1043
  {
1044
    int count = 0;
1045
    Enumeration<?> e = depthFirstEnumeration();
1046
 
1047
    while (e.hasMoreElements())
1048
      {
1049
        TreeNode current = (TreeNode) e.nextElement();
1050
 
1051
        if (current.isLeaf())
1052
          count++;
1053
      }
1054
 
1055
    return count;
1056
  }
1057
 
1058
  /** Provides an enumeration of a tree in breadth-first traversal
1059
   * order.
1060
   */
1061
  static class BreadthFirstEnumeration implements Enumeration<TreeNode>
1062
  {
1063
 
1064
      LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
1065
 
1066
      BreadthFirstEnumeration(TreeNode node)
1067
      {
1068
          queue.add(node);
1069
      }
1070
 
1071
      public boolean hasMoreElements()
1072
      {
1073
          return !queue.isEmpty();
1074
      }
1075
 
1076
      @SuppressWarnings("unchecked")
1077
      public TreeNode nextElement()
1078
      {
1079
          if (queue.isEmpty())
1080
              throw new NoSuchElementException("No more elements left.");
1081
 
1082
          TreeNode node = queue.removeFirst();
1083
 
1084
          Enumeration<TreeNode> children =
1085
            (Enumeration<TreeNode>) node.children();
1086
          while (children.hasMoreElements())
1087
              queue.add(children.nextElement());
1088
 
1089
          return node;
1090
      }
1091
  }
1092
 
1093
  /** Provides an enumeration of a tree traversing it
1094
   * preordered.
1095
   */
1096
  static class PreorderEnumeration implements Enumeration<TreeNode>
1097
  {
1098
          TreeNode next;
1099
 
1100
      Stack<Enumeration<TreeNode>> childrenEnums =
1101
        new Stack<Enumeration<TreeNode>>();
1102
 
1103
      @SuppressWarnings("unchecked")
1104
      PreorderEnumeration(TreeNode node)
1105
      {
1106
          next = node;
1107
          childrenEnums.push((Enumeration<TreeNode>) node.children());
1108
      }
1109
 
1110
      public boolean hasMoreElements()
1111
      {
1112
          return next != null;
1113
      }
1114
 
1115
      public TreeNode nextElement()
1116
      {
1117
          if (next == null)
1118
              throw new NoSuchElementException("No more elements left.");
1119
 
1120
          TreeNode current = next;
1121
 
1122
          Enumeration<TreeNode> children = childrenEnums.peek();
1123
 
1124
          // Retrieves the next element.
1125
          next = traverse(children);
1126
 
1127
          return current;
1128
      }
1129
 
1130
      @SuppressWarnings("unchecked")
1131
      private TreeNode traverse(Enumeration<TreeNode> children)
1132
      {
1133
          // If more children are available step down.
1134
          if (children.hasMoreElements())
1135
          {
1136
              TreeNode child = children.nextElement();
1137
              childrenEnums.push((Enumeration<TreeNode>) child.children());
1138
 
1139
              return child;
1140
          }
1141
 
1142
          // If no children are left, we return to a higher level.
1143
          childrenEnums.pop();
1144
 
1145
          // If there are no more levels left, there is no next
1146
          // element to return.
1147
          if (childrenEnums.isEmpty())
1148
              return null;
1149
          else
1150
          {
1151
              return traverse(childrenEnums.peek());
1152
          }
1153
      }
1154
   }
1155
 
1156
  /** Provides an enumeration of a tree traversing it
1157
   * postordered (= depth-first).
1158
   */
1159
   static class PostorderEnumeration implements Enumeration<TreeNode>
1160
   {
1161
 
1162
       Stack<TreeNode> nodes = new Stack<TreeNode>();
1163
       Stack<Enumeration<TreeNode>> childrenEnums =
1164
         new Stack<Enumeration<TreeNode>>();
1165
 
1166
       @SuppressWarnings("unchecked")
1167
       PostorderEnumeration(TreeNode node)
1168
       {
1169
           nodes.push(node);
1170
           childrenEnums.push((Enumeration<TreeNode>) node.children());
1171
       }
1172
 
1173
       public boolean hasMoreElements()
1174
       {
1175
           return !nodes.isEmpty();
1176
       }
1177
 
1178
       public TreeNode nextElement()
1179
       {
1180
           if (nodes.isEmpty())
1181
               throw new NoSuchElementException("No more elements left!");
1182
 
1183
           Enumeration<TreeNode> children = childrenEnums.peek();
1184
 
1185
           return traverse(children);
1186
       }
1187
 
1188
       @SuppressWarnings("unchecked")
1189
       private TreeNode traverse(Enumeration<TreeNode> children)
1190
       {
1191
           if (children.hasMoreElements())
1192
           {
1193
               TreeNode node = children.nextElement();
1194
               nodes.push(node);
1195
 
1196
               Enumeration<TreeNode> newChildren =
1197
                 (Enumeration<TreeNode>) node.children();
1198
               childrenEnums.push(newChildren);
1199
 
1200
               return traverse(newChildren);
1201
           }
1202
           else
1203
           {
1204
               childrenEnums.pop();
1205
 
1206
               // Returns the node whose children
1207
               // have all been visited. (= postorder)
1208
               TreeNode next = nodes.peek();
1209
               nodes.pop();
1210
 
1211
               return next;
1212
           }
1213
       }
1214
 
1215
    }
1216
 
1217
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.