1 /*
2 * $Source: /usr/cvsroot/melati/melati/src/main/java/org/melati/util/ChildrenDrivenMutableTree.java,v $
3 * $Revision: 1.7 $
4 *
5 * Copyright (C) 2001 Myles Chippendale
6 *
7 * Part of Melati (http://melati.org), a framework for the rapid
8 * development of clean, maintainable web applications.
9 *
10 * Melati is free software; Permission is granted to copy, distribute
11 * and/or modify this software under the terms either:
12 *
13 * a) the GNU General Public License as published by the Free Software
14 * Foundation; either version 2 of the License, or (at your option)
15 * any later version,
16 *
17 * or
18 *
19 * b) any version of the Melati Software License, as published
20 * at http://melati.org
21 *
22 * You should have received a copy of the GNU General Public License and
23 * the Melati Software License along with this program;
24 * if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26 * GNU General Public License and visit http://melati.org to obtain the
27 * Melati Software License.
28 *
29 * Feel free to contact the Developers of Melati (http://melati.org),
30 * if you would like to work out a different arrangement than the options
31 * outlined here. It is our intention to allow Melati to be used by as
32 * wide an audience as possible.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * Contact details for copyright holder:
40 *
41 * Myles Chippendale <mylesc At paneris.org>
42 */
43 package org.melati.util;
44
45 import javax.swing.tree.DefaultMutableTreeNode;
46 import java.util.Vector;
47 import java.util.Enumeration;
48 import org.melati.poem.Treeable;
49
50 /**
51 * A tree of <code>DefaultMutableTreeNode</code>s,
52 * the <code>userObject</code>s of which
53 * are {@link Treeable} objects which supply their own
54 * <code>getChildren()</code> functions.
55 * This is used to build the tree of
56 * <code>DefaultMutableTreeNode</code>s.
57 * <p>
58 * It also allows you to search the subtree for a particular
59 * {@link Treeable} object and returns the corresponding
60 * <code>DefaultMutableTreeNode</code> object if one exists.
61 *
62 * @see DefaultMutableTreeNode
63 *
64 * @since 04/10/2000
65 * @author Myles Chippendale
66 **/
67
68
69 public class ChildrenDrivenMutableTree {
70
71 /**
72 * An enumeration that is always empty. This is used when an enumeration
73 * of a leaf node's children is requested.
74 */
75 public static final Enumeration EMPTY_ENUMERATION =
76 DefaultMutableTreeNode.EMPTY_ENUMERATION;
77
78 /** root node */
79 protected DefaultMutableTreeNode root;
80
81 /**
82 * Constructor.
83 */
84 public ChildrenDrivenMutableTree() {
85 this(null);
86 }
87
88 /**
89 * Constructor.
90 * @param userObject the root
91 */
92 public ChildrenDrivenMutableTree(Treeable userObject) {
93 root = new DefaultMutableTreeNode(userObject);
94 buildTree();
95 }
96
97 /**
98 * Compute the children.
99 */
100 public void buildTree() {
101 buildTree(computeChildren(root));
102 }
103
104 /**
105 * Compute the children given the nodes.
106 * @param nodes an Enumeration of nodes
107 */
108 public void buildTree(Enumeration nodes) {
109 while (nodes.hasMoreElements())
110 buildTree(computeChildren((DefaultMutableTreeNode)nodes.nextElement()));
111 }
112
113 private static Enumeration computeChildren(DefaultMutableTreeNode node) {
114 if (node == null)
115 return EMPTY_ENUMERATION;
116 Treeable[] kids = ((Treeable)node.getUserObject()).getChildren();
117 for(int i = 0; i<kids.length; i++) {
118 node.add(new DefaultMutableTreeNode(kids[i]));
119 }
120 return node.children();
121 }
122
123
124 /**
125 * Find a node in a tree.
126 * @param search the node object
127 * @return a tree node
128 */
129 public DefaultMutableTreeNode getTreeNodeFor(Treeable search) {
130
131 Vector agenda = new Vector();
132 agenda.addElement(root);
133
134 while (!agenda.isEmpty()) {
135 DefaultMutableTreeNode current =
136 (DefaultMutableTreeNode)agenda.firstElement();
137 if (current == null)
138 return null;
139 if (current.getUserObject() == search)
140 return current;
141
142 agenda.removeElementAt(0);
143 Enumeration kids = current.children();
144 while(kids.hasMoreElements()) {
145 agenda.addElement(kids.nextElement());
146 }
147 }
148 return null;
149 }
150
151 /**
152 * @return the root
153 */
154 public DefaultMutableTreeNode getRoot() {
155 return root;
156 }
157
158 /**
159 * Return an enumeration of nodes in preorder, whatever
160 * that means.
161 * <p>
162 * Root is first node. What is the difference
163 * from breadth first?
164 * @return the nodes
165 */
166 public Enumeration preorderEnumeration() {
167 return root.preorderEnumeration();
168 }
169
170 /**
171 * Return an enumeration of nodes in postorder, whatever
172 * that means.
173 * <p>
174 * Leftmost leaf is first. What is the difference
175 * from depth first?
176 * @return the nodes
177 */
178 public Enumeration postorderEnumeration() {
179 return root.postorderEnumeration();
180 }
181
182 /**
183 * @return an enumeration of nodes in breadth first order.
184 */
185 public Enumeration breadthFirstEnumeration() {
186 return root.breadthFirstEnumeration();
187 }
188
189 /**
190 * @return an enumeration of nodes in depth first order.
191 */
192 public Enumeration depthFirstEnumeration() {
193 return root.depthFirstEnumeration();
194 }
195 }