dom4j - 1.6.1

Clover coverage report - dom4j - 1.6.1
Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00
FRAMES NO FRAMES

file stats: | LOC: | 1.684 |  | Methods: | 115
| NCLOC: | 1.027 |  | Classes: | 1

Source file | Conditionals | Statements | Methods | TOTAL

AbstractElement.java

38,2%

48,1%

53%

45,9%

1 |  | /*
2 |  | * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3 |  | *
4 |  | * This software is open source.
5 |  | * See the bottom of this file for the licence.
6 |  | */
7 |  |
8 |  | package org.dom4j.tree;
9 |  |
10 |  | import java.io.IOException;
11 |  | import java.io.StringWriter;
12 |  | import java.io.Writer;
13 |  | import java.util.ArrayList;
14 |  | import java.util.Collections;
15 |  | import java.util.Iterator;
16 |  | import java.util.List;
17 |  | import java.util.Map;
18 |  |
19 |  | import org.dom4j.Attribute;
20 |  | import org.dom4j.CDATA;
21 |  | import org.dom4j.CharacterData;
22 |  | import org.dom4j.Comment;
23 |  | import org.dom4j.Document;
24 |  | import org.dom4j.DocumentFactory;
25 |  | import org.dom4j.Element;
26 |  | import org.dom4j.Entity;
27 |  | import org.dom4j.IllegalAddException;
28 |  | import org.dom4j.Namespace;
29 |  | import org.dom4j.Node;
30 |  | import org.dom4j.ProcessingInstruction;
31 |  | import org.dom4j.QName;
32 |  | import org.dom4j.Text;
33 |  | import org.dom4j.Visitor;
34 |  | import org.dom4j.io.OutputFormat;
35 |  | import org.dom4j.io.XMLWriter;
36 |  |
37 |  | import org.xml.sax.Attributes;
38 |  |
39 |  | /**
40 |  | * <p>
41 |  | * <code>AbstractElement</code> is an abstract base class for tree
42 |  | * implementors to use for implementation inheritence.
43 |  | * </p>
44 |  | *
45 |  | * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
46 |  | * @version $Revision: 1.80 $
47 |  | */
48 |  | public abstract class AbstractElement extends AbstractBranch implements
49 |  | org.dom4j.Element {
50 |  | /** The <code>DocumentFactory</code> instance used by default */
51 |  | private static final DocumentFactory DOCUMENT_FACTORY = DocumentFactory
52 |  | .getInstance();
53 |  |
54 |  | protected static final List EMPTY_LIST = Collections.EMPTY_LIST;
55 |  |
56 |  | protected static final Iterator EMPTY_ITERATOR = EMPTY_LIST.iterator();
57 |  |
58 |  | protected static final boolean VERBOSE_TOSTRING = false;
59 |  |
60 |  | protected static final boolean USE_STRINGVALUE_SEPARATOR = false;
61 |  |
62 | 96009 | public AbstractElement() {
63 |  | }
64 |  |
65 | 105403 | public short getNodeType() {
66 | 105403 | return ELEMENT_NODE;
67 |  | }
68 |  |
69 | 0 | public boolean isRootElement() {
70 | 0 | Document document = getDocument();
71 |  |
72 | 0 | if (document != null) {
73 | 0 | Element root = document.getRootElement();
74 |  |
75 | 0 | if (root == this) {
76 | 0 | return true;
77 |  | }
78 |  | }
79 |  |
80 | 0 | return false;
81 |  | }
82 |  |
83 | 1 | public void setName(String name) {
84 | 1 | setQName(getDocumentFactory().createQName(name));
85 |  | }
86 |  |
87 | 0 | public void setNamespace(Namespace namespace) {
88 | 0 | setQName(getDocumentFactory().createQName(getName(), namespace));
89 |  | }
90 |  |
91 |  | /**
92 |  | * Returns the XPath expression to match this Elements name which is
93 |  | * getQualifiedName() if there is a namespace prefix defined or if no
94 |  | * namespace is present then it is getName() or if a namespace is defined
95 |  | * with no prefix then the expression is [name()='X'] where X = getName().
96 |  | *
97 |  | * @return DOCUMENT ME!
98 |  | */
99 | 66 | public String getXPathNameStep() {
100 | 66 | String uri = getNamespaceURI();
101 |  |
102 | 66 | if ((uri == null) || (uri.length() == 0)) {
103 | 56 | return getName();
104 |  | }
105 |  |
106 | 10 | String prefix = getNamespacePrefix();
107 |  |
108 | 10 | if ((prefix == null) || (prefix.length() == 0)) {
109 | 8 | return "*[name()='" + getName() + "']";
110 |  | }
111 |  |
112 | 2 | return getQualifiedName();
113 |  | }
114 |  |
115 | 31 | public String getPath(Element context) {
116 | 31 | if (this == context) {
117 | 1 | return ".";
118 |  | }
119 |  |
120 | 30 | Element parent = getParent();
121 |  |
122 | 30 | if (parent == null) {
123 | 11 | return "/" + getXPathNameStep();
124 | 19 | } else if (parent == context) {
125 | 7 | return getXPathNameStep();
126 |  | }
127 |  |
128 | 12 | return parent.getPath(context) + "/" + getXPathNameStep();
129 |  | }
130 |  |
131 | 36 | public String getUniquePath(Element context) {
132 | 36 | Element parent = getParent();
133 |  |
134 | 36 | if (parent == null) {
135 | 13 | return "/" + getXPathNameStep();
136 |  | }
137 |  |
138 | 23 | StringBuffer buffer = new StringBuffer();
139 |  |
140 | 23 | if (parent != context) {
141 | 16 | buffer.append(parent.getUniquePath(context));
142 |  |
143 | 16 | buffer.append("/");
144 |  | }
145 |  |
146 | 23 | buffer.append(getXPathNameStep());
147 |  |
148 | 23 | List mySiblings = parent.elements(getQName());
149 |  |
150 | 23 | if (mySiblings.size() > 1) {
151 | 13 | int idx = mySiblings.indexOf(this);
152 |  |
153 | 13 | if (idx >= 0) {
154 | 13 | buffer.append("[");
155 |  |
156 | 13 | buffer.append(Integer.toString(++idx));
157 |  |
158 | 13 | buffer.append("]");
159 |  | }
160 |  | }
161 |  |
162 | 23 | return buffer.toString();
163 |  | }
164 |  |
165 | 2041 | public String asXML() {
166 | 2041 | try {
167 | 2041 | StringWriter out = new StringWriter();
168 | 2041 | XMLWriter writer = new XMLWriter(out, new OutputFormat());
169 |  |
170 | 2041 | writer.write(this);
171 | 2041 | writer.flush();
172 |  |
173 | 2041 | return out.toString();
174 |  | } catch (IOException e) {
175 | 0 | throw new RuntimeException("IOException while generating "
176 |  | + "textual representation: " + e.getMessage());
177 |  | }
178 |  | }
179 |  |
180 | 0 | public void write(Writer out) throws IOException {
181 | 0 | XMLWriter writer = new XMLWriter(out, new OutputFormat());
182 | 0 | writer.write(this);
183 |  | }
184 |  |
185 |  | /**
186 |  | * <p>
187 |  | * <code>accept</code> method is the <code>Visitor Pattern</code>
188 |  | * method.
189 |  | * </p>
190 |  | *
191 |  | * @param visitor
192 |  | * <code>Visitor</code> is the visitor.
193 |  | */
194 | 0 | public void accept(Visitor visitor) {
195 | 0 | visitor.visit(this);
196 |  |
197 |  | // visit attributes
198 | 0 | for (int i = 0, size = attributeCount(); i < size; i++) {
199 | 0 | Attribute attribute = attribute(i);
200 |  |
201 | 0 | visitor.visit(attribute);
202 |  | }
203 |  |
204 |  | // visit content
205 | 0 | for (int i = 0, size = nodeCount(); i < size; i++) {
206 | 0 | Node node = node(i);
207 |  |
208 | 0 | node.accept(visitor);
209 |  | }
210 |  | }
211 |  |
212 | 85700 | public String toString() {
213 | 85700 | String uri = getNamespaceURI();
214 |  |
215 | 85700 | if ((uri != null) && (uri.length() > 0)) {
216 | 2512 | if (VERBOSE_TOSTRING) {
217 | 0 | return super.toString() + " [Element: <" + getQualifiedName()
218 |  | + " uri: " + uri + " attributes: " + attributeList()
219 |  | + " content: " + contentList() + " />]";
220 |  | } else {
221 | 2512 | return super.toString() + " [Element: <" + getQualifiedName()
222 |  | + " uri: " + uri + " attributes: " + attributeList()
223 |  | + "/>]";
224 |  | }
225 |  | } else {
226 | 83188 | if (VERBOSE_TOSTRING) {
227 | 0 | return super.toString() + " [Element: <" + getQualifiedName()
228 |  | + " attributes: " + attributeList() + " content: "
229 |  | + contentList() + " />]";
230 |  | } else {
231 | 83188 | return super.toString() + " [Element: <" + getQualifiedName()
232 |  | + " attributes: " + attributeList() + "/>]";
233 |  | }
234 |  | }
235 |  | }
236 |  |
237 |  | // QName methods
238 |  | // -------------------------------------------------------------------------
239 | 120477 | public Namespace getNamespace() {
240 | 120477 | return getQName().getNamespace();
241 |  | }
242 |  |
243 | 84347 | public String getName() {
244 | 84347 | return getQName().getName();
245 |  | }
246 |  |
247 | 8774 | public String getNamespacePrefix() {
248 | 8774 | return getQName().getNamespacePrefix();
249 |  | }
250 |  |
251 | 172894 | public String getNamespaceURI() {
252 | 172894 | return getQName().getNamespaceURI();
253 |  | }
254 |  |
255 | 120578 | public String getQualifiedName() {
256 | 120578 | return getQName().getQualifiedName();
257 |  | }
258 |  |
259 | 0 | public Object getData() {
260 | 0 | return getText();
261 |  | }
262 |  |
263 | 0 | public void setData(Object data) {
264 |  | // ignore this method
265 |  | }
266 |  |
267 |  | // Node methods
268 |  | // -------------------------------------------------------------------------
269 | 0 | public Node node(int index) {
270 | 0 | if (index >= 0) {
271 | 0 | List list = contentList();
272 |  |
273 | 0 | if (index >= list.size()) {
274 | 0 | return null;
275 |  | }
276 |  |
277 | 0 | Object node = list.get(index);
278 |  |
279 | 0 | if (node != null) {
280 | 0 | if (node instanceof Node) {
281 | 0 | return (Node) node;
282 |  | } else {
283 | 0 | return getDocumentFactory().createText(node.toString());
284 |  | }
285 |  | }
286 |  | }
287 |  |
288 | 0 | return null;
289 |  | }
290 |  |
291 | 0 | public int indexOf(Node node) {
292 | 0 | return contentList().indexOf(node);
293 |  | }
294 |  |
295 | 1 | public int nodeCount() {
296 | 1 | return contentList().size();
297 |  | }
298 |  |
299 | 0 | public Iterator nodeIterator() {
300 | 0 | return contentList().iterator();
301 |  | }
302 |  |
303 |  | // Element methods
304 |  | // -------------------------------------------------------------------------
305 | 0 | public Element element(String name) {
306 | 0 | List list = contentList();
307 |  |
308 | 0 | int size = list.size();
309 |  |
310 | 0 | for (int i = 0; i < size; i++) {
311 | 0 | Object object = list.get(i);
312 |  |
313 | 0 | if (object instanceof Element) {
314 | 0 | Element element = (Element) object;
315 |  |
316 | 0 | if (name.equals(element.getName())) {
317 | 0 | return element;
318 |  | }
319 |  | }
320 |  | }
321 |  |
322 | 0 | return null;
323 |  | }
324 |  |
325 | 0 | public Element element(QName qName) {
326 | 0 | List list = contentList();
327 |  |
328 | 0 | int size = list.size();
329 |  |
330 | 0 | for (int i = 0; i < size; i++) {
331 | 0 | Object object = list.get(i);
332 |  |
333 | 0 | if (object instanceof Element) {
334 | 0 | Element element = (Element) object;
335 |  |
336 | 0 | if (qName.equals(element.getQName())) {
337 | 0 | return element;
338 |  | }
339 |  | }
340 |  | }
341 |  |
342 | 0 | return null;
343 |  | }
344 |  |
345 | 0 | public Element element(String name, Namespace namespace) {
346 | 0 | return element(getDocumentFactory().createQName(name, namespace));
347 |  | }
348 |  |
349 | 79 | public List elements() {
350 | 79 | List list = contentList();
351 |  |
352 | 79 | BackedList answer = createResultList();
353 |  |
354 | 79 | int size = list.size();
355 |  |
356 | 79 | for (int i = 0; i < size; i++) {
357 | 354 | Object object = list.get(i);
358 |  |
359 | 354 | if (object instanceof Element) {
360 | 145 | answer.addLocal(object);
361 |  | }
362 |  | }
363 |  |
364 | 79 | return answer;
365 |  | }
366 |  |
367 | 201 | public List elements(String name) {
368 | 201 | List list = contentList();
369 |  |
370 | 201 | BackedList answer = createResultList();
371 |  |
372 | 201 | int size = list.size();
373 |  |
374 | 201 | for (int i = 0; i < size; i++) {
375 | 1975 | Object object = list.get(i);
376 |  |
377 | 1975 | if (object instanceof Element) {
378 | 901 | Element element = (Element) object;
379 |  |
380 | 901 | if (name.equals(element.getName())) {
381 | 336 | answer.addLocal(element);
382 |  | }
383 |  | }
384 |  | }
385 |  |
386 | 201 | return answer;
387 |  | }
388 |  |
389 | 13972 | public List elements(QName qName) {
390 | 13972 | List list = contentList();
391 |  |
392 | 13972 | BackedList answer = createResultList();
393 |  |
394 | 13972 | int size = list.size();
395 |  |
396 | 13972 | for (int i = 0; i < size; i++) {
397 | 42383 | Object object = list.get(i);
398 |  |
399 | 42383 | if (object instanceof Element) {
400 | 14661 | Element element = (Element) object;
401 |  |
402 | 14661 | if (qName.equals(element.getQName())) {
403 | 3653 | answer.addLocal(element);
404 |  | }
405 |  | }
406 |  | }
407 |  |
408 | 13972 | return answer;
409 |  | }
410 |  |
411 | 0 | public List elements(String name, Namespace namespace) {
412 | 0 | return elements(getDocumentFactory().createQName(name, namespace));
413 |  | }
414 |  |
415 | 59 | public Iterator elementIterator() {
416 | 59 | List list = elements();
417 |  |
418 | 59 | return list.iterator();
419 |  | }
420 |  |
421 | 191 | public Iterator elementIterator(String name) {
422 | 191 | List list = elements(name);
423 |  |
424 | 191 | return list.iterator();
425 |  | }
426 |  |
427 | 13948 | public Iterator elementIterator(QName qName) {
428 | 13948 | List list = elements(qName);
429 |  |
430 | 13948 | return list.iterator();
431 |  | }
432 |  |
433 | 0 | public Iterator elementIterator(String name, Namespace ns) {
434 | 0 | return elementIterator(getDocumentFactory().createQName(name, ns));
435 |  | }
436 |  |
437 |  | // Attribute methods
438 |  | // -------------------------------------------------------------------------
439 | 0 | public List attributes() {
440 | 0 | return new ContentListFacade(this, attributeList());
441 |  | }
442 |  |
443 | 0 | public Iterator attributeIterator() {
444 | 0 | return attributeList().iterator();
445 |  | }
446 |  |
447 | 0 | public Attribute attribute(int index) {
448 | 0 | return (Attribute) attributeList().get(index);
449 |  | }
450 |  |
451 | 1 | public int attributeCount() {
452 | 1 | return attributeList().size();
453 |  | }
454 |  |
455 | 0 | public Attribute attribute(String name) {
456 | 0 | List list = attributeList();
457 |  |
458 | 0 | int size = list.size();
459 |  |
460 | 0 | for (int i = 0; i < size; i++) {
461 | 0 | Attribute attribute = (Attribute) list.get(i);
462 |  |
463 | 0 | if (name.equals(attribute.getName())) {
464 | 0 | return attribute;
465 |  | }
466 |  | }
467 |  |
468 | 0 | return null;
469 |  | }
470 |  |
471 | 0 | public Attribute attribute(QName qName) {
472 | 0 | List list = attributeList();
473 |  |
474 | 0 | int size = list.size();
475 |  |
476 | 0 | for (int i = 0; i < size; i++) {
477 | 0 | Attribute attribute = (Attribute) list.get(i);
478 |  |
479 | 0 | if (qName.equals(attribute.getQName())) {
480 | 0 | return attribute;
481 |  | }
482 |  | }
483 |  |
484 | 0 | return null;
485 |  | }
486 |  |
487 | 0 | public Attribute attribute(String name, Namespace namespace) {
488 | 0 | return attribute(getDocumentFactory().createQName(name, namespace));
489 |  | }
490 |  |
491 |  | /**
492 |  | * This method provides a more optimal way of setting all the attributes on
493 |  | * an Element particularly for use in {@link org.dom4j.io.SAXReader}.
494 |  | *
495 |  | * @param attributes
496 |  | * DOCUMENT ME!
497 |  | * @param namespaceStack
498 |  | * DOCUMENT ME!
499 |  | * @param noNamespaceAttributes
500 |  | * DOCUMENT ME!
501 |  | */
502 | 86719 | public void setAttributes(Attributes attributes,
503 |  | NamespaceStack namespaceStack, boolean noNamespaceAttributes) {
504 |  | // now lets add all attribute values
505 | 86719 | int size = attributes.getLength();
506 |  |
507 | 86719 | if (size > 0) {
508 | 7896 | DocumentFactory factory = getDocumentFactory();
509 |  |
510 | 7896 | if (size == 1) {
511 |  | // allow lazy construction of the List of Attributes
512 | 6278 | String name = attributes.getQName(0);
513 |  |
514 | 6278 | if (noNamespaceAttributes || !name.startsWith("xmlns")) {
515 | 6270 | String attributeURI = attributes.getURI(0);
516 |  |
517 | 6270 | String attributeLocalName = attributes.getLocalName(0);
518 |  |
519 | 6270 | String attributeValue = attributes.getValue(0);
520 |  |
521 | 6270 | QName attributeQName = namespaceStack.getAttributeQName(
522 |  | attributeURI, attributeLocalName, name);
523 |  |
524 | 6270 | add(factory.createAttribute(this, attributeQName,
525 |  | attributeValue));
526 |  | }
527 |  | } else {
528 | 1618 | List list = attributeList(size);
529 |  |
530 | 1618 | list.clear();
531 |  |
532 | 1618 | for (int i = 0; i < size; i++) {
533 |  | // optimised to avoid the call to attribute(QName) to
534 |  | // lookup an attribute for a given QName
535 | 4190 | String attributeName = attributes.getQName(i);
536 |  |
537 | 4190 | if (noNamespaceAttributes
538 |  | || !attributeName.startsWith("xmlns")) {
539 | 4185 | String attributeURI = attributes.getURI(i);
540 |  |
541 | 4185 | String attributeLocalName = attributes.getLocalName(i);
542 |  |
543 | 4185 | String attributeValue = attributes.getValue(i);
544 |  |
545 | 4185 | QName attributeQName = namespaceStack
546 |  | .getAttributeQName(attributeURI,
547 |  | attributeLocalName, attributeName);
548 |  |
549 | 4185 | Attribute attribute = factory.createAttribute(this,
550 |  | attributeQName, attributeValue);
551 |  |
552 | 4185 | list.add(attribute);
553 |  |
554 | 4185 | childAdded(attribute);
555 |  | }
556 |  | }
557 |  | }
558 |  | }
559 |  | }
560 |  |
561 | 1984 | public String attributeValue(String name) {
562 | 1984 | Attribute attrib = attribute(name);
563 |  |
564 | 1984 | if (attrib == null) {
565 | 586 | return null;
566 |  | } else {
567 | 1398 | return attrib.getValue();
568 |  | }
569 |  | }
570 |  |
571 | 4 | public String attributeValue(QName qName) {
572 | 4 | Attribute attrib = attribute(qName);
573 |  |
574 | 4 | if (attrib == null) {
575 | 2 | return null;
576 |  | } else {
577 | 2 | return attrib.getValue();
578 |  | }
579 |  | }
580 |  |
581 | 7 | public String attributeValue(String name, String defaultValue) {
582 | 7 | String answer = attributeValue(name);
583 |  |
584 | 7 | return (answer != null) ? answer : defaultValue;
585 |  | }
586 |  |
587 | 0 | public String attributeValue(QName qName, String defaultValue) {
588 | 0 | String answer = attributeValue(qName);
589 |  |
590 | 0 | return (answer != null) ? answer : defaultValue;
591 |  | }
592 |  |
593 |  | /**
594 |  | * DOCUMENT ME!
595 |  | *
596 |  | * @param name
597 |  | * DOCUMENT ME!
598 |  | * @param value
599 |  | * DOCUMENT ME!
600 |  | *
601 |  | * @deprecated As of version 0.5. Please use {@link
602 |  | * #addAttribute(String,String)} instead. WILL BE REMOVED IN
603 |  | * dom4j-1.6 !!
604 |  | */
605 | 0 | public void setAttributeValue(String name, String value) {
606 | 0 | addAttribute(name, value);
607 |  | }
608 |  |
609 |  | /**
610 |  | * DOCUMENT ME!
611 |  | *
612 |  | * @param qName
613 |  | * DOCUMENT ME!
614 |  | * @param value
615 |  | * DOCUMENT ME!
616 |  | *
617 |  | * @deprecated As of version 0.5. Please use {@link
618 |  | * #addAttribute(String,String)} instead. WILL BE REMOVED IN
619 |  | * dom4j-1.6 !!
620 |  | */
621 | 0 | public void setAttributeValue(QName qName, String value) {
622 | 0 | addAttribute(qName, value);
623 |  | }
624 |  |
625 | 0 | public void add(Attribute attribute) {
626 | 0 | if (attribute.getParent() != null) {
627 | 0 | String message = "The Attribute already has an existing parent \""
628 |  | + attribute.getParent().getQualifiedName() + "\"";
629 |  |
630 | 0 | throw new IllegalAddException(this, attribute, message);
631 |  | }
632 |  |
633 | 0 | if (attribute.getValue() == null) {
634 |  | // try remove a previous attribute with the same
635 |  | // name since adding an attribute with a null value
636 |  | // is equivalent to removing it.
637 | 0 | Attribute oldAttribute = attribute(attribute.getQName());
638 |  |
639 | 0 | if (oldAttribute != null) {
640 | 0 | remove(oldAttribute);
641 |  | }
642 |  | } else {
643 | 0 | attributeList().add(attribute);
644 |  |
645 | 0 | childAdded(attribute);
646 |  | }
647 |  | }
648 |  |
649 | 0 | public boolean remove(Attribute attribute) {
650 | 0 | List list = attributeList();
651 |  |
652 | 0 | boolean answer = list.remove(attribute);
653 |  |
654 | 0 | if (answer) {
655 | 0 | childRemoved(attribute);
656 |  | } else {
657 |  | // we may have a copy of the attribute
658 | 0 | Attribute copy = attribute(attribute.getQName());
659 |  |
660 | 0 | if (copy != null) {
661 | 0 | list.remove(copy);
662 |  |
663 | 0 | answer = true;
664 |  | }
665 |  | }
666 |  |
667 | 0 | return answer;
668 |  | }
669 |  |
670 |  | // Processing instruction API
671 |  | // -------------------------------------------------------------------------
672 | 0 | public List processingInstructions() {
673 | 0 | List list = contentList();
674 |  |
675 | 0 | BackedList answer = createResultList();
676 |  |
677 | 0 | int size = list.size();
678 |  |
679 | 0 | for (int i = 0; i < size; i++) {
680 | 0 | Object object = list.get(i);
681 |  |
682 | 0 | if (object instanceof ProcessingInstruction) {
683 | 0 | answer.addLocal(object);
684 |  | }
685 |  | }
686 |  |
687 | 0 | return answer;
688 |  | }
689 |  |
690 | 0 | public List processingInstructions(String target) {
691 | 0 | List list = contentList();
692 |  |
693 | 0 | BackedList answer = createResultList();
694 |  |
695 | 0 | int size = list.size();
696 |  |
697 | 0 | for (int i = 0; i < size; i++) {
698 | 0 | Object object = list.get(i);
699 |  |
700 | 0 | if (object instanceof ProcessingInstruction) {
701 | 0 | ProcessingInstruction pi = (ProcessingInstruction) object;
702 |  |
703 | 0 | if (target.equals(pi.getName())) {
704 | 0 | answer.addLocal(pi);
705 |  | }
706 |  | }
707 |  | }
708 |  |
709 | 0 | return answer;
710 |  | }
711 |  |
712 | 0 | public ProcessingInstruction processingInstruction(String target) {
713 | 0 | List list = contentList();
714 |  |
715 | 0 | int size = list.size();
716 |  |
717 | 0 | for (int i = 0; i < size; i++) {
718 | 0 | Object object = list.get(i);
719 |  |
720 | 0 | if (object instanceof ProcessingInstruction) {
721 | 0 | ProcessingInstruction pi = (ProcessingInstruction) object;
722 |  |
723 | 0 | if (target.equals(pi.getName())) {
724 | 0 | return pi;
725 |  | }
726 |  | }
727 |  | }
728 |  |
729 | 0 | return null;
730 |  | }
731 |  |
732 | 0 | public boolean removeProcessingInstruction(String target) {
733 | 0 | List list = contentList();
734 |  |
735 | 0 | for (Iterator iter = list.iterator(); iter.hasNext();) {
736 | 0 | Object object = iter.next();
737 |  |
738 | 0 | if (object instanceof ProcessingInstruction) {
739 | 0 | ProcessingInstruction pi = (ProcessingInstruction) object;
740 |  |
741 | 0 | if (target.equals(pi.getName())) {
742 | 0 | iter.remove();
743 |  |
744 | 0 | return true;
745 |  | }
746 |  | }
747 |  | }
748 |  |
749 | 0 | return false;
750 |  | }
751 |  |
752 |  | // Content Model methods
753 |  | // -------------------------------------------------------------------------
754 | 2 | public Node getXPathResult(int index) {
755 | 2 | Node answer = node(index);
756 |  |
757 | 2 | if ((answer != null) && !answer.supportsParent()) {
758 | 0 | return answer.asXPathResult(this);
759 |  | }
760 |  |
761 | 2 | return answer;
762 |  | }
763 |  |
764 | 1631 | public Element addAttribute(String name, String value) {
765 |  | // adding a null value is equivalent to removing the attribute
766 | 1631 | Attribute attribute = attribute(name);
767 |  |
768 | 1631 | if (value != null) {
769 | 1628 | if (attribute == null) {
770 | 1627 | add(getDocumentFactory().createAttribute(this, name, value));
771 | 1 | } else if (attribute.isReadOnly()) {
772 | 0 | remove(attribute);
773 |  |
774 | 0 | add(getDocumentFactory().createAttribute(this, name, value));
775 |  | } else {
776 | 1 | attribute.setValue(value);
777 |  | }
778 | 3 | } else if (attribute != null) {
779 | 2 | remove(attribute);
780 |  | }
781 |  |
782 | 1631 | return this;
783 |  | }
784 |  |
785 | 2845 | public Element addAttribute(QName qName, String value) {
786 |  | // adding a null value is equivalent to removing the attribute
787 | 2845 | Attribute attribute = attribute(qName);
788 |  |
789 | 2845 | if (value != null) {
790 | 2843 | if (attribute == null) {
791 | 2843 | add(getDocumentFactory().createAttribute(this, qName, value));
792 | 0 | } else if (attribute.isReadOnly()) {
793 | 0 | remove(attribute);
794 |  |
795 | 0 | add(getDocumentFactory().createAttribute(this, qName, value));
796 |  | } else {
797 | 0 | attribute.setValue(value);
798 |  | }
799 | 2 | } else if (attribute != null) {
800 | 1 | remove(attribute);
801 |  | }
802 |  |
803 | 2845 | return this;
804 |  | }
805 |  |
806 | 102 | public Element addCDATA(String cdata) {
807 | 102 | CDATA node = getDocumentFactory().createCDATA(cdata);
808 |  |
809 | 102 | addNewNode(node);
810 |  |
811 | 102 | return this;
812 |  | }
813 |  |
814 | 491 | public Element addComment(String comment) {
815 | 491 | Comment node = getDocumentFactory().createComment(comment);
816 |  |
817 | 491 | addNewNode(node);
818 |  |
819 | 491 | return this;
820 |  | }
821 |  |
822 | 1654 | public Element addElement(String name) {
823 | 1654 | DocumentFactory factory = getDocumentFactory();
824 |  |
825 | 1654 | int index = name.indexOf(":");
826 |  |
827 | 1654 | String prefix = "";
828 |  |
829 | 1654 | String localName = name;
830 |  |
831 | 1654 | Namespace namespace = null;
832 |  |
833 | 1654 | if (index > 0) {
834 | 2 | prefix = name.substring(0, index);
835 |  |
836 | 2 | localName = name.substring(index + 1);
837 |  |
838 | 2 | namespace = getNamespaceForPrefix(prefix);
839 |  |
840 | 2 | if (namespace == null) {
841 | 0 | throw new IllegalAddException("No such namespace prefix: "
842 |  | + prefix + " is in scope on: " + this
843 |  | + " so cannot add element: " + name);
844 |  | }
845 |  | } else {
846 | 1652 | namespace = getNamespaceForPrefix("");
847 |  | }
848 |  |
849 | 1654 | Element node;
850 |  |
851 | 1654 | if (namespace != null) {
852 | 1654 | QName qname = factory.createQName(localName, namespace);
853 |  |
854 | 1654 | node = factory.createElement(qname);
855 |  | } else {
856 | 0 | node = factory.createElement(name);
857 |  | }
858 |  |
859 | 1654 | addNewNode(node);
860 |  |
861 | 1654 | return node;
862 |  | }
863 |  |
864 | 4 | public Element addEntity(String name, String text) {
865 | 4 | Entity node = getDocumentFactory().createEntity(name, text);
866 |  |
867 | 4 | addNewNode(node);
868 |  |
869 | 4 | return this;
870 |  | }
871 |  |
872 | 11 | public Element addNamespace(String prefix, String uri) {
873 | 11 | Namespace node = getDocumentFactory().createNamespace(prefix, uri);
874 |  |
875 | 11 | addNewNode(node);
876 |  |
877 | 11 | return this;
878 |  | }
879 |  |
880 | 1 | public Element addProcessingInstruction(String target, String data) {
881 | 1 | ProcessingInstruction node = getDocumentFactory()
882 |  | .createProcessingInstruction(target, data);
883 |  |
884 | 1 | addNewNode(node);
885 |  |
886 | 1 | return this;
887 |  | }
888 |  |
889 | 0 | public Element addProcessingInstruction(String target, Map data) {
890 | 0 | ProcessingInstruction node = getDocumentFactory()
891 |  | .createProcessingInstruction(target, data);
892 |  |
893 | 0 | addNewNode(node);
894 |  |
895 | 0 | return this;
896 |  | }
897 |  |
898 | 121732 | public Element addText(String text) {
899 | 121732 | Text node = getDocumentFactory().createText(text);
900 |  |
901 | 121732 | addNewNode(node);
902 |  |
903 | 121732 | return this;
904 |  | }
905 |  |
906 |  | // polymorphic node methods
907 | 370 | public void add(Node node) {
908 | 370 | switch (node.getNodeType()) {
909 | 128 | case ELEMENT_NODE:
910 | 128 | add((Element) node);
911 |  |
912 | 128 | break;
913 |  |
914 | 0 | case ATTRIBUTE_NODE:
915 | 0 | add((Attribute) node);
916 |  |
917 | 0 | break;
918 |  |
919 | 231 | case TEXT_NODE:
920 | 231 | add((Text) node);
921 |  |
922 | 231 | break;
923 |  |
924 | 0 | case CDATA_SECTION_NODE:
925 | 0 | add((CDATA) node);
926 |  |
927 | 0 | break;
928 |  |
929 | 0 | case ENTITY_REFERENCE_NODE:
930 | 0 | add((Entity) node);
931 |  |
932 | 0 | break;
933 |  |
934 | 0 | case PROCESSING_INSTRUCTION_NODE:
935 | 0 | add((ProcessingInstruction) node);
936 |  |
937 | 0 | break;
938 |  |
939 | 3 | case COMMENT_NODE:
940 | 3 | add((Comment) node);
941 |  |
942 | 3 | break;
943 |  |
944 |  | /*
945 |  | * XXXX: to do! case DOCUMENT_TYPE_NODE: add((DocumentType) node);
946 |  | * break;
947 |  | */
948 | 8 | case NAMESPACE_NODE:
949 | 8 | add((Namespace) node);
950 |  |
951 | 8 | break;
952 |  |
953 | 0 | default:
954 | 0 | invalidNodeTypeAddException(node);
955 |  | }
956 |  | }
957 |  |
958 | 1515 | public boolean remove(Node node) {
959 | 1515 | switch (node.getNodeType()) {
960 | 1513 | case ELEMENT_NODE:
961 | 1513 | return remove((Element) node);
962 |  |
963 | 2 | case ATTRIBUTE_NODE:
964 | 2 | return remove((Attribute) node);
965 |  |
966 | 0 | case TEXT_NODE:
967 | 0 | return remove((Text) node);
968 |  |
969 | 0 | case CDATA_SECTION_NODE:
970 | 0 | return remove((CDATA) node);
971 |  |
972 | 0 | case ENTITY_REFERENCE_NODE:
973 | 0 | return remove((Entity) node);
974 |  |
975 | 0 | case PROCESSING_INSTRUCTION_NODE:
976 | 0 | return remove((ProcessingInstruction) node);
977 |  |
978 | 0 | case COMMENT_NODE:
979 | 0 | return remove((Comment) node);
980 |  |
981 |  | /*
982 |  | * case DOCUMENT_TYPE_NODE: return remove((DocumentType) node);
983 |  | */
984 | 0 | case NAMESPACE_NODE:
985 | 0 | return remove((Namespace) node);
986 |  |
987 | 0 | default:
988 | 0 | return false;
989 |  | }
990 |  | }
991 |  |
992 |  | // typesafe versions using node classes
993 | 0 | public void add(CDATA cdata) {
994 | 0 | addNode(cdata);
995 |  | }
996 |  |
997 | 3 | public void add(Comment comment) {
998 | 3 | addNode(comment);
999 |  | }
1000 |  |
1001 | 89668 | public void add(Element element) {
1002 | 89668 | addNode(element);
1003 |  | }
1004 |  |
1005 | 0 | public void add(Entity entity) {
1006 | 0 | addNode(entity);
1007 |  | }
1008 |  |
1009 | 5944 | public void add(Namespace namespace) {
1010 | 5944 | addNode(namespace);
1011 |  | }
1012 |  |
1013 | 0 | public void add(ProcessingInstruction pi) {
1014 | 0 | addNode(pi);
1015 |  | }
1016 |  |
1017 | 231 | public void add(Text text) {
1018 | 231 | addNode(text);
1019 |  | }
1020 |  |
1021 | 0 | public boolean remove(CDATA cdata) {
1022 | 0 | return removeNode(cdata);
1023 |  | }
1024 |  |
1025 | 0 | public boolean remove(Comment comment) {
1026 | 0 | return removeNode(comment);
1027 |  | }
1028 |  |
1029 | 1513 | public boolean remove(Element element) {
1030 | 1513 | return removeNode(element);
1031 |  | }
1032 |  |
1033 | 0 | public boolean remove(Entity entity) {
1034 | 0 | return removeNode(entity);
1035 |  | }
1036 |  |
1037 | 3 | public boolean remove(Namespace namespace) {
1038 | 3 | return removeNode(namespace);
1039 |  | }
1040 |  |
1041 | 0 | public boolean remove(ProcessingInstruction pi) {
1042 | 0 | return removeNode(pi);
1043 |  | }
1044 |  |
1045 | 12026 | public boolean remove(Text text) {
1046 | 12026 | return removeNode(text);
1047 |  | }
1048 |  |
1049 |  | // Helper methods
1050 |  | // -------------------------------------------------------------------------
1051 | 0 | public boolean hasMixedContent() {
1052 | 0 | List content = contentList();
1053 |  |
1054 | 0 | if ((content == null) || content.isEmpty() || (content.size() < 2)) {
1055 | 0 | return false;
1056 |  | }
1057 |  |
1058 | 0 | Class prevClass = null;
1059 |  |
1060 | 0 | for (Iterator iter = content.iterator(); iter.hasNext();) {
1061 | 0 | Object object = iter.next();
1062 |  |
1063 | 0 | Class newClass = object.getClass();
1064 |  |
1065 | 0 | if (newClass != prevClass) {
1066 | 0 | if (prevClass != null) {
1067 | 0 | return true;
1068 |  | }
1069 |  |
1070 | 0 | prevClass = newClass;
1071 |  | }
1072 |  | }
1073 |  |
1074 | 0 | return false;
1075 |  | }
1076 |  |
1077 | 2 | public boolean isTextOnly() {
1078 | 2 | List content = contentList();
1079 |  |
1080 | 2 | if ((content == null) || content.isEmpty()) {
1081 | 0 | return true;
1082 |  | }
1083 |  |
1084 | 2 | for (Iterator iter = content.iterator(); iter.hasNext();) {
1085 | 2 | Object object = iter.next();
1086 |  |
1087 | 2 | if (!(object instanceof CharacterData)
1088 |  | && !(object instanceof String)) {
1089 | 1 | return false;
1090 |  | }
1091 |  | }
1092 |  |
1093 | 1 | return true;
1094 |  | }
1095 |  |
1096 | 2017 | public void setText(String text) {
1097 |  | /* remove all text nodes */
1098 | 2017 | List allContent = contentList();
1099 |  |
1100 | 2017 | if (allContent != null) {
1101 | 2017 | Iterator it = allContent.iterator();
1102 |  |
1103 | 2017 | while (it.hasNext()) {
1104 | 9 | Node node = (Node) it.next();
1105 |  |
1106 | 9 | switch (node.getNodeType()) {
1107 | 0 | case CDATA_SECTION_NODE:
1108 |  |
1109 |  | // case ENTITY_NODE:
1110 | 0 | case ENTITY_REFERENCE_NODE:
1111 | 8 | case TEXT_NODE:
1112 | 8 | it.remove();
1113 |  |
1114 | 1 | default:
1115 | 9 | break;
1116 |  | }
1117 |  | }
1118 |  | }
1119 |  |
1120 | 2017 | addText(text);
1121 |  | }
1122 |  |
1123 | 0 | public String getStringValue() {
1124 | 0 | List list = contentList();
1125 |  |
1126 | 0 | int size = list.size();
1127 |  |
1128 | 0 | if (size > 0) {
1129 | 0 | if (size == 1) {
1130 |  | // optimised to avoid StringBuffer creation
1131 | 0 | return getContentAsStringValue(list.get(0));
1132 |  | } else {
1133 | 0 | StringBuffer buffer = new StringBuffer();
1134 |  |
1135 | 0 | for (int i = 0; i < size; i++) {
1136 | 0 | Object node = list.get(i);
1137 |  |
1138 | 0 | String string = getContentAsStringValue(node);
1139 |  |
1140 | 0 | if (string.length() > 0) {
1141 | 0 | if (USE_STRINGVALUE_SEPARATOR) {
1142 | 0 | if (buffer.length() > 0) {
1143 | 0 | buffer.append(' ');
1144 |  | }
1145 |  | }
1146 |  |
1147 | 0 | buffer.append(string);
1148 |  | }
1149 |  | }
1150 |  |
1151 | 0 | return buffer.toString();
1152 |  | }
1153 |  | }
1154 |  |
1155 | 0 | return "";
1156 |  | }
1157 |  |
1158 |  | /**
1159 |  | * Puts all <code>Text</code> nodes in the full depth of the sub-tree
1160 |  | * underneath this <code>Node</code>, including attribute nodes, into a
1161 |  | * "normal" form where only structure (e.g., elements, comments, processing
1162 |  | * instructions, CDATA sections, and entity references) separates
1163 |  | * <code>Text</code> nodes, i.e., there are neither adjacent
1164 |  | * <code>Text</code> nodes nor empty <code>Text</code> nodes. This can
1165 |  | * be used to ensure that the DOM view of a document is the same as if it
1166 |  | * were saved and re-loaded, and is useful when operations (such as XPointer
1167 |  | * lookups) that depend on a particular document tree structure are to be
1168 |  | * used.In cases where the document contains <code>CDATASections</code>,
1169 |  | * the normalize operation alone may not be sufficient, since XPointers do
1170 |  | * not differentiate between <code>Text</code> nodes and
1171 |  | * <code>CDATASection</code> nodes.
1172 |  | *
1173 |  | * @since DOM Level 2
1174 |  | */
1175 | 42766 | public void normalize() {
1176 | 42766 | List content = contentList();
1177 |  |
1178 | 42766 | Text previousText = null;
1179 |  |
1180 | 42766 | int i = 0;
1181 |  |
1182 | 42766 | while (i < content.size()) {
1183 | 133130 | Node node = (Node) content.get(i);
1184 |  |
1185 | 133130 | if (node instanceof Text) {
1186 | 89266 | Text text = (Text) node;
1187 |  |
1188 | 89266 | if (previousText != null) {
1189 | 12026 | previousText.appendText(text.getText());
1190 |  |
1191 | 12026 | remove(text);
1192 |  | } else {
1193 | 77240 | String value = text.getText();
1194 |  |
1195 |  | // only remove empty Text nodes, not whitespace nodes
1196 |  | // if ( value == null || value.trim().length() <= 0 ) {
1197 | 77240 | if ((value == null) || (value.length() <= 0)) {
1198 | 0 | remove(text);
1199 |  | } else {
1200 | 77240 | previousText = text;
1201 |  |
1202 | 77240 | i++;
1203 |  | }
1204 |  | }
1205 |  | } else {
1206 | 43864 | if (node instanceof Element) {
1207 | 42656 | Element element = (Element) node;
1208 |  |
1209 | 42656 | element.normalize();
1210 |  | }
1211 |  |
1212 | 43864 | previousText = null;
1213 |  |
1214 | 43864 | i++;
1215 |  | }
1216 |  | }
1217 |  | }
1218 |  |
1219 | 0 | public String elementText(String name) {
1220 | 0 | Element element = element(name);
1221 |  |
1222 | 0 | return (element != null) ? element.getText() : null;
1223 |  | }
1224 |  |
1225 | 0 | public String elementText(QName qName) {
1226 | 0 | Element element = element(qName);
1227 |  |
1228 | 0 | return (element != null) ? element.getText() : null;
1229 |  | }
1230 |  |
1231 | 0 | public String elementTextTrim(String name) {
1232 | 0 | Element element = element(name);
1233 |  |
1234 | 0 | return (element != null) ? element.getTextTrim() : null;
1235 |  | }
1236 |  |
1237 | 0 | public String elementTextTrim(QName qName) {
1238 | 0 | Element element = element(qName);
1239 |  |
1240 | 0 | return (element != null) ? element.getTextTrim() : null;
1241 |  | }
1242 |  |
1243 |  | // add to me content from another element
1244 |  | // analagous to the addAll(collection) methods in Java 2 collections
1245 | 134 | public void appendAttributes(Element element) {
1246 | 134 | for (int i = 0, size = element.attributeCount(); i < size; i++) {
1247 | 58 | Attribute attribute = element.attribute(i);
1248 |  |
1249 | 58 | if (attribute.supportsParent()) {
1250 | 58 | addAttribute(attribute.getQName(), attribute.getValue());
1251 |  | } else {
1252 | 0 | add(attribute);
1253 |  | }
1254 |  | }
1255 |  | }
1256 |  |
1257 |  | /**
1258 |  | * <p>
1259 |  | * This returns a deep clone of this element. The new element is detached
1260 |  | * from its parent, and getParent() on the clone will return null.
1261 |  | * </p>
1262 |  | *
1263 |  | * @return the clone of this element
1264 |  | */
1265 |  |
1266 |  | /*
1267 |  | * public Object clone() { Element clone = createElement(getQName());
1268 |  | * clone.appendAttributes(this); clone.appendContent(this); return clone; }
1269 |  | */
1270 | 5 | public Element createCopy() {
1271 | 5 | Element clone = createElement(getQName());
1272 |  |
1273 | 5 | clone.appendAttributes(this);
1274 |  |
1275 | 5 | clone.appendContent(this);
1276 |  |
1277 | 5 | return clone;
1278 |  | }
1279 |  |
1280 | 0 | public Element createCopy(String name) {
1281 | 0 | Element clone = createElement(name);
1282 |  |
1283 | 0 | clone.appendAttributes(this);
1284 |  |
1285 | 0 | clone.appendContent(this);
1286 |  |
1287 | 0 | return clone;
1288 |  | }
1289 |  |
1290 | 0 | public Element createCopy(QName qName) {
1291 | 0 | Element clone = createElement(qName);
1292 |  |
1293 | 0 | clone.appendAttributes(this);
1294 |  |
1295 | 0 | clone.appendContent(this);
1296 |  |
1297 | 0 | return clone;
1298 |  | }
1299 |  |
1300 | 7005 | public QName getQName(String qualifiedName) {
1301 | 7005 | String prefix = "";
1302 |  |
1303 | 7005 | String localName = qualifiedName;
1304 |  |
1305 | 7005 | int index = qualifiedName.indexOf(":");
1306 |  |
1307 | 7005 | if (index > 0) {
1308 | 5004 | prefix = qualifiedName.substring(0, index);
1309 |  |
1310 | 5004 | localName = qualifiedName.substring(index + 1);
1311 |  | }
1312 |  |
1313 | 7005 | Namespace namespace = getNamespaceForPrefix(prefix);
1314 |  |
1315 | 7005 | if (namespace != null) {
1316 | 7005 | return getDocumentFactory().createQName(localName, namespace);
1317 |  | } else {
1318 | 0 | return getDocumentFactory().createQName(localName);
1319 |  | }
1320 |  | }
1321 |  |
1322 | 0 | public Namespace getNamespaceForPrefix(String prefix) {
1323 | 0 | if (prefix == null) {
1324 | 0 | prefix = "";
1325 |  | }
1326 |  |
1327 | 0 | if (prefix.equals(getNamespacePrefix())) {
1328 | 0 | return getNamespace();
1329 | 0 | } else if (prefix.equals("xml")) {
1330 | 0 | return Namespace.XML_NAMESPACE;
1331 |  | } else {
1332 | 0 | List list = contentList();
1333 |  |
1334 | 0 | int size = list.size();
1335 |  |
1336 | 0 | for (int i = 0; i < size; i++) {
1337 | 0 | Object object = list.get(i);
1338 |  |
1339 | 0 | if (object instanceof Namespace) {
1340 | 0 | Namespace namespace = (Namespace) object;
1341 |  |
1342 | 0 | if (prefix.equals(namespace.getPrefix())) {
1343 | 0 | return namespace;
1344 |  | }
1345 |  | }
1346 |  | }
1347 |  | }
1348 |  |
1349 | 0 | Element parent = getParent();
1350 |  |
1351 | 0 | if (parent != null) {
1352 | 0 | Namespace answer = parent.getNamespaceForPrefix(prefix);
1353 |  |
1354 | 0 | if (answer != null) {
1355 | 0 | return answer;
1356 |  | }
1357 |  | }
1358 |  |
1359 | 0 | if ((prefix == null) || (prefix.length() <= 0)) {
1360 | 0 | return Namespace.NO_NAMESPACE;
1361 |  | }
1362 |  |
1363 | 0 | return null;
1364 |  | }
1365 |  |
1366 | 0 | public Namespace getNamespaceForURI(String uri) {
1367 | 0 | if ((uri == null) || (uri.length() <= 0)) {
1368 | 0 | return Namespace.NO_NAMESPACE;
1369 | 0 | } else if (uri.equals(getNamespaceURI())) {
1370 | 0 | return getNamespace();
1371 |  | } else {
1372 | 0 | List list = contentList();
1373 |  |
1374 | 0 | int size = list.size();
1375 |  |
1376 | 0 | for (int i = 0; i < size; i++) {
1377 | 0 | Object object = list.get(i);
1378 |  |
1379 | 0 | if (object instanceof Namespace) {
1380 | 0 | Namespace namespace = (Namespace) object;
1381 |  |
1382 | 0 | if (uri.equals(namespace.getURI())) {
1383 | 0 | return namespace;
1384 |  | }
1385 |  | }
1386 |  | }
1387 |  |
1388 | 0 | return null;
1389 |  | }
1390 |  | }
1391 |  |
1392 | 1 | public List getNamespacesForURI(String uri) {
1393 | 1 | BackedList answer = createResultList();
1394 |  |
1395 |  | // if (getNamespaceURI().equals(uri)) {
1396 |  | //
1397 |  | // answer.addLocal(getNamespace());
1398 |  | //
1399 |  | // }
1400 | 1 | List list = contentList();
1401 |  |
1402 | 1 | int size = list.size();
1403 |  |
1404 | 1 | for (int i = 0; i < size; i++) {
1405 | 4 | Object object = list.get(i);
1406 |  |
1407 | 4 | if ((object instanceof Namespace)
1408 |  | && ((Namespace) object).getURI().equals(uri)) {
1409 | 2 | answer.addLocal(object);
1410 |  | }
1411 |  | }
1412 |  |
1413 | 1 | return answer;
1414 |  | }
1415 |  |
1416 | 0 | public List declaredNamespaces() {
1417 | 0 | BackedList answer = createResultList();
1418 |  |
1419 |  | // if (getNamespaceURI().length() > 0) {
1420 |  | //
1421 |  | // answer.addLocal(getNamespace());
1422 |  | //
1423 |  | // }
1424 |  | //
1425 | 0 | List list = contentList();
1426 |  |
1427 | 0 | int size = list.size();
1428 |  |
1429 | 0 | for (int i = 0; i < size; i++) {
1430 | 0 | Object object = list.get(i);
1431 |  |
1432 | 0 | if (object instanceof Namespace) {
1433 | 0 | answer.addLocal(object);
1434 |  | }
1435 |  | }
1436 |  |
1437 | 0 | return answer;
1438 |  | }
1439 |  |
1440 | 0 | public List additionalNamespaces() {
1441 | 0 | List list = contentList();
1442 |  |
1443 | 0 | int size = list.size();
1444 |  |
1445 | 0 | BackedList answer = createResultList();
1446 |  |
1447 | 0 | for (int i = 0; i < size; i++) {
1448 | 0 | Object object = list.get(i);
1449 |  |
1450 | 0 | if (object instanceof Namespace) {
1451 | 0 | Namespace namespace = (Namespace) object;
1452 |  |
1453 | 0 | if (!namespace.equals(getNamespace())) {
1454 | 0 | answer.addLocal(namespace);
1455 |  | }
1456 |  | }
1457 |  | }
1458 |  |
1459 | 0 | return answer;
1460 |  | }
1461 |  |
1462 | 0 | public List additionalNamespaces(String defaultNamespaceURI) {
1463 | 0 | List list = contentList();
1464 |  |
1465 | 0 | BackedList answer = createResultList();
1466 |  |
1467 | 0 | int size = list.size();
1468 |  |
1469 | 0 | for (int i = 0; i < size; i++) {
1470 | 0 | Object object = list.get(i);
1471 |  |
1472 | 0 | if (object instanceof Namespace) {
1473 | 0 | Namespace namespace = (Namespace) object;
1474 |  |
1475 | 0 | if (!defaultNamespaceURI.equals(namespace.getURI())) {
1476 | 0 | answer.addLocal(namespace);
1477 |  | }
1478 |  | }
1479 |  | }
1480 |  |
1481 | 0 | return answer;
1482 |  | }
1483 |  |
1484 |  | // Implementation helper methods
1485 |  | // -------------------------------------------------------------------------
1486 |  |
1487 |  | /**
1488 |  | * Ensures that the list of attributes has the given size
1489 |  | *
1490 |  | * @param minCapacity
1491 |  | * DOCUMENT ME!
1492 |  | */
1493 | 0 | public void ensureAttributesCapacity(int minCapacity) {
1494 | 0 | if (minCapacity > 1) {
1495 | 0 | List list = attributeList();
1496 |  |
1497 | 0 | if (list instanceof ArrayList) {
1498 | 0 | ArrayList arrayList = (ArrayList) list;
1499 |  |
1500 | 0 | arrayList.ensureCapacity(minCapacity);
1501 |  | }
1502 |  | }
1503 |  | }
1504 |  |
1505 |  | // Implementation methods
1506 |  | // -------------------------------------------------------------------------
1507 | 0 | protected Element createElement(String name) {
1508 | 0 | return getDocumentFactory().createElement(name);
1509 |  | }
1510 |  |
1511 | 4 | protected Element createElement(QName qName) {
1512 | 4 | return getDocumentFactory().createElement(qName);
1513 |  | }
1514 |  |
1515 | 95996 | protected void addNode(Node node) {
1516 | 95996 | if (node.getParent() != null) {
1517 |  | // XXX: could clone here
1518 | 1 | String message = "The Node already has an existing parent of \""
1519 |  | + node.getParent().getQualifiedName() + "\"";
1520 |  |
1521 | 1 | throw new IllegalAddException(this, node, message);
1522 |  | }
1523 |  |
1524 | 95995 | addNewNode(node);
1525 |  | }
1526 |  |
1527 | 8 | protected void addNode(int index, Node node) {
1528 | 8 | if (node.getParent() != null) {
1529 |  | // XXX: could clone here
1530 | 1 | String message = "The Node already has an existing parent of \""
1531 |  | + node.getParent().getQualifiedName() + "\"";
1532 |  |
1533 | 1 | throw new IllegalAddException(this, node, message);
1534 |  | }
1535 |  |
1536 | 7 | addNewNode(index, node);
1537 |  | }
1538 |  |
1539 |  | /**
1540 |  | * Like addNode() but does not require a parent check
1541 |  | *
1542 |  | * @param node
1543 |  | * DOCUMENT ME!
1544 |  | */
1545 | 0 | protected void addNewNode(Node node) {
1546 | 0 | contentList().add(node);
1547 |  |
1548 | 0 | childAdded(node);
1549 |  | }
1550 |  |
1551 | 7 | protected void addNewNode(int index, Node node) {
1552 | 7 | contentList().add(index, node);
1553 |  |
1554 | 7 | childAdded(node);
1555 |  | }
1556 |  |
1557 | 0 | protected boolean removeNode(Node node) {
1558 | 0 | boolean answer = contentList().remove(node);
1559 |  |
1560 | 0 | if (answer) {
1561 | 0 | childRemoved(node);
1562 |  | }
1563 |  |
1564 | 0 | return answer;
1565 |  | }
1566 |  |
1567 |  | /**
1568 |  | * Called when a new child node is added to create any parent relationships
1569 |  | *
1570 |  | * @param node
1571 |  | * DOCUMENT ME!
1572 |  | */
1573 | 234937 | protected void childAdded(Node node) {
1574 | 234937 | if (node != null) {
1575 | 234937 | node.setParent(this);
1576 |  | }
1577 |  | }
1578 |  |
1579 | 13560 | protected void childRemoved(Node node) {
1580 | 13560 | if (node != null) {
1581 | 13560 | node.setParent(null);
1582 |  |
1583 | 13560 | node.setDocument(null);
1584 |  | }
1585 |  | }
1586 |  |
1587 |  | /**
1588 |  | * DOCUMENT ME!
1589 |  | *
1590 |  | * @return the internal List used to store attributes or creates one if one
1591 |  | * is not available
1592 |  | */
1593 |  | protected abstract List attributeList();
1594 |  |
1595 |  | /**
1596 |  | * DOCUMENT ME!
1597 |  | *
1598 |  | * @param attributeCount
1599 |  | * DOCUMENT ME!
1600 |  | *
1601 |  | * @return the internal List used to store attributes or creates one with
1602 |  | * the specified size if one is not available
1603 |  | */
1604 |  | protected abstract List attributeList(int attributeCount);
1605 |  |
1606 | 1 | protected DocumentFactory getDocumentFactory() {
1607 | 1 | QName qName = getQName();
1608 |  |
1609 |  | // QName might be null as we might not have been constructed yet
1610 | 1 | if (qName != null) {
1611 | 0 | DocumentFactory factory = qName.getDocumentFactory();
1612 |  |
1613 | 0 | if (factory != null) {
1614 | 0 | return factory;
1615 |  | }
1616 |  | }
1617 |  |
1618 | 1 | return DOCUMENT_FACTORY;
1619 |  | }
1620 |  |
1621 |  | /**
1622 |  | * A Factory Method pattern which creates a List implementation used to
1623 |  | * store attributes
1624 |  | *
1625 |  | * @return DOCUMENT ME!
1626 |  | */
1627 | 28757 | protected List createAttributeList() {
1628 | 28757 | return createAttributeList(DEFAULT_CONTENT_LIST_SIZE);
1629 |  | }
1630 |  |
1631 |  | /**
1632 |  | * A Factory Method pattern which creates a List implementation used to
1633 |  | * store attributes
1634 |  | *
1635 |  | * @param size
1636 |  | * DOCUMENT ME!
1637 |  | *
1638 |  | * @return DOCUMENT ME!
1639 |  | */
1640 | 30375 | protected List createAttributeList(int size) {
1641 | 30375 | return new ArrayList(size);
1642 |  | }
1643 |  |
1644 | 62118 | protected Iterator createSingleIterator(Object result) {
1645 | 62118 | return new SingleIterator(result);
1646 |  | }
1647 |  | }
1648 |  |
1649 |  | /*
1650 |  | * Redistribution and use of this software and associated documentation
1651 |  | * ("Software"), with or without modification, are permitted provided that the
1652 |  | * following conditions are met:
1653 |  | *
1654 |  | * 1. Redistributions of source code must retain copyright statements and
1655 |  | * notices. Redistributions must also contain a copy of this document.
1656 |  | *
1657 |  | * 2. Redistributions in binary form must reproduce the above copyright notice,
1658 |  | * this list of conditions and the following disclaimer in the documentation
1659 |  | * and/or other materials provided with the distribution.
1660 |  | *
1661 |  | * 3. The name "DOM4J" must not be used to endorse or promote products derived
1662 |  | * from this Software without prior written permission of MetaStuff, Ltd. For
1663 |  | * written permission, please contact dom4j-info@metastuff.com.
1664 |  | *
1665 |  | * 4. Products derived from this Software may not be called "DOM4J" nor may
1666 |  | * "DOM4J" appear in their names without prior written permission of MetaStuff,
1667 |  | * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
1668 |  | *
1669 |  | * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
1670 |  | *
1671 |  | * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
1672 |  | * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1673 |  | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1674 |  | * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
1675 |  | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1676 |  | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1677 |  | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1678 |  | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1679 |  | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1680 |  | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1681 |  | * POSSIBILITY OF SUCH DAMAGE.
1682 |  | *
1683 |  | * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
1684 |  | */