1
2
3
4
5
6
7
8 package org.dom4j.dom;
9
10 import java.util.List;
11
12 import org.dom4j.Branch;
13 import org.dom4j.CharacterData;
14 import org.dom4j.Document;
15 import org.dom4j.DocumentType;
16 import org.dom4j.Element;
17 import org.dom4j.Node;
18
19 import org.w3c.dom.DOMException;
20 import org.w3c.dom.NamedNodeMap;
21 import org.w3c.dom.NodeList;
22
23 /***
24 * <p>
25 * <code>DOMNodeHelper</code> contains a collection of utility methods for use
26 * across Node implementations.
27 * </p>
28 *
29 * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
30 * @version $Revision: 1.20 $
31 */
32 public class DOMNodeHelper {
33 public static final NodeList EMPTY_NODE_LIST = new EmptyNodeList();
34
35 protected DOMNodeHelper() {
36 }
37
38
39
40 public static boolean supports(Node node, String feature, String version) {
41 return false;
42 }
43
44 public static String getNamespaceURI(Node node) {
45 return null;
46 }
47
48 public static String getPrefix(Node node) {
49 return null;
50 }
51
52 public static String getLocalName(Node node) {
53 return null;
54 }
55
56 public static void setPrefix(Node node, String prefix) throws DOMException {
57 notSupported();
58 }
59
60 public static String getNodeValue(Node node) throws DOMException {
61 return node.getText();
62 }
63
64 public static void setNodeValue(Node node, String nodeValue)
65 throws DOMException {
66 node.setText(nodeValue);
67 }
68
69 public static org.w3c.dom.Node getParentNode(Node node) {
70 return asDOMNode(node.getParent());
71 }
72
73 public static NodeList getChildNodes(Node node) {
74 return EMPTY_NODE_LIST;
75 }
76
77 public static org.w3c.dom.Node getFirstChild(Node node) {
78 return null;
79 }
80
81 public static org.w3c.dom.Node getLastChild(Node node) {
82 return null;
83 }
84
85 public static org.w3c.dom.Node getPreviousSibling(Node node) {
86 Element parent = node.getParent();
87
88 if (parent != null) {
89 int index = parent.indexOf(node);
90
91 if (index > 0) {
92 Node previous = parent.node(index - 1);
93
94 return asDOMNode(previous);
95 }
96 }
97
98 return null;
99 }
100
101 public static org.w3c.dom.Node getNextSibling(Node node) {
102 Element parent = node.getParent();
103
104 if (parent != null) {
105 int index = parent.indexOf(node);
106
107 if (index >= 0) {
108 if (++index < parent.nodeCount()) {
109 Node next = parent.node(index);
110
111 return asDOMNode(next);
112 }
113 }
114 }
115
116 return null;
117 }
118
119 public static NamedNodeMap getAttributes(Node node) {
120 return null;
121 }
122
123 public static org.w3c.dom.Document getOwnerDocument(Node node) {
124 return asDOMDocument(node.getDocument());
125 }
126
127 public static org.w3c.dom.Node insertBefore(Node node,
128 org.w3c.dom.Node newChild, org.w3c.dom.Node refChild)
129 throws DOMException {
130 if (node instanceof Branch) {
131 Branch branch = (Branch) node;
132 List list = branch.content();
133 int index = list.indexOf(refChild);
134
135 if (index < 0) {
136 branch.add((Node) newChild);
137 } else {
138 list.add(index, newChild);
139 }
140
141 return newChild;
142 } else {
143 throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
144 "Children not allowed for this node: " + node);
145 }
146 }
147
148 public static org.w3c.dom.Node replaceChild(Node node,
149 org.w3c.dom.Node newChild, org.w3c.dom.Node oldChild)
150 throws DOMException {
151 if (node instanceof Branch) {
152 Branch branch = (Branch) node;
153 List list = branch.content();
154 int index = list.indexOf(oldChild);
155
156 if (index < 0) {
157 throw new DOMException(DOMException.NOT_FOUND_ERR,
158 "Tried to replace a non existing child " + "for node: "
159 + node);
160 }
161
162 list.set(index, newChild);
163
164 return oldChild;
165 } else {
166 throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
167 "Children not allowed for this node: " + node);
168 }
169 }
170
171 public static org.w3c.dom.Node removeChild(Node node,
172 org.w3c.dom.Node oldChild) throws DOMException {
173 if (node instanceof Branch) {
174 Branch branch = (Branch) node;
175 branch.remove((Node) oldChild);
176
177 return oldChild;
178 }
179
180 throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
181 "Children not allowed for this node: " + node);
182 }
183
184 public static org.w3c.dom.Node appendChild(Node node,
185 org.w3c.dom.Node newChild) throws DOMException {
186 if (node instanceof Branch) {
187 Branch branch = (Branch) node;
188 org.w3c.dom.Node previousParent = newChild.getParentNode();
189
190 if (previousParent != null) {
191 previousParent.removeChild(newChild);
192 }
193
194 branch.add((Node) newChild);
195
196 return newChild;
197 }
198
199 throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
200 "Children not allowed for this node: " + node);
201 }
202
203 public static boolean hasChildNodes(Node node) {
204 return false;
205 }
206
207 public static org.w3c.dom.Node cloneNode(Node node, boolean deep) {
208 return asDOMNode((Node) node.clone());
209 }
210
211 public static void normalize(Node node) {
212 notSupported();
213 }
214
215 public static boolean isSupported(Node n, String feature, String version) {
216 return false;
217 }
218
219 public static boolean hasAttributes(Node node) {
220 if ((node != null) && node instanceof Element) {
221 return ((Element) node).attributeCount() > 0;
222 } else {
223 return false;
224 }
225 }
226
227
228
229 public static String getData(CharacterData charData) throws DOMException {
230 return charData.getText();
231 }
232
233 public static void setData(CharacterData charData, String data)
234 throws DOMException {
235 charData.setText(data);
236 }
237
238 public static int getLength(CharacterData charData) {
239 String text = charData.getText();
240
241 return (text != null) ? text.length() : 0;
242 }
243
244 public static String substringData(CharacterData charData, int offset,
245 int count) throws DOMException {
246 if (count < 0) {
247 throw new DOMException(DOMException.INDEX_SIZE_ERR,
248 "Illegal value for count: " + count);
249 }
250
251 String text = charData.getText();
252 int length = (text != null) ? text.length() : 0;
253
254 if ((offset < 0) || (offset >= length)) {
255 throw new DOMException(DOMException.INDEX_SIZE_ERR,
256 "No text at offset: " + offset);
257 }
258
259 if ((offset + count) > length) {
260 return text.substring(offset);
261 }
262
263 return text.substring(offset, offset + count);
264 }
265
266 public static void appendData(CharacterData charData, String arg)
267 throws DOMException {
268 if (charData.isReadOnly()) {
269 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
270 "CharacterData node is read only: " + charData);
271 } else {
272 String text = charData.getText();
273
274 if (text == null) {
275 charData.setText(text);
276 } else {
277 charData.setText(text + arg);
278 }
279 }
280 }
281
282 public static void insertData(CharacterData data, int offset, String arg)
283 throws DOMException {
284 if (data.isReadOnly()) {
285 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
286 "CharacterData node is read only: " + data);
287 } else {
288 String text = data.getText();
289
290 if (text == null) {
291 data.setText(arg);
292 } else {
293 int length = text.length();
294
295 if ((offset < 0) || (offset > length)) {
296 throw new DOMException(DOMException.INDEX_SIZE_ERR,
297 "No text at offset: " + offset);
298 } else {
299 StringBuffer buffer = new StringBuffer(text);
300 buffer.insert(offset, arg);
301 data.setText(buffer.toString());
302 }
303 }
304 }
305 }
306
307 public static void deleteData(CharacterData charData, int offset, int count)
308 throws DOMException {
309 if (charData.isReadOnly()) {
310 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
311 "CharacterData node is read only: " + charData);
312 } else {
313 if (count < 0) {
314 throw new DOMException(DOMException.INDEX_SIZE_ERR,
315 "Illegal value for count: " + count);
316 }
317
318 String text = charData.getText();
319
320 if (text != null) {
321 int length = text.length();
322
323 if ((offset < 0) || (offset >= length)) {
324 throw new DOMException(DOMException.INDEX_SIZE_ERR,
325 "No text at offset: " + offset);
326 } else {
327 StringBuffer buffer = new StringBuffer(text);
328 buffer.delete(offset, offset + count);
329 charData.setText(buffer.toString());
330 }
331 }
332 }
333 }
334
335 public static void replaceData(CharacterData charData, int offset,
336 int count, String arg) throws DOMException {
337 if (charData.isReadOnly()) {
338 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
339 "CharacterData node is read only: " + charData);
340 } else {
341 if (count < 0) {
342 throw new DOMException(DOMException.INDEX_SIZE_ERR,
343 "Illegal value for count: " + count);
344 }
345
346 String text = charData.getText();
347
348 if (text != null) {
349 int length = text.length();
350
351 if ((offset < 0) || (offset >= length)) {
352 throw new DOMException(DOMException.INDEX_SIZE_ERR,
353 "No text at offset: " + offset);
354 } else {
355 StringBuffer buffer = new StringBuffer(text);
356 buffer.replace(offset, offset + count, arg);
357 charData.setText(buffer.toString());
358 }
359 }
360 }
361 }
362
363
364
365 public static void appendElementsByTagName(List list, Branch parent,
366 String name) {
367 final boolean isStar = "*".equals(name);
368
369 for (int i = 0, size = parent.nodeCount(); i < size; i++) {
370 Node node = parent.node(i);
371
372 if (node instanceof Element) {
373 Element element = (Element) node;
374
375 if (isStar || name.equals(element.getName())) {
376 list.add(element);
377 }
378
379 appendElementsByTagName(list, element, name);
380 }
381 }
382 }
383
384 public static void appendElementsByTagNameNS(List list, Branch parent,
385 String namespace, String localName) {
386 final boolean isStarNS = "*".equals(namespace);
387 final boolean isStar = "*".equals(localName);
388
389 for (int i = 0, size = parent.nodeCount(); i < size; i++) {
390 Node node = parent.node(i);
391
392 if (node instanceof Element) {
393 Element element = (Element) node;
394
395 if ((isStarNS
396 || (((namespace == null)
397 || (namespace.length() == 0)) && ((element
398 .getNamespaceURI() == null) || (element
399 .getNamespaceURI().length() == 0)))
400 || ((namespace != null) && namespace
401 .equals(element.getNamespaceURI())))
402 && (isStar || localName.equals(element.getName()))) {
403 list.add(element);
404 }
405
406 appendElementsByTagNameNS(list, element, namespace, localName);
407 }
408 }
409 }
410
411
412
413 public static NodeList createNodeList(final List list) {
414 return new NodeList() {
415 public org.w3c.dom.Node item(int index) {
416 if (index >= getLength()) {
417
418
419
420
421
422 return null;
423 } else {
424 return DOMNodeHelper.asDOMNode((Node) list.get(index));
425 }
426 }
427
428 public int getLength() {
429 return list.size();
430 }
431 };
432 }
433
434 public static org.w3c.dom.Node asDOMNode(Node node) {
435 if (node == null) {
436 return null;
437 }
438
439 if (node instanceof org.w3c.dom.Node) {
440 return (org.w3c.dom.Node) node;
441 } else {
442
443 System.out.println("Cannot convert: " + node
444 + " into a W3C DOM Node");
445 notSupported();
446
447 return null;
448 }
449 }
450
451 public static org.w3c.dom.Document asDOMDocument(Document document) {
452 if (document == null) {
453 return null;
454 }
455
456 if (document instanceof org.w3c.dom.Document) {
457 return (org.w3c.dom.Document) document;
458 } else {
459
460 notSupported();
461
462 return null;
463 }
464 }
465
466 public static org.w3c.dom.DocumentType asDOMDocumentType(DocumentType dt) {
467 if (dt == null) {
468 return null;
469 }
470
471 if (dt instanceof org.w3c.dom.DocumentType) {
472 return (org.w3c.dom.DocumentType) dt;
473 } else {
474
475 notSupported();
476
477 return null;
478 }
479 }
480
481 public static org.w3c.dom.Text asDOMText(CharacterData text) {
482 if (text == null) {
483 return null;
484 }
485
486 if (text instanceof org.w3c.dom.Text) {
487 return (org.w3c.dom.Text) text;
488 } else {
489
490 notSupported();
491
492 return null;
493 }
494 }
495
496 public static org.w3c.dom.Element asDOMElement(Node element) {
497 if (element == null) {
498 return null;
499 }
500
501 if (element instanceof org.w3c.dom.Element) {
502 return (org.w3c.dom.Element) element;
503 } else {
504
505 notSupported();
506
507 return null;
508 }
509 }
510
511 public static org.w3c.dom.Attr asDOMAttr(Node attribute) {
512 if (attribute == null) {
513 return null;
514 }
515
516 if (attribute instanceof org.w3c.dom.Attr) {
517 return (org.w3c.dom.Attr) attribute;
518 } else {
519
520 notSupported();
521
522 return null;
523 }
524 }
525
526 /***
527 * Called when a method has not been implemented yet
528 *
529 * @throws DOMException
530 * DOCUMENT ME!
531 */
532 public static void notSupported() {
533 throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
534 "Not supported yet");
535 }
536
537 public static class EmptyNodeList implements NodeList {
538 public org.w3c.dom.Node item(int index) {
539 return null;
540 }
541
542 public int getLength() {
543 return 0;
544 }
545 }
546 }
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583