1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.webapp.admin;
20
21
22 import java.io.Serializable;
23 import java.util.HashMap;
24
25
26 /***
27 * <p>The overall data structure representing a <em>tree control</em>
28 * that can be rendered by the <code>TreeControlTag</code> custom tag.
29 * Each node of the tree is represented by an instance of
30 * <code>TreeControlNode</code>.</p>
31 *
32 * @author Jazmin Jonson
33 * @author Craig R. McClanahan
34 * @version $Revision: 516448 $ $Date: 2007-03-09 17:25:47 +0100 (Fri, 09 Mar 2007) $
35 */
36
37 public class TreeControl implements Serializable
38 {
39 private static final long serialVersionUID = 1;
40
41
42
43
44
45 /***
46 * Construct a new instance with no predefined root node.
47 */
48 public TreeControl() {
49
50 super();
51 setRoot(null);
52
53 }
54
55
56 /***
57 * Construct a new instance with the specified root node.
58 *
59 * @param root The new root node
60 */
61 public TreeControl(TreeControlNode root) {
62
63 super();
64 setRoot(root);
65
66 }
67
68
69
70
71
72 /***
73 * The collection of nodes that represent this tree, keyed by name.
74 */
75 protected HashMap registry = new HashMap();
76
77
78 /***
79 * The most recently selected node.
80 */
81 protected TreeControlNode selected = null;
82
83
84
85
86
87 /***
88 * The root node of the entire tree.
89 */
90 protected TreeControlNode root = null;
91
92 public TreeControlNode getRoot() {
93 return (this.root);
94 }
95
96 protected void setRoot(TreeControlNode root) {
97 if (this.root != null)
98 removeNode(this.root);
99 if (root != null)
100 addNode(root);
101 root.setLast(true);
102 this.root = root;
103 }
104
105
106 /***
107 * The current displayable "width" of this tree (that is, the maximum
108 * depth of the visible part of the tree).
109 */
110 public int getWidth() {
111
112 if (root == null)
113 return (0);
114 else
115 return (getWidth(root));
116
117 }
118
119
120
121
122
123 /***
124 * Find and return the <code>TreeControlNode</code> for the specified
125 * node name, if it exists; otherwise, return <code>null</code>.
126 *
127 * @param name Name of the <code>TreeControlNode</code> to be returned
128 */
129 public TreeControlNode findNode(String name) {
130
131 synchronized (registry) {
132 return ((TreeControlNode) registry.get(name));
133 }
134
135 }
136
137
138 /***
139 * Mark the specified node as the one-and-only currently selected one,
140 * deselecting any previous node that was so marked.
141 *
142 * @param node Name of the node to mark as selected, or <code>null</code>
143 * if there should be no currently selected node
144 */
145 public void selectNode(String name) {
146
147 if (selected != null) {
148 selected.setSelected(false);
149 selected = null;
150 }
151 selected = findNode(name);
152 if (selected != null)
153 selected.setSelected(true);
154
155 }
156
157
158
159
160
161 /***
162 * Register the specified node in our registry of the complete tree.
163 *
164 * @param node The <code>TreeControlNode</code> to be registered
165 *
166 * @exception IllegalArgumentException if the name of this node
167 * is not unique
168 */
169 void addNode(TreeControlNode node) throws IllegalArgumentException {
170
171 synchronized (registry) {
172 String name = node.getName();
173 if (registry.containsKey(name))
174 {
175
176
177 }
178 node.setTree(this);
179 registry.put(name, node);
180 }
181
182 }
183
184
185 /***
186 * Calculate the width of the subtree below the specified node.
187 *
188 * @param node The node for which to calculate the width
189 */
190 int getWidth(TreeControlNode node) {
191
192 int width = node.getWidth();
193 if (!node.isExpanded())
194 return (width);
195 TreeControlNode children[] = node.findChildren();
196 for (int i = 0; i < children.length; i++) {
197 int current = getWidth(children[i]);
198 if (current > width)
199 width = current;
200 }
201 return (width);
202
203 }
204
205
206 /***
207 * Deregister the specified node, as well as all child nodes of this
208 * node, from our registry of the complete tree. If this node is not
209 * present, no action is taken.
210 *
211 * @param node The <code>TreeControlNode</code> to be deregistered
212 */
213 public void removeNode(TreeControlNode node)
214 {
215
216 synchronized (registry) {
217 TreeControlNode children[] = node.findChildren();
218 for (int i = 0; i < children.length; i++)
219 removeNode(children[i]);
220 TreeControlNode parent = node.getParent();
221 if (parent != null) {
222 parent.removeChild(node);
223 }
224 node.setParent(null);
225 node.setTree(null);
226 if (node == this.root) {
227 this.root = null;
228 }
229 registry.remove(node.getName());
230 }
231
232 }
233
234
235 }