1 /* DefaultMutableTreeNode.java --
2 Copyright (C) 2002 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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., 59 Temple Place, Suite 330, Boston, MA
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
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. */
39 package javax
.swing
.tree
;
41 import java
.io
.IOException
;
42 import java
.io
.ObjectInputStream
;
43 import java
.io
.ObjectOutputStream
;
44 import java
.io
.Serializable
;
45 import java
.util
.ArrayList
;
46 import java
.util
.Enumeration
;
47 import java
.util
.Random
;
48 import java
.util
.Stack
;
49 import java
.util
.Vector
;
52 * DefaultMutableTreeNode
53 * @author Andrew Selkirk
55 public class DefaultMutableTreeNode
56 implements Cloneable
, MutableTreeNode
, Serializable
58 static final long serialVersionUID
= -4298474751201349152L;
60 //-------------------------------------------------------------
61 // Variables --------------------------------------------------
62 //-------------------------------------------------------------
67 public static final Enumeration EMPTY_ENUMERATION
= null; // TODO
72 protected MutableTreeNode parent
= null;
77 protected Vector children
= new Vector();
82 protected transient Object userObject
= "";
87 protected boolean allowsChildren
= true;
90 //-------------------------------------------------------------
91 // Initialization ---------------------------------------------
92 //-------------------------------------------------------------
95 * Constructor DefaultMutableTreeNode
97 public DefaultMutableTreeNode() {
99 } // DefaultMutableTreeNode()
102 * Constructor DefaultMutableTreeNode
105 public DefaultMutableTreeNode(Object userObject
) {
106 this.userObject
= userObject
;
107 } // DefaultMutableTreeNode()
110 * Constructor DefaultMutableTreeNode
114 public DefaultMutableTreeNode(Object userObject
, boolean allowsChildren
) {
115 this.userObject
= userObject
;
116 this.allowsChildren
= allowsChildren
;
117 } // DefaultMutableTreeNode()
120 //-------------------------------------------------------------
121 // Methods ----------------------------------------------------
122 //-------------------------------------------------------------
128 public Object
clone() {
136 public String
toString() {
137 if (userObject
== null) {
140 return userObject
.toString();
147 public void add(MutableTreeNode child
) {
149 child
.setParent(this);
156 public TreeNode
getParent() {
164 public void remove(int index
) {
165 children
.remove(index
);
172 public void remove(MutableTreeNode node
) {
173 children
.remove(node
);
179 * @exception IOException TODO
181 private void writeObject(ObjectOutputStream value0
) throws IOException
{
188 * @exception IOException TODO
189 * @exception ClassNotFoundException TODO
191 private void readObject(ObjectInputStream value0
) throws IOException
, ClassNotFoundException
{
200 public void insert(MutableTreeNode node
, int index
) {
201 children
.insertElementAt(node
, index
);
206 * @returns TreeNode[]
208 public TreeNode
[] getPath() {
216 // Determine length of Path
217 size
= getLevel() + 1;
220 path
= new TreeNode
[size
];
222 for (index
= size
- 1; index
>= 0; index
--) {
223 path
[index
] = current
;
224 current
= current
.getParent();
234 * @returns Enumeration
236 public Enumeration
children() {
237 return children
.elements();
244 public void setParent(MutableTreeNode node
) {
253 public TreeNode
getChildAt(int index
) {
254 return (TreeNode
) children
.elementAt(index
);
261 public int getChildCount() {
262 return children
.size();
270 public int getIndex(TreeNode node
) {
271 return children
.indexOf(node
);
278 public void setAllowsChildren(boolean allowsChildren
) {
279 this.allowsChildren
= allowsChildren
;
280 } // setAllowsChildren()
286 public boolean getAllowsChildren() {
287 return allowsChildren
;
288 } // getAllowsChildren()
294 public void setUserObject(Object userObject
) {
295 this.userObject
= userObject
;
302 public Object
getUserObject() {
309 public void removeFromParent() {
312 } // removeFromParent()
317 public void removeAllChildren() {
318 children
.removeAllElements();
319 } // removeAllChildren()
326 public boolean isNodeAncestor(TreeNode node
) {
336 // Search For Ancestor
338 while (current
!= null && current
!= node
) {
339 current
= current
.getParent();
342 // Check for Ancestor
343 if (current
== node
) {
350 } // isNodeAncestor()
357 public boolean isNodeDescendant(DefaultMutableTreeNode node
) {
367 // Search For Descendant
369 while (current
!= null && current
!= this) {
370 current
= current
.getParent();
373 // Check for Descendant
374 if (current
== this) {
381 } // isNodeDescendant()
388 public TreeNode
getSharedAncestor(DefaultMutableTreeNode node
) {
394 // Get List of Path Elements for this node
396 list
= new ArrayList();
397 while (current
!= null) {
399 current
= current
.getParent();
402 // Check if any path element of node are in list
404 while (current
!= null) {
405 if (list
.contains(current
) == true) {
408 current
= current
.getParent();
411 // Unable to locate shared ancestor
414 } // getSharedAncestor()
421 public boolean isNodeRelated(DefaultMutableTreeNode node
) {
428 // Check for the same root
429 if (node
.getRoot() == getRoot()) {
433 // Nodes are not related
442 public int getDepth() {
452 // Check for children
453 if (allowsChildren
== false || children
.size() == 0) {
459 stack
.push(new Integer(0));
460 node
= getChildAt(0);
461 //System.out.println(" * Descend: 0-0");
464 while (stack
.empty() == false) {
466 // Check if node has children
467 if (node
.getChildCount() != 0) {
468 node
= node
.getChildAt(0);
469 stack
.push(new Integer(0));
471 // System.out.println(" * Descend: 0-" + current);
473 // Check for next sibling
477 if (current
> depth
) {
483 // Traverse to Parent
484 node
= node
.getParent();
485 size
= node
.getChildCount();
487 index
= ((Integer
) stack
.pop()).intValue();
488 // System.out.println(" * Ascend from: " + index + "-" + current);
491 } while (index
>= size
&& node
!= this);
495 node
= node
.getChildAt(index
);
496 stack
.push(new Integer(index
));
498 // System.out.println(" * Descend: " + index + "-" + current);
509 static Random random
= new Random(System
.currentTimeMillis());
511 public static void growTree(DefaultMutableTreeNode root
) {
515 DefaultMutableTreeNode node
;
516 DefaultMutableTreeNode current
;
520 // while (current != root) {
523 // if (random.nextInt(3) < 2) {
524 if (random
.nextBoolean()) {
525 node
= new DefaultMutableTreeNode(String
.valueOf(index
));
530 current
= (DefaultMutableTreeNode
) current
.getParent();
534 } while (current
!= root
&& current
!= null);
536 System
.out
.println("Number of nodes: " + index
);
540 size = random.nextInt(4);
542 for (index = 0; index < size; index++) {
545 node = new DefaultMutableTreeNode(String.valueOf(index));
555 public static void main(String
[] argv
) {
557 DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("node1");
558 DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("node2");
559 DefaultMutableTreeNode node3 = new DefaultMutableTreeNode("node3");
560 DefaultMutableTreeNode node4 = new DefaultMutableTreeNode("node4");
561 DefaultMutableTreeNode node5 = new DefaultMutableTreeNode("node5");
562 DefaultMutableTreeNode node6 = new DefaultMutableTreeNode("node6");
563 DefaultMutableTreeNode node7 = new DefaultMutableTreeNode("node7");
564 DefaultMutableTreeNode node8 = new DefaultMutableTreeNode("node8");
574 System.out.println("Depth (node1): " + node1.getDepth());
575 System.out.println("Depth (node2): " + node2.getDepth());
576 System.out.println("Depth (node3): " + node3.getDepth());
579 System
.out
.println("Create tree...");
580 DefaultMutableTreeNode root
= new DefaultMutableTreeNode("root");
582 System
.out
.println("Find depth...");
583 System
.out
.println("Depth (root): " + root
.getDepth());
591 public int getLevel() {
601 current
= current
.getParent();
603 } while (current
!= null);
613 * @returns TreeNode[]
615 protected TreeNode
[] getPathToRoot(TreeNode value0
, int value1
) {
623 public Object
[] getUserObjectPath() {
630 // Get Path for Tree Nodes
633 // Construct Object Path
634 object
= new Object
[path
.length
];
635 for (index
= 0; index
< path
.length
; index
++) {
636 object
[index
] = ((DefaultMutableTreeNode
) path
[index
]).getUserObject();
639 // Return Object Path
642 } // getUserObjectPath()
648 public TreeNode
getRoot() {
656 check
= current
.getParent();
657 while (check
!= null) {
659 check
= current
.getParent();
670 public boolean isRoot() {
671 return (parent
== null);
676 * @returns DefaultMutableTreeNode
678 public DefaultMutableTreeNode
getNextNode() {
684 * @returns DefaultMutableTreeNode
686 public DefaultMutableTreeNode
getPreviousNode() {
688 } // getPreviousNode()
691 * preorderEnumeration
692 * @returns Enumeration
694 public Enumeration
preorderEnumeration() {
696 } // preorderEnumeration()
699 * postorderEnumeration
700 * @returns Enumeration
702 public Enumeration
postorderEnumeration() {
704 } // postorderEnumeration()
707 * breadthFirstEnumeration
708 * @returns Enumeration
710 public Enumeration
breadthFirstEnumeration() {
712 } // breadthFirstEnumeration()
715 * depthFirstEnumeration
716 * @returns Enumeration
718 public Enumeration
depthFirstEnumeration() {
720 } // depthFirstEnumeration()
723 * pathFromAncestorEnumeration
725 * @returns Enumeration
727 public Enumeration
pathFromAncestorEnumeration(TreeNode value0
) {
729 } // pathFromAncestorEnumeration()
736 public boolean isNodeChild(TreeNode node
) {
748 while (current
!= null) {
749 if (current
== this) {
752 current
= current
.getParent();
755 // Node not located in path, not child
764 public TreeNode
getFirstChild() {
765 return (TreeNode
) children
.firstElement();
772 public TreeNode
getLastChild() {
773 return (TreeNode
) children
.lastElement();
781 public TreeNode
getChildAfter(TreeNode node
) {
787 if (node
== null || node
.getParent() != this) {
788 throw new IllegalArgumentException();
791 // Get index of child node
792 index
= getIndex(node
);
794 // Check for child after
796 if (index
== getChildCount()) {
800 // Retrieve Child After
801 return getChildAt(index
);
810 public TreeNode
getChildBefore(TreeNode node
) {
816 if (node
== null || node
.getParent() != this) {
817 throw new IllegalArgumentException();
820 // Get index of child node
821 index
= getIndex(node
);
823 // Check for child before
829 // Retrieve Child Before
830 return getChildAt(index
);
832 } // getChildBefore()
839 public boolean isNodeSibling(TreeNode node
) {
846 // Check if nodes share a parent
847 if (node
.getParent() == getParent() && getParent() != null) {
851 // Nodes are not siblings
860 public int getSiblingCount() {
864 // Check for no parent
865 if (parent
== null) {
869 // Calculate sibling count from parent's child count
870 return parent
.getChildCount();
872 } // getSiblingCount()
876 * @returns DefaultMutableTreeNode
878 public DefaultMutableTreeNode
getNextSibling() {
885 if (parent
== null) {
889 // Get Index of this node
890 index
= parent
.getIndex(this);
892 // Check for Next Sibling
893 size
= parent
.getChildCount();
899 return (DefaultMutableTreeNode
) parent
.getChildAt(index
);
901 } // getNextSibling()
905 * @returns DefaultMutableTreeNode
907 public DefaultMutableTreeNode
getPreviousSibling() {
913 if (parent
== null) {
917 // Get Index of this node
918 index
= parent
.getIndex(this);
920 // Check for Previous Sibling
926 return (DefaultMutableTreeNode
) parent
.getChildAt(index
);
928 } // getPreviousSibling()
934 public boolean isLeaf() {
935 return (children
.size() == 0); // TODO: check allowsChildren??
940 * @returns DefaultMutableTreeNode
942 public DefaultMutableTreeNode
getFirstLeaf() {
948 while (current
.getChildCount() > 0) {
949 current
= current
.getChildAt(0);
952 return (DefaultMutableTreeNode
) current
;
958 * @returns DefaultMutableTreeNode
960 public DefaultMutableTreeNode
getLastLeaf() {
967 size
= current
.getChildCount();
969 current
= current
.getChildAt(size
- 1);
970 size
= current
.getChildCount();
973 return (DefaultMutableTreeNode
) current
;
979 * @returns DefaultMutableTreeNode
981 public DefaultMutableTreeNode
getNextLeaf() {
987 * @returns DefaultMutableTreeNode
989 public DefaultMutableTreeNode
getPreviousLeaf() {
991 } // getPreviousLeaf()
997 public int getLeafCount() {
1004 // Get Enumeration of all descendants
1005 e
= depthFirstEnumeration();
1009 while (e
.hasMoreElements() == true) {
1010 current
= (TreeNode
) e
.nextElement();
1011 if (current
.isLeaf() == true) {
1021 } // DefaultMutableTreeNode