1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.jasper.xmlparser;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.Iterator;
24
25
26 /***
27 * Simplified implementation of a Node from a Document Object Model (DOM)
28 * parse of an XML document. This class is used to represent a DOM tree
29 * so that the XML parser's implementation of <code>org.w3c.dom</code> need
30 * not be visible to the remainder of Jasper.
31 * <p/>
32 * <strong>WARNING</strong> - Construction of a new tree, or modifications
33 * to an existing one, are not thread-safe and such accesses must be
34 * synchronized.
35 *
36 * @author Craig R. McClanahan
37 * @version $Revision: 466606 $ $Date: 2006-10-21 17:07:12 -0600 (Sat, 21 Oct 2006) $
38 */
39
40 public class TreeNode {
41
42
43
44
45
46 /***
47 * Construct a new node with no parent.
48 *
49 * @param name The name of this node
50 */
51 public TreeNode(String name) {
52
53 this(name, null);
54
55 }
56
57
58 /***
59 * Construct a new node with the specified parent.
60 *
61 * @param name The name of this node
62 * @param parent The node that is the parent of this node
63 */
64 public TreeNode(String name, TreeNode parent) {
65
66 super();
67 this.name = name;
68 this.parent = parent;
69 if (this.parent != null)
70 this.parent.addChild(this);
71
72 }
73
74
75
76
77
78 /***
79 * The attributes of this node, keyed by attribute name,
80 * Instantiated only if required.
81 */
82 protected HashMap attributes = null;
83
84
85 /***
86 * The body text associated with this node (if any).
87 */
88 protected String body = null;
89
90
91 /***
92 * The children of this node, instantiated only if required.
93 */
94 protected ArrayList children = null;
95
96
97 /***
98 * The name of this node.
99 */
100 protected String name = null;
101
102
103 /***
104 * The parent node of this node.
105 */
106 protected TreeNode parent = null;
107
108
109
110
111
112 /***
113 * Add an attribute to this node, replacing any existing attribute
114 * with the same name.
115 *
116 * @param name The attribute name to add
117 * @param value The new attribute value
118 */
119 public void addAttribute(String name, String value) {
120
121 if (attributes == null)
122 attributes = new HashMap();
123 attributes.put(name, value);
124
125 }
126
127
128 /***
129 * Add a new child node to this node.
130 *
131 * @param node The new child node
132 */
133 public void addChild(TreeNode node) {
134
135 if (children == null)
136 children = new ArrayList();
137 children.add(node);
138
139 }
140
141
142 /***
143 * Return the value of the specified node attribute if it exists, or
144 * <code>null</code> otherwise.
145 *
146 * @param name Name of the requested attribute
147 */
148 public String findAttribute(String name) {
149
150 if (attributes == null)
151 return (null);
152 else
153 return ((String) attributes.get(name));
154
155 }
156
157
158 /***
159 * Return an Iterator of the attribute names of this node. If there are
160 * no attributes, an empty Iterator is returned.
161 */
162 public Iterator findAttributes() {
163
164 if (attributes == null)
165 return (Collections.EMPTY_LIST.iterator());
166 else
167 return (attributes.keySet().iterator());
168
169 }
170
171
172 /***
173 * Return the first child node of this node with the specified name,
174 * if there is one; otherwise, return <code>null</code>.
175 *
176 * @param name Name of the desired child element
177 */
178 public TreeNode findChild(String name) {
179
180 if (children == null)
181 return (null);
182 Iterator items = children.iterator();
183 while (items.hasNext()) {
184 TreeNode item = (TreeNode) items.next();
185 if (name.equals(item.getName()))
186 return (item);
187 }
188 return (null);
189
190 }
191
192
193 /***
194 * Return an Iterator of all children of this node. If there are no
195 * children, an empty Iterator is returned.
196 */
197 public Iterator findChildren() {
198
199 if (children == null)
200 return (Collections.EMPTY_LIST.iterator());
201 else
202 return (children.iterator());
203
204 }
205
206
207 /***
208 * Return an Iterator over all children of this node that have the
209 * specified name. If there are no such children, an empty Iterator
210 * is returned.
211 *
212 * @param name Name used to select children
213 */
214 public Iterator findChildren(String name) {
215
216 if (children == null)
217 return (Collections.EMPTY_LIST.iterator());
218
219 ArrayList results = new ArrayList();
220 Iterator items = children.iterator();
221 while (items.hasNext()) {
222 TreeNode item = (TreeNode) items.next();
223 if (name.equals(item.getName()))
224 results.add(item);
225 }
226 return (results.iterator());
227
228 }
229
230
231 /***
232 * Return the body text associated with this node (if any).
233 */
234 public String getBody() {
235
236 return (this.body);
237
238 }
239
240
241 /***
242 * Return the name of this node.
243 */
244 public String getName() {
245
246 return (this.name);
247
248 }
249
250
251 /***
252 * Remove any existing value for the specified attribute name.
253 *
254 * @param name The attribute name to remove
255 */
256 public void removeAttribute(String name) {
257
258 if (attributes != null)
259 attributes.remove(name);
260
261 }
262
263
264 /***
265 * Remove a child node from this node, if it is one.
266 *
267 * @param node The child node to remove
268 */
269 public void removeNode(TreeNode node) {
270
271 if (children != null)
272 children.remove(node);
273
274 }
275
276
277 /***
278 * Set the body text associated with this node (if any).
279 *
280 * @param body The body text (if any)
281 */
282 public void setBody(String body) {
283
284 this.body = body;
285
286 }
287
288
289 /***
290 * Return a String representation of this TreeNode.
291 */
292 public String toString() {
293
294 StringBuffer sb = new StringBuffer();
295 toString(sb, 0, this);
296 return (sb.toString());
297
298 }
299
300
301
302
303
304 /***
305 * Append to the specified StringBuffer a character representation of
306 * this node, with the specified amount of indentation.
307 *
308 * @param sb The StringBuffer to append to
309 * @param indent Number of characters of indentation
310 * @param node The TreeNode to be printed
311 */
312 protected void toString(StringBuffer sb, int indent,
313 TreeNode node) {
314
315 int indent2 = indent + 2;
316
317
318 for (int i = 0; i < indent; i++)
319 sb.append(' ');
320 sb.append('<');
321 sb.append(node.getName());
322 Iterator names = node.findAttributes();
323 while (names.hasNext()) {
324 sb.append(' ');
325 String name = (String) names.next();
326 sb.append(name);
327 sb.append("=\"");
328 String value = node.findAttribute(name);
329 sb.append(value);
330 sb.append("\"");
331 }
332 sb.append(">\n");
333
334
335 String body = node.getBody();
336 if ((body != null) && (body.length() > 0)) {
337 for (int i = 0; i < indent2; i++)
338 sb.append(' ');
339 sb.append(body);
340 sb.append("\n");
341 }
342
343
344 Iterator children = node.findChildren();
345 while (children.hasNext()) {
346 TreeNode child = (TreeNode) children.next();
347 toString(sb, indent2, child);
348 }
349
350
351 for (int i = 0; i < indent; i++)
352 sb.append(' ');
353 sb.append("</");
354 sb.append(node.getName());
355 sb.append(">\n");
356
357 }
358
359
360 }