View Javadoc

1   /*
2    * Copyright 2001-2004 (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    * $Id: DefaultElement.java,v 1.56 2004/08/04 18:22:39 maartenc Exp $
8    */
9   
10  package org.dom4j.tree;
11  
12  import java.util.ArrayList;
13  import java.util.Iterator;
14  import java.util.List;
15  
16  import org.dom4j.Attribute;
17  import org.dom4j.Branch;
18  import org.dom4j.Document;
19  import org.dom4j.DocumentFactory;
20  import org.dom4j.Element;
21  import org.dom4j.IllegalAddException;
22  import org.dom4j.Namespace;
23  import org.dom4j.Node;
24  import org.dom4j.ProcessingInstruction;
25  import org.dom4j.QName;
26  
27  /***
28   * <p>
29   * <code>DefaultElement</code> is the default DOM4J default implementation of
30   * an XML element.
31   * </p>
32   * 
33   * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
34   * @version $Revision: 1.56 $
35   */
36  
37  public class DefaultElement extends AbstractElement {
38  
39  	/*** The <code>DocumentFactory</code> instance used by default */
40  
41  	private static transient final DocumentFactory DOCUMENT_FACTORY = DocumentFactory
42  			.getInstance();
43  
44  	/*** The <code>QName</code> for this element */
45  
46  	private QName qname;
47  
48  	/***
49  	 * Stores the parent branch of this node which is either a Document if this
50  	 * element is the root element in a document, or another Element if it is a
51  	 * child of the root document, or null if it has not been added to a
52  	 * document yet.
53  	 */
54  
55  	private Branch parentBranch;
56  
57  	/***
58  	 * Stores null for no content, a Node for a single content node or a List
59  	 * for multiple content nodes. The List will be lazily constructed when
60  	 * required.
61  	 */
62  
63  	private Object content;
64  
65  	/*** Lazily constructes list of attributes */
66  
67  	private Object attributes;
68  
69  	public DefaultElement(String name) {
70  
71  		this.qname = DOCUMENT_FACTORY.createQName(name);
72  
73  	}
74  
75  	public DefaultElement(QName qname) {
76  
77  		this.qname = qname;
78  
79  	}
80  
81  	public DefaultElement(QName qname, int attributeCount) {
82  
83  		this.qname = qname;
84  
85  		if (attributeCount > 1) {
86  
87  			this.attributes = new ArrayList(attributeCount);
88  
89  		}
90  
91  	}
92  
93  	public DefaultElement(String name, Namespace namespace) {
94  
95  		this.qname = DOCUMENT_FACTORY.createQName(name, namespace);
96  
97  	}
98  
99  	public Element getParent() {
100 
101 		return (parentBranch instanceof Element) ? (Element) parentBranch
102 				: null;
103 
104 	}
105 
106 	public void setParent(Element parent) {
107 
108 		if (parentBranch instanceof Element || parent != null) {
109 
110 			parentBranch = parent;
111 
112 		}
113 
114 	}
115 
116 	public Document getDocument() {
117 
118 		if (parentBranch instanceof Document) {
119 
120 			return (Document) parentBranch;
121 
122 		}
123 
124 		else if (parentBranch instanceof Element) {
125 
126 			Element parent = (Element) parentBranch;
127 
128 			return parent.getDocument();
129 
130 		}
131 
132 		return null;
133 
134 	}
135 
136 	public void setDocument(Document document) {
137 
138 		if (parentBranch instanceof Document || document != null) {
139 
140 			parentBranch = document;
141 
142 		}
143 
144 	}
145 
146 	public boolean supportsParent() {
147 
148 		return true;
149 
150 	}
151 
152 	public QName getQName() {
153 
154 		return qname;
155 
156 	}
157 
158 	public void setQName(QName qname) {
159 
160 		this.qname = qname;
161 
162 	}
163 
164 	public String getText() {
165 		final Object contentShadow = content;
166 		if (contentShadow instanceof List) {
167 
168 			return super.getText();
169 
170 		}
171 
172 		else {
173 
174 			if (contentShadow != null) {
175 
176 				return getContentAsText(contentShadow);
177 
178 			}
179 
180 			else {
181 
182 				return "";
183 
184 			}
185 
186 		}
187 
188 	}
189 
190 	public String getStringValue() {
191 		final Object contentShadow = content;
192 
193 		if (contentShadow instanceof List) {
194 
195 			List list = (List) contentShadow;
196 
197 			int size = list.size();
198 
199 			if (size > 0) {
200 
201 				if (size == 1) {
202 
203 					// optimised to avoid StringBuffer creation
204 
205 					return getContentAsStringValue(list.get(0));
206 
207 				}
208 
209 				else {
210 
211 					StringBuffer buffer = new StringBuffer();
212 
213 					for (int i = 0; i < size; i++) {
214 
215 						Object node = list.get(i);
216 
217 						String string = getContentAsStringValue(node);
218 
219 						if (string.length() > 0) {
220 
221 							if (USE_STRINGVALUE_SEPARATOR) {
222 
223 								if (buffer.length() > 0) {
224 
225 									buffer.append(' ');
226 
227 								}
228 
229 							}
230 
231 							buffer.append(string);
232 
233 						}
234 
235 					}
236 
237 					return buffer.toString();
238 
239 				}
240 
241 			}
242 
243 		}
244 
245 		else {
246 
247 			if (contentShadow != null) {
248 
249 				return getContentAsStringValue(contentShadow);
250 
251 			}
252 
253 		}
254 
255 		return "";
256 
257 	}
258 
259 	public Object clone() {
260 
261 		DefaultElement answer = (DefaultElement) super.clone();
262 
263 		if (answer != this) {
264 
265 			answer.content = null;
266 
267 			answer.attributes = null;
268 
269 			answer.appendAttributes(this);
270 
271 			answer.appendContent(this);
272 
273 		}
274 
275 		return answer;
276 
277 	}
278 
279 	public Namespace getNamespaceForPrefix(String prefix) {
280 
281 		if (prefix == null) {
282 
283 			prefix = "";
284 
285 		}
286 
287 		if (prefix.equals(getNamespacePrefix())) {
288 
289 			return getNamespace();
290 
291 		}
292 
293 		else if (prefix.equals("xml")) {
294 
295 			return Namespace.XML_NAMESPACE;
296 
297 		}
298 
299 		else {
300 			final Object contentShadow = content;
301 
302 			if (contentShadow instanceof List) {
303 
304 				List list = (List) contentShadow;
305 
306 				int size = list.size();
307 
308 				for (int i = 0; i < size; i++) {
309 
310 					Object object = list.get(i);
311 
312 					if (object instanceof Namespace) {
313 
314 						Namespace namespace = (Namespace) object;
315 
316 						if (prefix.equals(namespace.getPrefix())) {
317 
318 							return namespace;
319 
320 						}
321 
322 					}
323 
324 				}
325 
326 			}
327 
328 			else if (contentShadow instanceof Namespace) {
329 
330 				Namespace namespace = (Namespace) contentShadow;
331 
332 				if (prefix.equals(namespace.getPrefix())) {
333 
334 					return namespace;
335 
336 				}
337 
338 			}
339 
340 		}
341 
342 		Element parent = getParent();
343 
344 		if (parent != null) {
345 
346 			Namespace answer = parent.getNamespaceForPrefix(prefix);
347 
348 			if (answer != null) {
349 
350 				return answer;
351 
352 			}
353 
354 		}
355 
356 		if (prefix == null || prefix.length() <= 0) {
357 
358 			return Namespace.NO_NAMESPACE;
359 
360 		}
361 
362 		return null;
363 
364 	}
365 
366 	public Namespace getNamespaceForURI(String uri) {
367 
368 		if (uri == null || uri.length() <= 0) {
369 
370 			return Namespace.NO_NAMESPACE;
371 
372 		}
373 
374 		else if (uri.equals(getNamespaceURI())) {
375 
376 			return getNamespace();
377 
378 		}
379 
380 		else {
381 			final Object contentShadow = content;
382 
383 			if (contentShadow instanceof List) {
384 
385 				List list = (List) contentShadow;
386 
387 				int size = list.size();
388 
389 				for (int i = 0; i < size; i++) {
390 
391 					Object object = list.get(i);
392 
393 					if (object instanceof Namespace) {
394 
395 						Namespace namespace = (Namespace) object;
396 
397 						if (uri.equals(namespace.getURI())) {
398 
399 							return namespace;
400 
401 						}
402 
403 					}
404 
405 				}
406 
407 			}
408 
409 			else if (contentShadow instanceof Namespace) {
410 
411 				Namespace namespace = (Namespace) contentShadow;
412 
413 				if (uri.equals(namespace.getURI())) {
414 
415 					return namespace;
416 
417 				}
418 
419 			}
420 
421 			Element parent = getParent();
422 
423 			if (parent != null) {
424 
425 				return parent.getNamespaceForURI(uri);
426 
427 			}
428 
429 			return null;
430 
431 		}
432 
433 	}
434 
435 	public List declaredNamespaces() {
436 
437 		BackedList answer = createResultList();
438 
439 		//        if (getNamespaceURI().length() > 0) {
440 		//
441 		//            answer.addLocal(getNamespace());
442 		//
443 		//        }
444 
445 		final Object contentShadow = content;
446 		if (contentShadow instanceof List) {
447 
448 			List list = (List) contentShadow;
449 
450 			int size = list.size();
451 
452 			for (int i = 0; i < size; i++) {
453 
454 				Object object = list.get(i);
455 
456 				if (object instanceof Namespace) {
457 
458 					answer.addLocal(object);
459 
460 				}
461 
462 			}
463 
464 		}
465 
466 		else {
467 
468 			if (contentShadow instanceof Namespace) {
469 
470 				answer.addLocal(contentShadow);
471 
472 			}
473 
474 		}
475 
476 		return answer;
477 
478 	}
479 
480 	public List additionalNamespaces() {
481 		final Object contentShadow = content;
482 
483 		if (contentShadow instanceof List) {
484 
485 			List list = (List) contentShadow;
486 
487 			int size = list.size();
488 
489 			BackedList answer = createResultList();
490 
491 			for (int i = 0; i < size; i++) {
492 
493 				Object object = list.get(i);
494 
495 				if (object instanceof Namespace) {
496 
497 					Namespace namespace = (Namespace) object;
498 
499 					if (!namespace.equals(getNamespace())) {
500 
501 						answer.addLocal(namespace);
502 					}
503 
504 				}
505 
506 			}
507 
508 			return answer;
509 
510 		}
511 
512 		else {
513 
514 			if (contentShadow instanceof Namespace) {
515 
516 				Namespace namespace = (Namespace) contentShadow;
517 
518 				if (namespace.equals(getNamespace())) {
519 
520 					return createEmptyList();
521 
522 				}
523 
524 				return createSingleResultList(namespace);
525 
526 			}
527 
528 			else {
529 
530 				return createEmptyList();
531 
532 			}
533 
534 		}
535 
536 	}
537 
538 	public List additionalNamespaces(String defaultNamespaceURI) {
539 
540 		final Object contentShadow = content;
541 		if (contentShadow instanceof List) {
542 
543 			List list = (List) contentShadow;
544 
545 			BackedList answer = createResultList();
546 
547 			int size = list.size();
548 
549 			for (int i = 0; i < size; i++) {
550 
551 				Object object = list.get(i);
552 
553 				if (object instanceof Namespace) {
554 
555 					Namespace namespace = (Namespace) object;
556 
557 					if (!defaultNamespaceURI.equals(namespace.getURI())) {
558 
559 						answer.addLocal(namespace);
560 
561 					}
562 
563 				}
564 
565 			}
566 
567 			return answer;
568 
569 		}
570 
571 		else {
572 
573 			if (contentShadow instanceof Namespace) {
574 
575 				Namespace namespace = (Namespace) contentShadow;
576 
577 				if (!defaultNamespaceURI.equals(namespace.getURI())) {
578 
579 					return createSingleResultList(namespace);
580 
581 				}
582 
583 			}
584 
585 		}
586 
587 		return createEmptyList();
588 
589 	}
590 
591 	// Processing instruction API
592 
593 	public List processingInstructions() {
594 
595 		final Object contentShadow = content;
596 		if (contentShadow instanceof List) {
597 
598 			List list = (List) contentShadow;
599 
600 			BackedList answer = createResultList();
601 
602 			int size = list.size();
603 
604 			for (int i = 0; i < size; i++) {
605 
606 				Object object = list.get(i);
607 
608 				if (object instanceof ProcessingInstruction) {
609 
610 					answer.addLocal(object);
611 
612 				}
613 
614 			}
615 
616 			return answer;
617 
618 		}
619 
620 		else {
621 
622 			if (contentShadow instanceof ProcessingInstruction) {
623 
624 				return createSingleResultList(contentShadow);
625 
626 			}
627 
628 			return createEmptyList();
629 
630 		}
631 
632 	}
633 
634 	public List processingInstructions(String target) {
635 
636 		final Object contentShadow = content;
637 		if (contentShadow instanceof List) {
638 
639 			List list = (List) contentShadow;
640 
641 			BackedList answer = createResultList();
642 
643 			int size = list.size();
644 
645 			for (int i = 0; i < size; i++) {
646 
647 				Object object = list.get(i);
648 
649 				if (object instanceof ProcessingInstruction) {
650 
651 					ProcessingInstruction pi = (ProcessingInstruction) object;
652 
653 					if (target.equals(pi.getName())) {
654 
655 						answer.addLocal(pi);
656 
657 					}
658 
659 				}
660 
661 			}
662 
663 			return answer;
664 
665 		}
666 
667 		else {
668 
669 			if (contentShadow instanceof ProcessingInstruction) {
670 
671 				ProcessingInstruction pi = (ProcessingInstruction) contentShadow;
672 
673 				if (target.equals(pi.getName())) {
674 
675 					return createSingleResultList(pi);
676 
677 				}
678 
679 			}
680 
681 			return createEmptyList();
682 
683 		}
684 
685 	}
686 
687 	public ProcessingInstruction processingInstruction(String target) {
688 		final Object contentShadow = content;
689 
690 		if (contentShadow instanceof List) {
691 
692 			List list = (List) contentShadow;
693 
694 			int size = list.size();
695 
696 			for (int i = 0; i < size; i++) {
697 
698 				Object object = list.get(i);
699 
700 				if (object instanceof ProcessingInstruction) {
701 
702 					ProcessingInstruction pi = (ProcessingInstruction) object;
703 
704 					if (target.equals(pi.getName())) {
705 
706 						return pi;
707 
708 					}
709 
710 				}
711 
712 			}
713 
714 		}
715 
716 		else {
717 
718 			if (contentShadow instanceof ProcessingInstruction) {
719 
720 				ProcessingInstruction pi = (ProcessingInstruction) contentShadow;
721 
722 				if (target.equals(pi.getName())) {
723 
724 					return pi;
725 
726 				}
727 
728 			}
729 
730 		}
731 
732 		return null;
733 
734 	}
735 
736 	public boolean removeProcessingInstruction(String target) {
737 		final Object contentShadow = content;
738 
739 		if (contentShadow instanceof List) {
740 
741 			List list = (List) contentShadow;
742 
743 			for (Iterator iter = list.iterator(); iter.hasNext();) {
744 
745 				Object object = iter.next();
746 
747 				if (object instanceof ProcessingInstruction) {
748 
749 					ProcessingInstruction pi = (ProcessingInstruction) object;
750 
751 					if (target.equals(pi.getName())) {
752 
753 						iter.remove();
754 
755 						return true;
756 
757 					}
758 
759 				}
760 
761 			}
762 
763 		}
764 
765 		else {
766 
767 			if (contentShadow instanceof ProcessingInstruction) {
768 
769 				ProcessingInstruction pi = (ProcessingInstruction) contentShadow;
770 
771 				if (target.equals(pi.getName())) {
772 
773 					this.content = null;
774 
775 					return true;
776 
777 				}
778 
779 			}
780 
781 		}
782 
783 		return false;
784 
785 	}
786 
787 	public Element element(String name) {
788 		final Object contentShadow = content;
789 
790 		if (contentShadow instanceof List) {
791 
792 			List list = (List) contentShadow;
793 
794 			int size = list.size();
795 
796 			for (int i = 0; i < size; i++) {
797 
798 				Object object = list.get(i);
799 
800 				if (object instanceof Element) {
801 
802 					Element element = (Element) object;
803 
804 					if (name.equals(element.getName())) {
805 
806 						return element;
807 
808 					}
809 
810 				}
811 
812 			}
813 
814 		}
815 
816 		else {
817 
818 			if (contentShadow instanceof Element) {
819 
820 				Element element = (Element) contentShadow;
821 
822 				if (name.equals(element.getName())) {
823 
824 					return element;
825 
826 				}
827 
828 			}
829 
830 		}
831 
832 		return null;
833 
834 	}
835 
836 	public Element element(QName qName) {
837 		final Object contentShadow = content;
838 
839 		if (contentShadow instanceof List) {
840 
841 			List list = (List) contentShadow;
842 
843 			int size = list.size();
844 
845 			for (int i = 0; i < size; i++) {
846 
847 				Object object = list.get(i);
848 
849 				if (object instanceof Element) {
850 
851 					Element element = (Element) object;
852 
853 					if (qName.equals(element.getQName())) {
854 
855 						return element;
856 
857 					}
858 
859 				}
860 
861 			}
862 
863 		}
864 
865 		else {
866 
867 			if (contentShadow instanceof Element) {
868 
869 				Element element = (Element) contentShadow;
870 
871 				if (qName.equals(element.getQName())) {
872 
873 					return element;
874 
875 				}
876 
877 			}
878 
879 		}
880 
881 		return null;
882 
883 	}
884 
885 	public Element element(String name, Namespace namespace) {
886 
887 		return element(getDocumentFactory().createQName(name, namespace));
888 
889 	}
890 
891 	//    public List elements() {
892 	//        final Object contentShadow = content;
893 	//
894 	//        if (contentShadow instanceof List) {
895 	//
896 	//            List list = (List) contentShadow;
897 	//
898 	//            BackedList answer = createResultList();
899 	//
900 	//            int size = list.size();
901 	//
902 	//            for (int i = 0; i < size; i++) {
903 	//
904 	//                Object object = list.get(i);
905 	//
906 	//                if (object instanceof Element) {
907 	//
908 	//                    answer.addLocal(object);
909 	//
910 	//                }
911 	//
912 	//            }
913 	//
914 	//            return answer;
915 	//
916 	//        }
917 	//
918 	//        else {
919 	//
920 	//            if (contentShadow instanceof Element) {
921 	//
922 	//                Element element = (Element) contentShadow;
923 	//
924 	//                return createSingleResultList(element);
925 	//
926 	//            }
927 	//
928 	//            return createEmptyList();
929 	//
930 	//        }
931 	//
932 	//    }
933 	//
934 	//    public List elements(String name) {
935 	//        final Object contentShadow = content;
936 	//
937 	//        if (contentShadow instanceof List) {
938 	//
939 	//            List list = (List) contentShadow;
940 	//
941 	//            BackedList answer = createResultList();
942 	//
943 	//            int size = list.size();
944 	//
945 	//            for (int i = 0; i < size; i++) {
946 	//
947 	//                Object object = list.get(i);
948 	//
949 	//                if (object instanceof Element) {
950 	//
951 	//                    Element element = (Element) object;
952 	//
953 	//                    if (name.equals(element.getName())) {
954 	//
955 	//                        answer.addLocal(element);
956 	//
957 	//                    }
958 	//
959 	//                }
960 	//
961 	//            }
962 	//
963 	//            return answer;
964 	//
965 	//        }
966 	//
967 	//        else {
968 	//
969 	//            if (contentShadow instanceof Element) {
970 	//
971 	//                Element element = (Element) contentShadow;
972 	//
973 	//                if (name.equals(element.getName())) {
974 	//
975 	//                    return createSingleResultList(element);
976 	//
977 	//                }
978 	//
979 	//            }
980 	//
981 	//            return createEmptyList();
982 	//
983 	//        }
984 	//
985 	//    }
986 	//
987 	//    public List elements(QName qName) {
988 	//        final Object contentShadow = content;
989 	//
990 	//        if (contentShadow instanceof List) {
991 	//
992 	//            List list = (List) contentShadow;
993 	//
994 	//            BackedList answer = createResultList();
995 	//
996 	//            int size = list.size();
997 	//
998 	//            for (int i = 0; i < size; i++) {
999 	//
1000 	//                Object object = list.get(i);
1001 	//
1002 	//                if (object instanceof Element) {
1003 	//
1004 	//                    Element element = (Element) object;
1005 	//
1006 	//                    if (qName.equals(element.getQName())) {
1007 	//
1008 	//                        answer.addLocal(element);
1009 	//
1010 	//                    }
1011 	//
1012 	//                }
1013 	//
1014 	//            }
1015 	//
1016 	//            return answer;
1017 	//
1018 	//        }
1019 	//
1020 	//        else {
1021 	//
1022 	//            if (contentShadow instanceof Element) {
1023 	//
1024 	//                Element element = (Element) contentShadow;
1025 	//
1026 	//                if (qName.equals(element.getQName())) {
1027 	//
1028 	//                    return createSingleResultList(element);
1029 	//
1030 	//                }
1031 	//
1032 	//            }
1033 	//
1034 	//            return createEmptyList();
1035 	//
1036 	//        }
1037 	//
1038 	//    }
1039 	//
1040 	//    public List elements(String name, Namespace namespace) {
1041 	//
1042 	//        return elements(getDocumentFactory().createQName(name, namespace));
1043 	//
1044 	//    }
1045 	//
1046 	//    public Iterator elementIterator() {
1047 	//        final Object contentShadow = content;
1048 	//
1049 	//        if (contentShadow instanceof List) {
1050 	//
1051 	//            List list = (List) contentShadow;
1052 	//
1053 	//            return new ElementIterator(list.iterator());
1054 	//
1055 	//        }
1056 	//
1057 	//        else {
1058 	//
1059 	//            if (contentShadow instanceof Element) {
1060 	//
1061 	//                Element element = (Element) contentShadow;
1062 	//
1063 	//                return createSingleIterator(element);
1064 	//
1065 	//            }
1066 	//
1067 	//            return EMPTY_ITERATOR;
1068 	//
1069 	//        }
1070 	//
1071 	//    }
1072 	//
1073 	//    public Iterator elementIterator(String name) {
1074 	//        final Object contentShadow = content;
1075 	//
1076 	//        if (contentShadow instanceof List) {
1077 	//
1078 	//            List list = (List) contentShadow;
1079 	//
1080 	//            return new ElementNameIterator(list.iterator(), name);
1081 	//
1082 	//        }
1083 	//
1084 	//        else {
1085 	//
1086 	//            if (contentShadow instanceof Element) {
1087 	//
1088 	//                Element element = (Element) contentShadow;
1089 	//
1090 	//                if (name.equals(element.getName())) {
1091 	//
1092 	//                    return createSingleIterator(element);
1093 	//
1094 	//                }
1095 	//
1096 	//            }
1097 	//
1098 	//            return EMPTY_ITERATOR;
1099 	//
1100 	//        }
1101 	//
1102 	//    }
1103 	//
1104 	//    public Iterator elementIterator(QName qName) {
1105 	//        final Object contentShadow = content;
1106 	//
1107 	//        if (contentShadow instanceof List) {
1108 	//
1109 	//            List list = (List) contentShadow;
1110 	//
1111 	//            return new ElementQNameIterator(list.iterator(), qName);
1112 	//
1113 	//        }
1114 	//
1115 	//        else {
1116 	//
1117 	//            if (contentShadow instanceof Element) {
1118 	//
1119 	//                Element element = (Element) contentShadow;
1120 	//
1121 	//                if (qName.equals(element.getQName())) {
1122 	//
1123 	//                    return createSingleIterator(element);
1124 	//
1125 	//                }
1126 	//
1127 	//            }
1128 	//
1129 	//            return EMPTY_ITERATOR;
1130 	//
1131 	//        }
1132 	//
1133 	//    }
1134 	//
1135 	//    public Iterator elementIterator(String name, Namespace namespace) {
1136 	//
1137 	//        return elementIterator(getDocumentFactory().createQName(name,
1138 	// namespace));
1139 	//
1140 	//    }
1141 	//
1142 	public void setContent(List content) {
1143 
1144 		if (content instanceof ContentListFacade) {
1145 
1146 			content = ((ContentListFacade) content).getBackingList();
1147 
1148 		}
1149 
1150 		if (content == null) {
1151 
1152 			this.content = null;
1153 
1154 		}
1155 
1156 		else {
1157 
1158 			int size = content.size();
1159 
1160 			List newContent = createContentList(size);
1161 
1162 			for (int i = 0; i < size; i++) {
1163 
1164 				Object object = content.get(i);
1165 
1166 				if (object instanceof Node) {
1167 
1168 					Node node = (Node) object;
1169 
1170 					Element parent = node.getParent();
1171 
1172 					if (parent != null && parent != this) {
1173 
1174 						node = (Node) node.clone();
1175 
1176 					}
1177 
1178 					newContent.add(node);
1179 
1180 					childAdded(node);
1181 
1182 				}
1183 
1184 				else if (object != null) {
1185 
1186 					String text = object.toString();
1187 
1188 					Node node = getDocumentFactory().createText(text);
1189 
1190 					newContent.add(node);
1191 
1192 					childAdded(node);
1193 
1194 				}
1195 
1196 			}
1197 
1198 			contentRemoved();
1199 
1200 			this.content = newContent;
1201 
1202 		}
1203 
1204 	}
1205 
1206 	public void clearContent() {
1207 
1208 		if (content != null) {
1209 
1210 			contentRemoved();
1211 
1212 			content = null;
1213 
1214 		}
1215 
1216 	}
1217 
1218 	public Node node(int index) {
1219 
1220 		if (index >= 0) {
1221 
1222 			final Object contentShadow = content;
1223 			Object node;
1224 
1225 			if (contentShadow instanceof List) {
1226 
1227 				List list = (List) contentShadow;
1228 
1229 				if (index >= list.size()) {
1230 
1231 					return null;
1232 
1233 				}
1234 
1235 				node = list.get(index);
1236 
1237 			} else {
1238 				node = (index == 0) ? contentShadow : null;
1239 			}
1240 
1241 			if (node != null) {
1242 
1243 				if (node instanceof Node) {
1244 
1245 					return (Node) node;
1246 
1247 				}
1248 
1249 				else {
1250 
1251 					return new DefaultText(node.toString());
1252 
1253 				}
1254 
1255 			}
1256 
1257 		}
1258 
1259 		return null;
1260 
1261 	}
1262 
1263 	public int indexOf(Node node) {
1264 		final Object contentShadow = content;
1265 
1266 		if (contentShadow instanceof List) {
1267 
1268 			List list = (List) contentShadow;
1269 
1270 			return list.indexOf(node);
1271 
1272 		}
1273 
1274 		else {
1275 
1276 			return (contentShadow != null && contentShadow.equals(node)) ? 0
1277 					: -1;
1278 
1279 		}
1280 
1281 	}
1282 
1283 	public int nodeCount() {
1284 		final Object contentShadow = content;
1285 
1286 		if (contentShadow instanceof List) {
1287 
1288 			List list = (List) contentShadow;
1289 
1290 			return list.size();
1291 
1292 		}
1293 
1294 		else {
1295 
1296 			return (contentShadow != null) ? 1 : 0;
1297 
1298 		}
1299 
1300 	}
1301 
1302 	public Iterator nodeIterator() {
1303 		final Object contentShadow = content;
1304 
1305 		if (contentShadow instanceof List) {
1306 
1307 			List list = (List) contentShadow;
1308 
1309 			return list.iterator();
1310 
1311 		}
1312 
1313 		else {
1314 
1315 			if (contentShadow != null) {
1316 
1317 				return createSingleIterator(contentShadow);
1318 
1319 			}
1320 
1321 			else {
1322 
1323 				return EMPTY_ITERATOR;
1324 
1325 			}
1326 
1327 		}
1328 
1329 	}
1330 
1331 	public List attributes() {
1332 
1333 		return new ContentListFacade(this, attributeList());
1334 
1335 	}
1336 
1337 	public void setAttributes(List attributes) {
1338 
1339 		if (attributes instanceof ContentListFacade) {
1340 
1341 			attributes = ((ContentListFacade) attributes).getBackingList();
1342 
1343 		}
1344 		this.attributes = attributes;
1345 
1346 	}
1347 
1348 	public Iterator attributeIterator() {
1349 		final Object attributesShadow = this.attributes;
1350 		if (attributesShadow instanceof List) {
1351 
1352 			List list = (List) attributesShadow;
1353 
1354 			return list.iterator();
1355 
1356 		}
1357 
1358 		else if (attributesShadow != null) {
1359 
1360 			return createSingleIterator(attributesShadow);
1361 
1362 		}
1363 
1364 		else {
1365 
1366 			return EMPTY_ITERATOR;
1367 
1368 		}
1369 
1370 	}
1371 
1372 	public Attribute attribute(int index) {
1373 		final Object attributesShadow = this.attributes;
1374 		if (attributesShadow instanceof List) {
1375 
1376 			List list = (List) attributesShadow;
1377 
1378 			return (Attribute) list.get(index);
1379 
1380 		}
1381 
1382 		else if (attributesShadow != null && index == 0) {
1383 
1384 			return (Attribute) attributesShadow;
1385 
1386 		}
1387 
1388 		else {
1389 
1390 			return null;
1391 
1392 		}
1393 
1394 	}
1395 
1396 	public int attributeCount() {
1397 		final Object attributesShadow = this.attributes;
1398 
1399 		if (attributesShadow instanceof List) {
1400 
1401 			List list = (List) attributesShadow;
1402 
1403 			return list.size();
1404 
1405 		}
1406 
1407 		else {
1408 
1409 			return (attributesShadow != null) ? 1 : 0;
1410 
1411 		}
1412 
1413 	}
1414 
1415 	public Attribute attribute(String name) {
1416 		final Object attributesShadow = this.attributes;
1417 
1418 		if (attributesShadow instanceof List) {
1419 
1420 			List list = (List) attributesShadow;
1421 
1422 			int size = list.size();
1423 
1424 			for (int i = 0; i < size; i++) {
1425 
1426 				Attribute attribute = (Attribute) list.get(i);
1427 
1428 				if (name.equals(attribute.getName())) {
1429 
1430 					return attribute;
1431 
1432 				}
1433 
1434 			}
1435 
1436 		}
1437 
1438 		else if (attributesShadow != null) {
1439 
1440 			Attribute attribute = (Attribute) attributesShadow;
1441 
1442 			if (name.equals(attribute.getName())) {
1443 
1444 				return attribute;
1445 
1446 			}
1447 
1448 		}
1449 
1450 		return null;
1451 
1452 	}
1453 
1454 	public Attribute attribute(QName qName) {
1455 		final Object attributesShadow = this.attributes;
1456 
1457 		if (attributesShadow instanceof List) {
1458 
1459 			List list = (List) attributesShadow;
1460 
1461 			int size = list.size();
1462 
1463 			for (int i = 0; i < size; i++) {
1464 
1465 				Attribute attribute = (Attribute) list.get(i);
1466 
1467 				if (qName.equals(attribute.getQName())) {
1468 
1469 					return attribute;
1470 
1471 				}
1472 
1473 			}
1474 
1475 		}
1476 
1477 		else if (attributesShadow != null) {
1478 
1479 			Attribute attribute = (Attribute) attributesShadow;
1480 
1481 			if (qName.equals(attribute.getQName())) {
1482 
1483 				return attribute;
1484 
1485 			}
1486 
1487 		}
1488 
1489 		return null;
1490 
1491 	}
1492 
1493 	public Attribute attribute(String name, Namespace namespace) {
1494 
1495 		return attribute(getDocumentFactory().createQName(name, namespace));
1496 
1497 	}
1498 
1499 	public void add(Attribute attribute) {
1500 
1501 		if (attribute.getParent() != null) {
1502 
1503 			String message = "The Attribute already has an existing parent \""
1504 					+ attribute.getParent().getQualifiedName() + "\"";
1505 
1506 			throw new IllegalAddException(this, attribute, message);
1507 
1508 		}
1509 
1510 		if (attribute.getValue() == null) {
1511 
1512 			// try remove a previous attribute with the same
1513 
1514 			// name since adding an attribute with a null value
1515 
1516 			// is equivalent to removing it.
1517 
1518 			Attribute oldAttribute = attribute(attribute.getQName());
1519 
1520 			if (oldAttribute != null) {
1521 
1522 				remove(oldAttribute);
1523 
1524 			}
1525 
1526 		}
1527 
1528 		else {
1529 
1530 			if (attributes == null) {
1531 
1532 				attributes = attribute;
1533 
1534 			}
1535 
1536 			else {
1537 
1538 				attributeList().add(attribute);
1539 
1540 			}
1541 
1542 			childAdded(attribute);
1543 
1544 		}
1545 
1546 	}
1547 
1548 	public boolean remove(Attribute attribute) {
1549 
1550 		boolean answer = false;
1551 		final Object attributesShadow = this.attributes;
1552 
1553 		if (attributesShadow instanceof List) {
1554 
1555 			List list = (List) attributesShadow;
1556 
1557 			answer = list.remove(attribute);
1558 
1559 			if (!answer) {
1560 
1561 				// we may have a copy of the attribute
1562 
1563 				Attribute copy = attribute(attribute.getQName());
1564 
1565 				if (copy != null) {
1566 
1567 					list.remove(copy);
1568 
1569 					answer = true;
1570 
1571 				}
1572 
1573 			}
1574 
1575 		}
1576 
1577 		else if (attributesShadow != null) {
1578 
1579 			if (attribute.equals(attributesShadow)) {
1580 
1581 				this.attributes = null;
1582 
1583 				answer = true;
1584 
1585 			}
1586 
1587 			else {
1588 
1589 				// we may have a copy of the attribute
1590 
1591 				Attribute other = (Attribute) attributesShadow;
1592 
1593 				if (attribute.getQName().equals(other.getQName())) {
1594 
1595 					attributes = null;
1596 
1597 					answer = true;
1598 
1599 				}
1600 
1601 			}
1602 
1603 		}
1604 
1605 		if (answer) {
1606 
1607 			childRemoved(attribute);
1608 
1609 		}
1610 
1611 		return answer;
1612 
1613 	}
1614 
1615 	// Implementation methods
1616 
1617 	//-------------------------------------------------------------------------
1618 
1619 	protected void addNewNode(Node node) {
1620 		final Object contentShadow = content;
1621 
1622 		if (contentShadow == null) {
1623 
1624 			this.content = node;
1625 
1626 		}
1627 
1628 		else {
1629 
1630 			if (contentShadow instanceof List) {
1631 
1632 				List list = (List) contentShadow;
1633 
1634 				list.add(node);
1635 
1636 			}
1637 
1638 			else {
1639 
1640 				List list = createContentList();
1641 
1642 				list.add(contentShadow);
1643 
1644 				list.add(node);
1645 
1646 				this.content = list;
1647 
1648 			}
1649 
1650 		}
1651 
1652 		childAdded(node);
1653 
1654 	}
1655 
1656 	protected boolean removeNode(Node node) {
1657 
1658 		boolean answer = false;
1659 		final Object contentShadow = content;
1660 
1661 		if (contentShadow != null) {
1662 
1663 			if (contentShadow == node) {
1664 
1665 				this.content = null;
1666 
1667 				answer = true;
1668 
1669 			}
1670 
1671 			else if (contentShadow instanceof List) {
1672 
1673 				List list = (List) contentShadow;
1674 
1675 				answer = list.remove(node);
1676 
1677 			}
1678 
1679 		}
1680 
1681 		if (answer) {
1682 
1683 			childRemoved(node);
1684 
1685 		}
1686 
1687 		return answer;
1688 
1689 	}
1690 
1691 	protected List contentList() {
1692 		final Object contentShadow = content;
1693 
1694 		if (contentShadow instanceof List) {
1695 
1696 			return (List) contentShadow;
1697 
1698 		}
1699 
1700 		else {
1701 
1702 			List list = createContentList();
1703 
1704 			if (contentShadow != null) {
1705 
1706 				list.add(contentShadow);
1707 
1708 			}
1709 
1710 			this.content = list;
1711 
1712 			return list;
1713 
1714 		}
1715 
1716 	}
1717 
1718 	protected List attributeList() {
1719 		final Object attributesShadow = this.attributes;
1720 
1721 		if (attributesShadow instanceof List) {
1722 
1723 			return (List) attributesShadow;
1724 
1725 		}
1726 
1727 		else if (attributesShadow != null) {
1728 
1729 			List list = createAttributeList();
1730 
1731 			list.add(attributesShadow);
1732 
1733 			this.attributes = list;
1734 
1735 			return list;
1736 
1737 		}
1738 
1739 		else {
1740 
1741 			List list = createAttributeList();
1742 
1743 			this.attributes = list;
1744 
1745 			return list;
1746 
1747 		}
1748 
1749 	}
1750 
1751 	protected List attributeList(int size) {
1752 		final Object attributesShadow = this.attributes;
1753 		if (attributesShadow instanceof List) {
1754 
1755 			return (List) attributesShadow;
1756 
1757 		}
1758 
1759 		else if (attributesShadow != null) {
1760 
1761 			List list = createAttributeList(size);
1762 
1763 			list.add(attributesShadow);
1764 
1765 			this.attributes = list;
1766 
1767 			return list;
1768 
1769 		}
1770 
1771 		else {
1772 
1773 			List list = createAttributeList(size);
1774 
1775 			this.attributes = list;
1776 
1777 			return list;
1778 
1779 		}
1780 
1781 	}
1782 
1783 	protected void setAttributeList(List attributes) {
1784 
1785 		this.attributes = attributes;
1786 
1787 	}
1788 
1789 	protected DocumentFactory getDocumentFactory() {
1790 
1791 		DocumentFactory factory = qname.getDocumentFactory();
1792 
1793 		return (factory != null) ? factory : DOCUMENT_FACTORY;
1794 
1795 	}
1796 
1797 }
1798 
1799 /*
1800  * Redistribution and use of this software and associated documentation
1801  * ("Software"), with or without modification, are permitted provided that the
1802  * following conditions are met:
1803  * 
1804  * 1. Redistributions of source code must retain copyright statements and
1805  * notices. Redistributions must also contain a copy of this document.
1806  * 
1807  * 2. Redistributions in binary form must reproduce the above copyright notice,
1808  * this list of conditions and the following disclaimer in the documentation
1809  * and/or other materials provided with the distribution.
1810  * 
1811  * 3. The name "DOM4J" must not be used to endorse or promote products derived
1812  * from this Software without prior written permission of MetaStuff, Ltd. For
1813  * written permission, please contact dom4j-info@metastuff.com.
1814  * 
1815  * 4. Products derived from this Software may not be called "DOM4J" nor may
1816  * "DOM4J" appear in their names without prior written permission of MetaStuff,
1817  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
1818  * 
1819  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
1820  * 
1821  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
1822  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1823  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1824  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
1825  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1826  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1827  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1828  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1829  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1830  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1831  * POSSIBILITY OF SUCH DAMAGE.
1832  * 
1833  * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
1834  * 
1835  * $Id: DefaultElement.java,v 1.56 2004/08/04 18:22:39 maartenc Exp $
1836  */