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