1 /*
2 * @(#)HashMapElement.java 1.36 02/03/21
3 *
4 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
5 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6 */
7 package org.enhydra.xml;
8
9 import java.io.File;
10 import java.io.FileOutputStream;
11 import java.util.ArrayList;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.HashMap;
15 import java.util.HashMap;
16
17 import org.w3c.dom.Attr;
18 import org.w3c.dom.Document;
19 import org.w3c.dom.Element;
20 import org.w3c.dom.DOMException;
21 import org.w3c.dom.NamedNodeMap;
22 import org.w3c.dom.Node;
23 import org.w3c.dom.NodeList;
24
25 /***
26 * @author Tweety
27 *
28 * A class representing a node in a meta-data tree, which implements
29 * the <a href="../../../../api/org/w3c/dom/Element.html">
30 *
31 * <p> Namespaces are ignored in this implementation. The terms "tag
32 * name" and "node name" are always considered to be synonymous.
33 *
34 * @version 1.0
35 */
36 public class HashMapElement extends ElementImpl {
37
38
39 /***
40 * All <code>Element<code> type children of this <code>Element<code>
41 */
42 protected HashMap children = null;
43
44
45 /***
46 * Constructs an empty <code>HashMapElement</code>.
47 */
48 public HashMapElement() {
49 super();
50 children = new HashMap();
51 }
52
53
54 /***
55 * Constructs a <code>HashMapElement</code> from the given node,
56 * without creating entire children subtree.
57 *
58 * @param element, as a <code>HashMapElement</code>.
59 */
60 public HashMapElement(HashMapElement element) {
61 super(element);
62 children = element.children;
63 }
64
65
66 /***
67 * Constructs an <code>HashMapElement</code> with the given
68 * document owner and node name.
69 *
70 * @param ownerDoc the document owner of the node, as a <code>Document</code>.
71 * @param nodeName the name of the node, as a <code>String</code>.
72 */
73 public HashMapElement(Document ownerDoc, String name) {
74 super(ownerDoc, name);
75 this.children = new HashMap();
76 }
77
78
79 /***
80 * Constructs an <code>HashMapElement</code> with the given
81 * document owner, node name, node type and node value.
82 *
83 * @param ownerDoc the document owner of the node, as a <code>Document</code>.
84 * @param nodeName the name of the node, as a <code>String</code>.
85 * @param type the type of the node, as a <code>short</code>.
86 * @param value the value of the node, as a <code>String</code>.
87 */
88 protected HashMapElement(Document ownerDoc, String nodeName, short type, String value) {
89 super(ownerDoc, nodeName, type, value);
90 }
91
92
93 /***
94 * Constructs an <code>HashMapElement</code> from a given node
95 * (creates the children subtree too), as a <code>Node</code>
96 *
97 * @param node, as a <code>Node</code>.
98 */
99 public HashMapElement(Node node) {
100 this(node, true);
101 }
102
103 /***
104 * Constructs an <code>HashMapElement</code> from a given node,
105 * as a <code>Node</code>, and deep as <code>boolean</code>.
106 *
107 * @param node, as a <code>Node</code>.
108 * @param deep if <code>true</code>, recursively clone the subtree
109 * under the specified node; if <code>false</code>, clone only the
110 * node itself.
111 */
112 public HashMapElement(Node node, boolean deep) {
113 super(node, false);
114 children = new HashMap();
115 if (deep)
116 initNodeImplChildren(node);
117 }
118
119
120 /***
121 * Creates new instance of the HashMapElement class from the given <code>Node</code>.
122 *
123 * @param node, as a <code>Node</code>.
124 *
125 * @return new instance of the HashMapElement class.
126 */
127 protected Node newElementInstance(Node node) {
128 return new HashMapElement(node);
129 }
130
131 /***
132 * Creates new instance of <code>HashMapElement</code> from a given document
133 * as a <code>Document</code>.
134 *
135 * @param document document.
136 *
137 * @return new <code>Element</code> node as a root of the <code>Document</code>.
138 */
139 public static Element newInstance(Document document) {
140 Node root = document.getDocumentElement();
141 return new HashMapElement(root);
142 }
143
144 /***
145 * Inserts the node <code>newChild</code> before the existing
146 * child node <code>refChild</code>. If <code>refChild</code> is
147 * <code>null</code>, insert <code>newChild</code> at the end of
148 * the list of children.
149 *
150 * @param newChild the <code>Node</code> to insert.
151 * @param refChild the reference <code>Node</code>.
152 *
153 * @return the node being inserted.
154 *
155 * @exception IllegalArgumentException if <code>newChild</code> is
156 * <code>null</code>.
157 */
158 public Node insertBefore(Node newChild, Node refChild) {
159 super.insertBefore(newChild, refChild);
160
161 if (newChild.getNodeType() == ELEMENT_NODE) {
162 HashMapElement newChildNode = (HashMapElement) newChild;
163
164 List list = (List) children.get(newChildNode.getTagName());
165 if (list == null)
166 list = new ArrayList();
167 list.add(newChildNode);
168 children.put(newChildNode.getTagName(), list);
169 }
170 return newChild;
171 }
172
173
174 /***
175 * Replaces the child node <code>oldChild</code> with
176 * <code>newChild</code> in the list of children, and returns the
177 * <code>oldChild</code> node.
178 *
179 * @param newChild the <code>Node</code> to insert.
180 * @param oldChild the <code>Node</code> to be replaced.
181 *
182 * @return the node replaced.
183 *
184 * @exception IllegalArgumentException if <code>newChild</code> is
185 * <code>null</code>.
186 */
187 public Node replaceChild(Node newChild, Node oldChild) {
188 super.replaceChild(newChild, oldChild);
189
190 if (oldChild.getNodeType() == ELEMENT_NODE) {
191 HashMapElement oldChildNode = (HashMapElement) oldChild;
192 List list = (List) children.get(oldChildNode.getTagName());
193 if (list != null) {
194 int index = list.indexOf(oldChildNode);
195 if (index != -1)
196 list.remove(index);
197 if (list.size() == 0)
198 children.remove(oldChildNode.getTagName());
199 }
200 }
201 if (newChild.getNodeType() == ELEMENT_NODE) {
202 HashMapElement newChildNode = (HashMapElement) newChild;
203 List list = (List) children.get(newChildNode.getTagName());
204 if (list == null)
205 list = new ArrayList();
206 list.add(newChildNode);
207 children.put(newChildNode.getTagName(), list);
208 }
209
210 return oldChild;
211 }
212
213
214 /***
215 * Removes the child node indicated by <code>oldChild</code> from
216 * the list of children, and returns it.
217 *
218 * @param oldChild the <code>Node</code> to be removed.
219 *
220 * @return the node removed.
221 *
222 * @exception IllegalArgumentException if <code>oldChild</code> is
223 * <code>null</code>.
224 */
225 public Node removeChild(Node oldChild) {
226 super.removeChild(oldChild);
227
228 if (oldChild.getNodeType() == ELEMENT_NODE) {
229 HashMapElement oldChildNode = (HashMapElement) oldChild;
230
231 List list = (List) children.get(oldChildNode.getTagName());
232 if (list != null) {
233 int index = list.indexOf(oldChildNode);
234 if (index != -1)
235 list.remove(index);
236 if (list.size() == 0)
237 children.remove(oldChildNode.getTagName());
238 }
239 }
240 return oldChild;
241 }
242
243
244 /***
245 * Returns a duplicate of this node. The duplicate node has no
246 * parent (<code>getParentNode</code> returns <code>null</code>).
247 * If a shallow clone is being performed (<code>deep</code> is
248 * <code>false</code>), the new node will not have any children or
249 * siblings. If a deep clone is being performed, the new node
250 * will form the root of a complete cloned subtree.
251 *
252 * @param deep if <code>true</code>, recursively clone the subtree
253 * under the specified node; if <code>false</code>, clone only the
254 * node itself.
255 *
256 * @return the duplicate node.
257 */
258 public Node cloneNode(boolean deep) {
259 return new HashMapElement(this, deep);
260 }
261
262
263
264 /***
265 * Returns all <code>Element</code> nodes with given name,
266 * searching by all sub nodes from this node.
267 *
268 * @param name tag name.
269 *
270 * @return all <code>Element</code> vith given name as <code>NodeList</code>.
271 */
272 public NodeList getElementsByTagName(String name) {
273 List list = new ArrayList();
274
275 // added for new search
276 if (nodeName.equals(name)) {
277 list.add(this);
278 }
279
280 getElementsByTagName(name, list);
281 return new NodeListImpl(list);
282 }
283
284
285 private void getElementsByTagName(String name, List list) {
286 if (numChildren == 0)
287 return;
288 List fList = (List) children.get(name);
289 if (fList != null);
290 list.addAll(fList);
291 for (Iterator iter = children.values().iterator(); iter.hasNext();) {
292 fList = (List) iter.next();
293 for (int i = 0; i < fList.size(); i++) {
294 ((HashMapElement) fList.get(i)).getElementsByTagName(
295 name,
296 list);
297 }
298 }
299 }
300
301
302 /***
303 * Returns <code>true</code> if this node has child nodes.
304 *
305 * @return <code>true</code> if this node has children.
306 */
307 public boolean hasElementChildNodes() {
308 return children.size() > 0;
309 }
310
311
312 /***
313 * Returns the list of all children nodes with the given tag name.
314 *
315 * @param name tag name.
316 *
317 * @return the list of all children nodes with the given tag name.
318 */
319 public NodeList getChildrenByTagName(String name) {
320 List list = (List) this.children.get(name);
321 if (list != null)
322 return new NodeListImpl(list);
323 return null;
324 }
325
326
327 /***
328 * Returns the first child <code>Element</code> with the given tag name.
329 *
330 * @param name tag name.
331 *
332 * @return the first child <code>Element</code> with the given tag name.
333 */
334 public Element getFirstChildByTagName(String name) {
335 NodeList children = getChildrenByTagName(name);
336 if (children != null && children.getLength() > 0)
337 return (HashMapElement) children.item(0);
338 return null;
339 }
340
341
342 /***
343 * Returns the next <code>Element</code> node (if exists) with the same tag name.
344 *
345 * @return the next <code>Element</code> node (if exists) with the same tag name.
346 */
347 public Element getNextSameNameNode() {
348 try {
349 HashMapElement parent = (HashMapElement) this.getParentNode();
350 List tagList = (List) parent.children.get(this.nodeName);
351 int index = tagList.indexOf(this);
352 if (++index <= tagList.size())
353 return (HashMapElement) tagList.get(index);
354 } catch (NullPointerException e) {
355 throw new NodeDOMException(
356 DOMException.NOT_FOUND_ERR,
357 "Root node doesn't have a successor");
358 }
359 return null;
360 }
361
362
363 /***
364 * Returns the concatenation of values of all text type children.
365 *
366 * @return the concatenation of values of all text type children.
367 */
368 public String getText() {
369 String text = "";
370 Node child = this.getFirstChild();
371 while (child != null) {
372 if (child.getNodeType() == Node.TEXT_NODE)
373 text += child.getNodeValue();
374 child = child.getNextSibling();
375 }
376 if (!text.equals(""))
377 return text;
378 return null;
379 }
380
381
382 /***
383 * Set the value of the first text child node to the given text,
384 * and remove all other text child nodes.
385 *
386 * @param text new text.
387 */
388 public void setText(String text) {
389 Node child = this.getFirstChild();
390 if (child != null) {
391 child.setNodeValue(text);
392 child = child.getNextSibling();
393 while (child != null) {
394 if (child.getNodeType() == Node.TEXT_NODE) {
395 Node temp = child;
396 child = child.getNextSibling();
397 this.removeChild(temp);
398 } else {
399 child = child.getNextSibling();
400 }
401 }
402 }
403 }
404
405
406 }
This page automatically generated by Maven