1   
2   
3   
4   
5   
6   
7   
8   package org.dom4j.tree;
9   
10  import java.util.ArrayList;
11  import java.util.Iterator;
12  import java.util.List;
13  
14  import org.dom4j.Attribute;
15  import org.dom4j.Branch;
16  import org.dom4j.Document;
17  import org.dom4j.DocumentFactory;
18  import org.dom4j.Element;
19  import org.dom4j.IllegalAddException;
20  import org.dom4j.Namespace;
21  import org.dom4j.Node;
22  import org.dom4j.ProcessingInstruction;
23  import org.dom4j.QName;
24  
25  /***
26   * <p>
27   * <code>DefaultElement</code> is the default DOM4J default implementation of
28   * an XML element.
29   * </p>
30   * 
31   * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
32   * @version $Revision: 1.59 $
33   */
34  public class DefaultElement extends AbstractElement {
35      /*** The <code>DocumentFactory</code> instance used by default */
36      private static final transient DocumentFactory DOCUMENT_FACTORY = 
37              DocumentFactory.getInstance();
38  
39      /*** The <code>QName</code> for this element */
40      private QName qname;
41  
42      /***
43       * Stores the parent branch of this node which is either a Document if this
44       * element is the root element in a document, or another Element if it is a
45       * child of the root document, or null if it has not been added to a
46       * document yet.
47       */
48      private Branch parentBranch;
49  
50      /***
51       * Stores null for no content, a Node for a single content node or a List
52       * for multiple content nodes. The List will be lazily constructed when
53       * required.
54       */
55      private Object content;
56  
57      /*** Lazily constructes list of attributes */
58      private Object attributes;
59  
60      public DefaultElement(String name) {
61          this.qname = DOCUMENT_FACTORY.createQName(name);
62      }
63  
64      public DefaultElement(QName qname) {
65          this.qname = qname;
66      }
67  
68      public DefaultElement(QName qname, int attributeCount) {
69          this.qname = qname;
70  
71          if (attributeCount > 1) {
72              this.attributes = new ArrayList(attributeCount);
73          }
74      }
75  
76      public DefaultElement(String name, Namespace namespace) {
77          this.qname = DOCUMENT_FACTORY.createQName(name, namespace);
78      }
79  
80      public Element getParent() {
81          Element result = null;
82  
83          if (parentBranch instanceof Element) {
84              result = (Element) parentBranch;
85          }
86  
87          return result;
88      }
89  
90      public void setParent(Element parent) {
91          if (parentBranch instanceof Element || (parent != null)) {
92              parentBranch = parent;
93          }
94      }
95  
96      public Document getDocument() {
97          if (parentBranch instanceof Document) {
98              return (Document) parentBranch;
99          } else if (parentBranch instanceof Element) {
100             Element parent = (Element) parentBranch;
101 
102             return parent.getDocument();
103         }
104 
105         return null;
106     }
107 
108     public void setDocument(Document document) {
109         if (parentBranch instanceof Document || (document != null)) {
110             parentBranch = document;
111         }
112     }
113 
114     public boolean supportsParent() {
115         return true;
116     }
117 
118     public QName getQName() {
119         return qname;
120     }
121 
122     public void setQName(QName name) {
123         this.qname = name;
124     }
125 
126     public String getText() {
127         final Object contentShadow = content;
128 
129         if (contentShadow instanceof List) {
130             return super.getText();
131         } else {
132             if (contentShadow != null) {
133                 return getContentAsText(contentShadow);
134             } else {
135                 return "";
136             }
137         }
138     }
139 
140     public String getStringValue() {
141         final Object contentShadow = content;
142 
143         if (contentShadow instanceof List) {
144             List list = (List) contentShadow;
145 
146             int size = list.size();
147 
148             if (size > 0) {
149                 if (size == 1) {
150                     
151                     return getContentAsStringValue(list.get(0));
152                 } else {
153                     StringBuffer buffer = new StringBuffer();
154 
155                     for (int i = 0; i < size; i++) {
156                         Object node = list.get(i);
157 
158                         String string = getContentAsStringValue(node);
159 
160                         if (string.length() > 0) {
161                             if (USE_STRINGVALUE_SEPARATOR) {
162                                 if (buffer.length() > 0) {
163                                     buffer.append(' ');
164                                 }
165                             }
166 
167                             buffer.append(string);
168                         }
169                     }
170 
171                     return buffer.toString();
172                 }
173             }
174         } else {
175             if (contentShadow != null) {
176                 return getContentAsStringValue(contentShadow);
177             }
178         }
179 
180         return "";
181     }
182 
183     public Object clone() {
184         DefaultElement answer = (DefaultElement) super.clone();
185 
186         if (answer != this) {
187             answer.content = null;
188 
189             answer.attributes = null;
190 
191             answer.appendAttributes(this);
192 
193             answer.appendContent(this);
194         }
195 
196         return answer;
197     }
198 
199     public Namespace getNamespaceForPrefix(String prefix) {
200         if (prefix == null) {
201             prefix = "";
202         }
203 
204         if (prefix.equals(getNamespacePrefix())) {
205             return getNamespace();
206         } else if (prefix.equals("xml")) {
207             return Namespace.XML_NAMESPACE;
208         } else {
209             final Object contentShadow = content;
210 
211             if (contentShadow instanceof List) {
212                 List list = (List) contentShadow;
213 
214                 int size = list.size();
215 
216                 for (int i = 0; i < size; i++) {
217                     Object object = list.get(i);
218 
219                     if (object instanceof Namespace) {
220                         Namespace namespace = (Namespace) object;
221 
222                         if (prefix.equals(namespace.getPrefix())) {
223                             return namespace;
224                         }
225                     }
226                 }
227             } else if (contentShadow instanceof Namespace) {
228                 Namespace namespace = (Namespace) contentShadow;
229 
230                 if (prefix.equals(namespace.getPrefix())) {
231                     return namespace;
232                 }
233             }
234         }
235 
236         Element parent = getParent();
237 
238         if (parent != null) {
239             Namespace answer = parent.getNamespaceForPrefix(prefix);
240 
241             if (answer != null) {
242                 return answer;
243             }
244         }
245 
246         if ((prefix == null) || (prefix.length() <= 0)) {
247             return Namespace.NO_NAMESPACE;
248         }
249 
250         return null;
251     }
252 
253     public Namespace getNamespaceForURI(String uri) {
254         if ((uri == null) || (uri.length() <= 0)) {
255             return Namespace.NO_NAMESPACE;
256         } else if (uri.equals(getNamespaceURI())) {
257             return getNamespace();
258         } else {
259             final Object contentShadow = content;
260 
261             if (contentShadow instanceof List) {
262                 List list = (List) contentShadow;
263 
264                 int size = list.size();
265 
266                 for (int i = 0; i < size; i++) {
267                     Object object = list.get(i);
268 
269                     if (object instanceof Namespace) {
270                         Namespace namespace = (Namespace) object;
271 
272                         if (uri.equals(namespace.getURI())) {
273                             return namespace;
274                         }
275                     }
276                 }
277             } else if (contentShadow instanceof Namespace) {
278                 Namespace namespace = (Namespace) contentShadow;
279 
280                 if (uri.equals(namespace.getURI())) {
281                     return namespace;
282                 }
283             }
284 
285             Element parent = getParent();
286 
287             if (parent != null) {
288                 return parent.getNamespaceForURI(uri);
289             }
290 
291             return null;
292         }
293     }
294 
295     public List declaredNamespaces() {
296         BackedList answer = createResultList();
297 
298         
299         
300         
301         
302         
303         final Object contentShadow = content;
304 
305         if (contentShadow instanceof List) {
306             List list = (List) contentShadow;
307 
308             int size = list.size();
309 
310             for (int i = 0; i < size; i++) {
311                 Object object = list.get(i);
312 
313                 if (object instanceof Namespace) {
314                     answer.addLocal(object);
315                 }
316             }
317         } else {
318             if (contentShadow instanceof Namespace) {
319                 answer.addLocal(contentShadow);
320             }
321         }
322 
323         return answer;
324     }
325 
326     public List additionalNamespaces() {
327         final Object contentShadow = content;
328 
329         if (contentShadow instanceof List) {
330             List list = (List) contentShadow;
331 
332             int size = list.size();
333 
334             BackedList answer = createResultList();
335 
336             for (int i = 0; i < size; i++) {
337                 Object object = list.get(i);
338 
339                 if (object instanceof Namespace) {
340                     Namespace namespace = (Namespace) object;
341 
342                     if (!namespace.equals(getNamespace())) {
343                         answer.addLocal(namespace);
344                     }
345                 }
346             }
347 
348             return answer;
349         } else {
350             if (contentShadow instanceof Namespace) {
351                 Namespace namespace = (Namespace) contentShadow;
352 
353                 if (namespace.equals(getNamespace())) {
354                     return createEmptyList();
355                 }
356 
357                 return createSingleResultList(namespace);
358             } else {
359                 return createEmptyList();
360             }
361         }
362     }
363 
364     public List additionalNamespaces(String defaultNamespaceURI) {
365         final Object contentShadow = content;
366 
367         if (contentShadow instanceof List) {
368             List list = (List) contentShadow;
369 
370             BackedList answer = createResultList();
371 
372             int size = list.size();
373 
374             for (int i = 0; i < size; i++) {
375                 Object object = list.get(i);
376 
377                 if (object instanceof Namespace) {
378                     Namespace namespace = (Namespace) object;
379 
380                     if (!defaultNamespaceURI.equals(namespace.getURI())) {
381                         answer.addLocal(namespace);
382                     }
383                 }
384             }
385 
386             return answer;
387         } else {
388             if (contentShadow instanceof Namespace) {
389                 Namespace namespace = (Namespace) contentShadow;
390 
391                 if (!defaultNamespaceURI.equals(namespace.getURI())) {
392                     return createSingleResultList(namespace);
393                 }
394             }
395         }
396 
397         return createEmptyList();
398     }
399 
400     
401     public List processingInstructions() {
402         final Object contentShadow = content;
403 
404         if (contentShadow instanceof List) {
405             List list = (List) contentShadow;
406 
407             BackedList answer = createResultList();
408 
409             int size = list.size();
410 
411             for (int i = 0; i < size; i++) {
412                 Object object = list.get(i);
413 
414                 if (object instanceof ProcessingInstruction) {
415                     answer.addLocal(object);
416                 }
417             }
418 
419             return answer;
420         } else {
421             if (contentShadow instanceof ProcessingInstruction) {
422                 return createSingleResultList(contentShadow);
423             }
424 
425             return createEmptyList();
426         }
427     }
428 
429     public List processingInstructions(String target) {
430         final Object shadow = content;
431 
432         if (shadow instanceof List) {
433             List list = (List) shadow;
434 
435             BackedList answer = createResultList();
436 
437             int size = list.size();
438 
439             for (int i = 0; i < size; i++) {
440                 Object object = list.get(i);
441 
442                 if (object instanceof ProcessingInstruction) {
443                     ProcessingInstruction pi = (ProcessingInstruction) object;
444 
445                     if (target.equals(pi.getName())) {
446                         answer.addLocal(pi);
447                     }
448                 }
449             }
450 
451             return answer;
452         } else {
453             if (shadow instanceof ProcessingInstruction) {
454                 ProcessingInstruction pi = (ProcessingInstruction) shadow;
455 
456                 if (target.equals(pi.getName())) {
457                     return createSingleResultList(pi);
458                 }
459             }
460 
461             return createEmptyList();
462         }
463     }
464 
465     public ProcessingInstruction processingInstruction(String target) {
466         final Object shadow = content;
467 
468         if (shadow instanceof List) {
469             List list = (List) shadow;
470 
471             int size = list.size();
472 
473             for (int i = 0; i < size; i++) {
474                 Object object = list.get(i);
475 
476                 if (object instanceof ProcessingInstruction) {
477                     ProcessingInstruction pi = (ProcessingInstruction) object;
478 
479                     if (target.equals(pi.getName())) {
480                         return pi;
481                     }
482                 }
483             }
484         } else {
485             if (shadow instanceof ProcessingInstruction) {
486                 ProcessingInstruction pi = (ProcessingInstruction) shadow;
487 
488                 if (target.equals(pi.getName())) {
489                     return pi;
490                 }
491             }
492         }
493 
494         return null;
495     }
496 
497     public boolean removeProcessingInstruction(String target) {
498         final Object shadow = content;
499 
500         if (shadow instanceof List) {
501             List list = (List) shadow;
502 
503             for (Iterator iter = list.iterator(); iter.hasNext();) {
504                 Object object = iter.next();
505 
506                 if (object instanceof ProcessingInstruction) {
507                     ProcessingInstruction pi = (ProcessingInstruction) object;
508 
509                     if (target.equals(pi.getName())) {
510                         iter.remove();
511 
512                         return true;
513                     }
514                 }
515             }
516         } else {
517             if (shadow instanceof ProcessingInstruction) {
518                 ProcessingInstruction pi = (ProcessingInstruction) shadow;
519 
520                 if (target.equals(pi.getName())) {
521                     this.content = null;
522 
523                     return true;
524                 }
525             }
526         }
527 
528         return false;
529     }
530 
531     public Element element(String name) {
532         final Object contentShadow = content;
533 
534         if (contentShadow instanceof List) {
535             List list = (List) contentShadow;
536 
537             int size = list.size();
538 
539             for (int i = 0; i < size; i++) {
540                 Object object = list.get(i);
541 
542                 if (object instanceof Element) {
543                     Element element = (Element) object;
544 
545                     if (name.equals(element.getName())) {
546                         return element;
547                     }
548                 }
549             }
550         } else {
551             if (contentShadow instanceof Element) {
552                 Element element = (Element) contentShadow;
553 
554                 if (name.equals(element.getName())) {
555                     return element;
556                 }
557             }
558         }
559 
560         return null;
561     }
562 
563     public Element element(QName qName) {
564         final Object contentShadow = content;
565 
566         if (contentShadow instanceof List) {
567             List list = (List) contentShadow;
568 
569             int size = list.size();
570 
571             for (int i = 0; i < size; i++) {
572                 Object object = list.get(i);
573 
574                 if (object instanceof Element) {
575                     Element element = (Element) object;
576 
577                     if (qName.equals(element.getQName())) {
578                         return element;
579                     }
580                 }
581             }
582         } else {
583             if (contentShadow instanceof Element) {
584                 Element element = (Element) contentShadow;
585 
586                 if (qName.equals(element.getQName())) {
587                     return element;
588                 }
589             }
590         }
591 
592         return null;
593     }
594 
595     public Element element(String name, Namespace namespace) {
596         return element(getDocumentFactory().createQName(name, namespace));
597     }
598 
599     public void setContent(List content) {
600         contentRemoved();
601 
602         if (content instanceof ContentListFacade) {
603             content = ((ContentListFacade) content).getBackingList();
604         }
605 
606         if (content == null) {
607             this.content = null;
608         } else {
609             int size = content.size();
610 
611             List newContent = createContentList(size);
612 
613             for (int i = 0; i < size; i++) {
614                 Object object = content.get(i);
615 
616                 if (object instanceof Node) {
617                     Node node = (Node) object;
618                     Element parent = node.getParent();
619 
620                     if ((parent != null) && (parent != this)) {
621                         node = (Node) node.clone();
622                     }
623 
624                     newContent.add(node);
625                     childAdded(node);
626                 } else if (object != null) {
627                     String text = object.toString();
628                     Node node = getDocumentFactory().createText(text);
629                     newContent.add(node);
630                     childAdded(node);
631                 }
632             }
633 
634             this.content = newContent;
635         }
636     }
637 
638     public void clearContent() {
639         if (content != null) {
640             contentRemoved();
641 
642             content = null;
643         }
644     }
645 
646     public Node node(int index) {
647         if (index >= 0) {
648             final Object contentShadow = content;
649             Object node;
650 
651             if (contentShadow instanceof List) {
652                 List list = (List) contentShadow;
653 
654                 if (index >= list.size()) {
655                     return null;
656                 }
657 
658                 node = list.get(index);
659             } else {
660                 node = (index == 0) ? contentShadow : null;
661             }
662 
663             if (node != null) {
664                 if (node instanceof Node) {
665                     return (Node) node;
666                 } else {
667                     return new DefaultText(node.toString());
668                 }
669             }
670         }
671 
672         return null;
673     }
674 
675     public int indexOf(Node node) {
676         final Object contentShadow = content;
677 
678         if (contentShadow instanceof List) {
679             List list = (List) contentShadow;
680 
681             return list.indexOf(node);
682         } else {
683             if ((contentShadow != null) && contentShadow.equals(node)) {
684                 return 0;
685             } else {
686                 return -1;
687             }
688         }
689     }
690 
691     public int nodeCount() {
692         final Object contentShadow = content;
693 
694         if (contentShadow instanceof List) {
695             List list = (List) contentShadow;
696 
697             return list.size();
698         } else {
699             return (contentShadow != null) ? 1 : 0;
700         }
701     }
702 
703     public Iterator nodeIterator() {
704         final Object contentShadow = content;
705 
706         if (contentShadow instanceof List) {
707             List list = (List) contentShadow;
708 
709             return list.iterator();
710         } else {
711             if (contentShadow != null) {
712                 return createSingleIterator(contentShadow);
713             } else {
714                 return EMPTY_ITERATOR;
715             }
716         }
717     }
718 
719     public List attributes() {
720         return new ContentListFacade(this, attributeList());
721     }
722 
723     public void setAttributes(List attributes) {
724         if (attributes instanceof ContentListFacade) {
725             attributes = ((ContentListFacade) attributes).getBackingList();
726         }
727 
728         this.attributes = attributes;
729     }
730 
731     public Iterator attributeIterator() {
732         final Object attributesShadow = this.attributes;
733 
734         if (attributesShadow instanceof List) {
735             List list = (List) attributesShadow;
736 
737             return list.iterator();
738         } else if (attributesShadow != null) {
739             return createSingleIterator(attributesShadow);
740         } else {
741             return EMPTY_ITERATOR;
742         }
743     }
744 
745     public Attribute attribute(int index) {
746         final Object attributesShadow = this.attributes;
747 
748         if (attributesShadow instanceof List) {
749             List list = (List) attributesShadow;
750 
751             return (Attribute) list.get(index);
752         } else if ((attributesShadow != null) && (index == 0)) {
753             return (Attribute) attributesShadow;
754         } else {
755             return null;
756         }
757     }
758 
759     public int attributeCount() {
760         final Object attributesShadow = this.attributes;
761 
762         if (attributesShadow instanceof List) {
763             List list = (List) attributesShadow;
764 
765             return list.size();
766         } else {
767             return (attributesShadow != null) ? 1 : 0;
768         }
769     }
770 
771     public Attribute attribute(String name) {
772         final Object attributesShadow = this.attributes;
773 
774         if (attributesShadow instanceof List) {
775             List list = (List) attributesShadow;
776 
777             int size = list.size();
778 
779             for (int i = 0; i < size; i++) {
780                 Attribute attribute = (Attribute) list.get(i);
781 
782                 if (name.equals(attribute.getName())) {
783                     return attribute;
784                 }
785             }
786         } else if (attributesShadow != null) {
787             Attribute attribute = (Attribute) attributesShadow;
788 
789             if (name.equals(attribute.getName())) {
790                 return attribute;
791             }
792         }
793 
794         return null;
795     }
796 
797     public Attribute attribute(QName qName) {
798         final Object attributesShadow = this.attributes;
799 
800         if (attributesShadow instanceof List) {
801             List list = (List) attributesShadow;
802 
803             int size = list.size();
804 
805             for (int i = 0; i < size; i++) {
806                 Attribute attribute = (Attribute) list.get(i);
807 
808                 if (qName.equals(attribute.getQName())) {
809                     return attribute;
810                 }
811             }
812         } else if (attributesShadow != null) {
813             Attribute attribute = (Attribute) attributesShadow;
814 
815             if (qName.equals(attribute.getQName())) {
816                 return attribute;
817             }
818         }
819 
820         return null;
821     }
822 
823     public Attribute attribute(String name, Namespace namespace) {
824         return attribute(getDocumentFactory().createQName(name, namespace));
825     }
826 
827     public void add(Attribute attribute) {
828         if (attribute.getParent() != null) {
829             String message = "The Attribute already has an existing parent \""
830                     + attribute.getParent().getQualifiedName() + "\"";
831 
832             throw new IllegalAddException(this, attribute, message);
833         }
834 
835         if (attribute.getValue() == null) {
836             
837             
838             
839             Attribute oldAttribute = attribute(attribute.getQName());
840 
841             if (oldAttribute != null) {
842                 remove(oldAttribute);
843             }
844         } else {
845             if (attributes == null) {
846                 attributes = attribute;
847             } else {
848                 attributeList().add(attribute);
849             }
850 
851             childAdded(attribute);
852         }
853     }
854 
855     public boolean remove(Attribute attribute) {
856         boolean answer = false;
857         final Object attributesShadow = this.attributes;
858 
859         if (attributesShadow instanceof List) {
860             List list = (List) attributesShadow;
861 
862             answer = list.remove(attribute);
863 
864             if (!answer) {
865                 
866                 Attribute copy = attribute(attribute.getQName());
867 
868                 if (copy != null) {
869                     list.remove(copy);
870 
871                     answer = true;
872                 }
873             }
874         } else if (attributesShadow != null) {
875             if (attribute.equals(attributesShadow)) {
876                 this.attributes = null;
877 
878                 answer = true;
879             } else {
880                 
881                 Attribute other = (Attribute) attributesShadow;
882 
883                 if (attribute.getQName().equals(other.getQName())) {
884                     attributes = null;
885 
886                     answer = true;
887                 }
888             }
889         }
890 
891         if (answer) {
892             childRemoved(attribute);
893         }
894 
895         return answer;
896     }
897 
898     
899     
900     protected void addNewNode(Node node) {
901         final Object contentShadow = content;
902 
903         if (contentShadow == null) {
904             this.content = node;
905         } else {
906             if (contentShadow instanceof List) {
907                 List list = (List) contentShadow;
908 
909                 list.add(node);
910             } else {
911                 List list = createContentList();
912 
913                 list.add(contentShadow);
914 
915                 list.add(node);
916 
917                 this.content = list;
918             }
919         }
920 
921         childAdded(node);
922     }
923 
924     protected boolean removeNode(Node node) {
925         boolean answer = false;
926         final Object contentShadow = content;
927 
928         if (contentShadow != null) {
929             if (contentShadow == node) {
930                 this.content = null;
931 
932                 answer = true;
933             } else if (contentShadow instanceof List) {
934                 List list = (List) contentShadow;
935 
936                 answer = list.remove(node);
937             }
938         }
939 
940         if (answer) {
941             childRemoved(node);
942         }
943 
944         return answer;
945     }
946 
947     protected List contentList() {
948         final Object contentShadow = content;
949 
950         if (contentShadow instanceof List) {
951             return (List) contentShadow;
952         } else {
953             List list = createContentList();
954 
955             if (contentShadow != null) {
956                 list.add(contentShadow);
957             }
958 
959             this.content = list;
960 
961             return list;
962         }
963     }
964 
965     protected List attributeList() {
966         final Object attributesShadow = this.attributes;
967 
968         if (attributesShadow instanceof List) {
969             return (List) attributesShadow;
970         } else if (attributesShadow != null) {
971             List list = createAttributeList();
972 
973             list.add(attributesShadow);
974 
975             this.attributes = list;
976 
977             return list;
978         } else {
979             List list = createAttributeList();
980 
981             this.attributes = list;
982 
983             return list;
984         }
985     }
986 
987     protected List attributeList(int size) {
988         final Object attributesShadow = this.attributes;
989 
990         if (attributesShadow instanceof List) {
991             return (List) attributesShadow;
992         } else if (attributesShadow != null) {
993             List list = createAttributeList(size);
994 
995             list.add(attributesShadow);
996 
997             this.attributes = list;
998 
999             return list;
1000         } else {
1001             List list = createAttributeList(size);
1002 
1003             this.attributes = list;
1004 
1005             return list;
1006         }
1007     }
1008 
1009     protected void setAttributeList(List attributeList) {
1010         this.attributes = attributeList;
1011     }
1012 
1013     protected DocumentFactory getDocumentFactory() {
1014         DocumentFactory factory = qname.getDocumentFactory();
1015 
1016         return (factory != null) ? factory : DOCUMENT_FACTORY;
1017     }
1018 }
1019 
1020 
1021 
1022 
1023 
1024 
1025 
1026 
1027 
1028 
1029 
1030 
1031 
1032 
1033 
1034 
1035 
1036 
1037 
1038 
1039 
1040 
1041 
1042 
1043 
1044 
1045 
1046 
1047 
1048 
1049 
1050 
1051 
1052 
1053 
1054 
1055