KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > xml > dom4j > o3impl > AbstractElement


1 /*
2  * Copyright 2001 (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: AbstractElement.java,v 1.1 2003/11/02 18:10:03 per_nyfelt Exp $
8  */

9
10 package org.ozoneDB.xml.dom4j.o3impl;
11
12 import org.dom4j.*;
13 import org.dom4j.CharacterData;
14 import org.dom4j.io.XMLWriter;
15 import org.xml.sax.Attributes JavaDoc;
16
17 import java.io.IOException JavaDoc;
18 import java.io.StringWriter JavaDoc;
19 import java.io.Writer JavaDoc;
20 import java.util.*;
21
22 /** <p><code>AbstractElement</code> is an abstract base class for
23  * tree implementors to use for implementation inheritence.</p>
24  *
25  * @author <a HREF="mailto:jstrachan@apache.org">James Strachan</a>
26  * @version $Revision: 1.1 $
27  */

28
29 public abstract class AbstractElement
30         extends AbstractBranch
31         implements Element {
32
33     protected static final List EMPTY_LIST = Collections.EMPTY_LIST;
34
35     protected static final Iterator EMPTY_ITERATOR = EMPTY_LIST.iterator();
36
37     protected static final boolean VERBOSE_TOSTRING = false;
38
39     protected static final boolean USE_STRINGVALUE_SEPARATOR = false;
40
41     public AbstractElement() {
42
43     }
44
45     public short getNodeType() {
46
47         return ELEMENT_NODE;
48
49     }
50
51     public boolean isRootElement() {
52
53         Document document = getDocument();
54
55         if (document != null) {
56
57             Element root = document.getRootElement();
58
59             if (root == this) {
60
61                 return true;
62
63             }
64
65         }
66
67         return false;
68
69     }
70
71     public void setName(String JavaDoc name) {
72
73         setQName(getNodeFactory().createQName(name));
74
75     }
76
77     public void setNamespace(Namespace namespace) {
78
79         setQName(getNodeFactory().createQName(getName(), namespace));
80
81     }
82
83     /** Returns the XPath expression to match this Elements name
84      * which is getQualifiedName() if there is a namespace prefix defined or
85      * if no namespace is present then it is getName() or if a namespace is defined
86      * with no prefix then the expression is *[name()='X'] where X = getName().
87      */

88
89     public String JavaDoc getXPathNameStep() {
90
91         String JavaDoc uri = getNamespaceURI();
92
93         if (uri == null || uri.length() == 0) {
94
95             return getName();
96
97         }
98
99         String JavaDoc prefix = getNamespacePrefix();
100
101         if (prefix == null || prefix.length() == 0) {
102
103             return "*[name()='" + getName() + "']";
104
105         }
106
107         return getQualifiedName();
108
109     }
110
111     public String JavaDoc getPath(Element context) {
112
113         Element parent = getParent();
114
115         if (parent == null) {
116
117             return "/" + getXPathNameStep();
118
119         } else if (parent == context) {
120
121             return getXPathNameStep();
122
123         }
124
125         return parent.getPath(context) + "/" + getXPathNameStep();
126
127     }
128
129     public String JavaDoc getUniquePath(Element context) {
130
131         Element parent = getParent();
132
133         if (parent == null) {
134
135             return "/" + getXPathNameStep();
136
137         }
138
139         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
140
141         if (parent != context) {
142
143             buffer.append(parent.getUniquePath(context));
144
145             buffer.append("/");
146
147         }
148
149         buffer.append(getXPathNameStep());
150
151         List mySiblings = parent.elements(getQName());
152
153         if (mySiblings.size() > 1) {
154
155             int idx = mySiblings.indexOf(this);
156
157             if (idx >= 0) {
158
159                 buffer.append("[");
160
161                 buffer.append(Integer.toString(++idx));
162
163                 buffer.append("]");
164
165             }
166
167         }
168
169         return buffer.toString();
170
171     }
172
173     public String JavaDoc asXML() {
174
175         try {
176
177             StringWriter JavaDoc out = new StringWriter JavaDoc();
178
179             XMLWriter writer = new XMLWriter(out, outputFormat);
180
181             writer.write(this);
182
183             return out.toString();
184
185         } catch (IOException JavaDoc e) {
186
187             throw new RuntimeException JavaDoc(
188                     "Wierd IOException while generating textual representation: " + e.getMessage());
189
190         }
191
192     }
193
194     public void write(Writer out) throws IOException JavaDoc {
195
196         XMLWriter writer = new XMLWriter(out, outputFormat);
197
198         writer.write(this);
199
200     }
201
202     /** <p><code>accept</code> method is the <code>Visitor Pattern</code> method.
203      * </p>
204      *
205      * @param visitor <code>Visitor</code> is the visitor.
206      */

207
208     public void accept(Visitor visitor) {
209
210         visitor.visit(this);
211
212         // visit attributes
213

214         for (int i = 0, size = attributeCount(); i < size; i++) {
215
216             Attribute attribute = attribute(i);
217
218             visitor.visit(attribute);
219
220         }
221
222         // visit content
223

224         for (int i = 0, size = nodeCount(); i < size; i++) {
225
226             Node node = node(i);
227
228             node.accept(visitor);
229
230         }
231
232     }
233
234     public String JavaDoc toString() {
235
236         String JavaDoc uri = getNamespaceURI();
237
238         if (uri != null && uri.length() > 0) {
239
240             if (VERBOSE_TOSTRING) {
241
242                 return super.toString()
243                         + " [Element: <"
244                         + getQualifiedName()
245                         + " uri: "
246                         + uri
247                         + " attributes: "
248                         + attributeList()
249                         + " content: "
250                         + contentList()
251                         + " />]";
252
253             } else {
254
255                 return super.toString()
256                         + " [Element: <"
257                         + getQualifiedName()
258                         + " uri: "
259                         + uri
260                         + " attributes: "
261                         + attributeList()
262                         + "/>]";
263
264             }
265
266         } else {
267
268             if (VERBOSE_TOSTRING) {
269
270                 return super.toString()
271                         + " [Element: <"
272                         + getQualifiedName()
273                         + " attributes: "
274                         + attributeList()
275                         + " content: "
276                         + contentList()
277                         + " />]";
278
279             } else {
280
281                 return super.toString()
282                         + " [Element: <"
283                         + getQualifiedName()
284                         + " attributes: "
285                         + attributeList()
286                         + "/>]";
287
288             }
289
290         }
291
292     }
293
294     // QName methods
295

296     //-------------------------------------------------------------------------
297

298     public Namespace getNamespace() {
299         return getQName().getNamespace();
300     }
301
302     public String JavaDoc getName() {
303         return getQName().getName();
304     }
305
306     public String JavaDoc getNamespacePrefix() {
307         return getQName().getNamespacePrefix();
308     }
309
310     public String JavaDoc getNamespaceURI() {
311         return getQName().getNamespaceURI();
312     }
313
314     public String JavaDoc getQualifiedName() {
315         return getQName().getQualifiedName();
316     }
317
318     public Object JavaDoc getData() {
319         return getText();
320     }
321
322     public void setData(Object JavaDoc data) {
323
324         // ignore this method
325

326     }
327
328     // Node methods
329

330     //-------------------------------------------------------------------------
331

332     public Node node(int index) {
333
334         if (index >= 0) {
335
336             List list = contentList();
337
338             if (index >= list.size()) {
339
340                 return null;
341
342             }
343
344             Object JavaDoc node = list.get(index);
345
346             if (node != null) {
347
348                 if (node instanceof Node) {
349
350                     return (Node) node;
351
352                 } else {
353
354                     return getNodeFactory().createText(node.toString());
355
356                 }
357
358             }
359
360         }
361
362         return null;
363
364     }
365
366     public int indexOf(Node node) {
367
368         return contentList().indexOf(node);
369
370     }
371
372     public int nodeCount() {
373
374         return contentList().size();
375
376     }
377
378     public Iterator nodeIterator() {
379
380         return contentList().iterator();
381
382     }
383
384     // Element methods
385

386     //-------------------------------------------------------------------------
387

388     public Element element(String JavaDoc name) {
389
390         List list = contentList();
391
392         int size = list.size();
393
394         for (int i = 0; i < size; i++) {
395
396             Object JavaDoc object = list.get(i);
397
398             if (object instanceof Element) {
399
400                 Element element = (Element) object;
401
402                 if (name.equals(element.getName())) {
403
404                     return element;
405
406                 }
407
408             }
409
410         }
411
412         return null;
413
414     }
415
416     public Element element(QName qName) {
417
418         List list = contentList();
419
420         int size = list.size();
421
422         for (int i = 0; i < size; i++) {
423
424             Object JavaDoc object = list.get(i);
425
426             if (object instanceof Element) {
427
428                 Element element = (Element) object;
429
430                 if (qName.equals(element.getQName())) {
431
432                     return element;
433
434                 }
435
436             }
437
438         }
439
440         return null;
441
442     }
443
444     public Element element(String JavaDoc name, Namespace namespace) {
445
446         return element(getNodeFactory().createQName(name, namespace));
447
448     }
449
450     public List elements() {
451
452         List list = contentList();
453
454         BackedList answer = createResultList();
455
456         int size = list.size();
457
458         for (int i = 0; i < size; i++) {
459
460             Object JavaDoc object = list.get(i);
461
462             if (object instanceof Element) {
463
464                 answer.addLocal(object);
465
466             }
467
468         }
469
470         return answer;
471
472     }
473
474     public List elements(String JavaDoc name) {
475
476         List list = contentList();
477
478         BackedList answer = createResultList();
479
480         int size = list.size();
481
482         for (int i = 0; i < size; i++) {
483
484             Object JavaDoc object = list.get(i);
485
486             if (object instanceof Element) {
487
488                 Element element = (Element) object;
489
490                 if (name.equals(element.getName())) {
491
492                     answer.addLocal(element);
493
494                 }
495
496             }
497
498         }
499
500         return answer;
501
502     }
503
504     public List elements(QName qName) {
505
506         List list = contentList();
507
508         BackedList answer = createResultList();
509
510         int size = list.size();
511
512         for (int i = 0; i < size; i++) {
513
514             Object JavaDoc object = list.get(i);
515
516             if (object instanceof Element) {
517
518                 Element element = (Element) object;
519
520                 if (qName.equals(element.getQName())) {
521
522                     answer.addLocal(element);
523
524                 }
525
526             }
527
528         }
529
530         return answer;
531
532     }
533
534     public List elements(String JavaDoc name, Namespace namespace) {
535
536         return elements(getNodeFactory().createQName(name, namespace));
537
538     }
539
540     public Iterator elementIterator() {
541
542         List list = contentList();
543
544         return new ElementIterator(list.iterator());
545
546     }
547
548     public Iterator elementIterator(String JavaDoc name) {
549
550         List list = contentList();
551
552         return new ElementNameIterator(list.iterator(), name);
553
554     }
555
556     public Iterator elementIterator(QName qName) {
557
558         List list = contentList();
559
560         return new ElementQNameIterator(list.iterator(), qName);
561
562     }
563
564     public Iterator elementIterator(String JavaDoc name, Namespace namespace) {
565
566         return elementIterator(getNodeFactory().createQName(name, namespace));
567
568     }
569
570     // Attribute methods
571

572     //-------------------------------------------------------------------------
573

574     public List attributes() {
575
576         return new ContentListFacade(this, attributeList());
577
578     }
579
580     public Iterator attributeIterator() {
581
582         return attributeList().iterator();
583
584     }
585
586     public Attribute attribute(int index) {
587
588         return (Attribute) attributeList().get(index);
589
590     }
591
592     public int attributeCount() {
593
594         return attributeList().size();
595
596     }
597
598     public Attribute attribute(String JavaDoc name) {
599
600         List list = attributeList();
601
602         int size = list.size();
603
604         for (int i = 0; i < size; i++) {
605
606             Attribute attribute = (Attribute) list.get(i);
607
608             if (name.equals(attribute.getName())) {
609
610                 return attribute;
611
612             }
613
614         }
615
616         return null;
617
618     }
619
620     public Attribute attribute(QName qName) {
621
622         List list = attributeList();
623
624         int size = list.size();
625
626         for (int i = 0; i < size; i++) {
627
628             Attribute attribute = (Attribute) list.get(i);
629
630             if (qName.equals(attribute.getQName())) {
631
632                 return attribute;
633
634             }
635
636         }
637
638         return null;
639
640     }
641
642     public Attribute attribute(String JavaDoc name, Namespace namespace) {
643
644         return attribute(getNodeFactory().createQName(name, namespace));
645
646     }
647
648     /** This method provides a more optimal way of setting all the attributes
649      * on an Element particularly for use in {@link org.dom4j.io.SAXReader}.
650      */

651
652     public void setAttributes(
653             Attributes JavaDoc attributes,
654             NamespaceStack namespaceStack,
655             boolean noNamespaceAttributes) {
656
657         // now lets add all attribute values
658

659         int size = attributes.getLength();
660
661         if (size > 0) {
662
663             NodeFactory factory = getNodeFactory();
664
665             if (size == 1) {
666
667                 // allow lazy construction of the List of Attributes
668

669                 String JavaDoc attributeQualifiedName = attributes.getQName(0);
670
671                 if (noNamespaceAttributes || !attributeQualifiedName.startsWith("xmlns")) {
672
673                     String JavaDoc attributeURI = attributes.getURI(0);
674
675                     String JavaDoc attributeLocalName = attributes.getLocalName(0);
676
677                     String JavaDoc attributeValue = attributes.getValue(0);
678
679                     QName attributeQName =
680                             namespaceStack.getAttributeQName(
681                                     attributeURI,
682                                     attributeLocalName,
683                                     attributeQualifiedName);
684
685                     add(factory.createAttribute(this, attributeQName, attributeValue));
686
687                 }
688
689             } else {
690
691                 List list = attributeList(size);
692
693                 list.clear();
694
695                 for (int i = 0; i < size; i++) {
696
697                     // optimised to avoid the call to attribute(QName) to
698

699                     // lookup an attribute for a given QName
700

701                     String JavaDoc attributeQualifiedName = attributes.getQName(i);
702
703                     if (noNamespaceAttributes || !attributeQualifiedName.startsWith("xmlns")) {
704
705                         String JavaDoc attributeURI = attributes.getURI(i);
706
707                         String JavaDoc attributeLocalName = attributes.getLocalName(i);
708
709                         String JavaDoc attributeValue = attributes.getValue(i);
710
711                         QName attributeQName =
712                                 namespaceStack.getAttributeQName(
713                                         attributeURI,
714                                         attributeLocalName,
715                                         attributeQualifiedName);
716
717                         Attribute attribute =
718                                 factory.createAttribute(this, attributeQName, attributeValue);
719
720                         list.add(attribute);
721
722                         childAdded(attribute);
723
724                     }
725
726                 }
727
728             }
729
730         }
731
732     }
733
734     public String JavaDoc attributeValue(String JavaDoc name) {
735
736         Attribute attrib = attribute(name);
737
738         if (attrib == null) {
739
740             return null;
741
742         } else {
743
744             return attrib.getValue();
745
746         }
747
748     }
749
750     public String JavaDoc attributeValue(QName qName) {
751
752         Attribute attrib = attribute(qName);
753
754         if (attrib == null) {
755
756             return null;
757
758         } else {
759
760             return attrib.getValue();
761
762         }
763
764     }
765
766     public String JavaDoc attributeValue(String JavaDoc name, String JavaDoc defaultValue) {
767
768         String JavaDoc answer = attributeValue(name);
769
770         return (answer != null) ? answer : defaultValue;
771
772     }
773
774     public String JavaDoc attributeValue(QName qName, String JavaDoc defaultValue) {
775
776         String JavaDoc answer = attributeValue(qName);
777
778         return (answer != null) ? answer : defaultValue;
779
780     }
781
782     /**
783      * @deprecated As of version 0.5. Please use
784      * {@link #addAttribute(String,String)} instead.
785      **/

786     public void setAttributeValue(String JavaDoc name, String JavaDoc value) {
787
788         addAttribute(name, value);
789
790     }
791
792     /**
793      * @deprecated As of version 0.5. Please use
794      * {@link #addAttribute(String,String)} instead.
795      **/

796     public void setAttributeValue(QName qName, String JavaDoc value) {
797
798         addAttribute(qName, value);
799
800     }
801
802     public void add(Attribute attribute) {
803
804         if (attribute.getParent() != null) {
805
806             String JavaDoc message =
807                     "The Attribute already has an existing parent \""
808                     + attribute.getParent().getQualifiedName()
809                     + "\"";
810
811             throw new IllegalAddException(this, attribute, message);
812
813         }
814
815         if (attribute.getValue() == null) {
816
817             // try remove a previous attribute with the same
818

819             // name since adding an attribute with a null value
820

821             // is equivalent to removing it.
822

823             Attribute oldAttribute = attribute(attribute.getQName());
824
825             if (oldAttribute != null) {
826
827                 remove(oldAttribute);
828
829             }
830
831         } else {
832
833             attributeList().add(attribute);
834
835             childAdded(attribute);
836
837         }
838
839     }
840
841     public boolean remove(Attribute attribute) {
842
843         List list = attributeList();
844
845         boolean answer = list.remove(attribute);
846
847         if (answer) {
848
849             childRemoved(attribute);
850
851         } else {
852
853             // we may have a copy of the attribute
854

855             Attribute copy = attribute(attribute.getQName());
856
857             if (copy != null) {
858
859                 list.remove(copy);
860
861                 answer = true;
862
863             }
864
865         }
866
867         return answer;
868
869     }
870
871     // Processing instruction API
872

873     //-------------------------------------------------------------------------
874

875     public List processingInstructions() {
876
877         List list = contentList();
878
879         BackedList answer = createResultList();
880
881         int size = list.size();
882
883         for (int i = 0; i < size; i++) {
884
885             Object JavaDoc object = list.get(i);
886
887             if (object instanceof ProcessingInstruction) {
888
889                 answer.addLocal(object);
890
891             }
892
893         }
894
895         return answer;
896
897     }
898
899     public List processingInstructions(String JavaDoc target) {
900
901         List list = contentList();
902
903         BackedList answer = createResultList();
904
905         int size = list.size();
906
907         for (int i = 0; i < size; i++) {
908
909             Object JavaDoc object = list.get(i);
910
911             if (object instanceof ProcessingInstruction) {
912
913                 ProcessingInstruction pi = (ProcessingInstruction) object;
914
915                 if (target.equals(pi.getName())) {
916
917                     answer.addLocal(pi);
918
919                 }
920
921             }
922
923         }
924
925         return answer;
926
927     }
928
929     public ProcessingInstruction processingInstruction(String JavaDoc target) {
930
931         List list = contentList();
932
933         int size = list.size();
934
935         for (int i = 0; i < size; i++) {
936
937             Object JavaDoc object = list.get(i);
938
939             if (object instanceof ProcessingInstruction) {
940
941                 ProcessingInstruction pi = (ProcessingInstruction) object;
942
943                 if (target.equals(pi.getName())) {
944
945                     return pi;
946
947                 }
948
949             }
950
951         }
952
953         return null;
954
955     }
956
957     public boolean removeProcessingInstruction(String JavaDoc target) {
958
959         List list = contentList();
960
961         for (Iterator iter = list.iterator(); iter.hasNext();) {
962
963             Object JavaDoc object = iter.next();
964
965             if (object instanceof ProcessingInstruction) {
966
967                 ProcessingInstruction pi = (ProcessingInstruction) object;
968
969                 if (target.equals(pi.getName())) {
970
971                     iter.remove();
972
973                     return true;
974
975                 }
976
977             }
978
979         }
980
981         return false;
982
983     }
984
985     // Content Model methods
986

987     //-------------------------------------------------------------------------
988

989     public Node getXPathResult(int index) {
990
991         Node answer = node(index);
992
993         if (answer != null && !answer.supportsParent()) {
994
995             return answer.asXPathResult(this);
996
997         }
998
999         return answer;
1000
1001    }
1002
1003    public Element addAttribute(String JavaDoc name, String JavaDoc value) {
1004
1005        // adding a null value is equivalent to removing the attribute
1006

1007        Attribute attribute = attribute(name);
1008
1009        if (value != null) {
1010
1011            if (attribute == null) {
1012
1013                add(getNodeFactory().createAttribute(this, name, value));
1014
1015            } else if (attribute.isReadOnly()) {
1016
1017                remove(attribute);
1018
1019                add(getNodeFactory().createAttribute(this, name, value));
1020
1021            } else {
1022
1023                attribute.setValue(value);
1024
1025            }
1026
1027        } else if (attribute != null) {
1028
1029            remove(attribute);
1030
1031        }
1032
1033        return this;
1034
1035    }
1036
1037    public Element addAttribute(QName qName, String JavaDoc value) {
1038
1039        // adding a null value is equivalent to removing the attribute
1040

1041        Attribute attribute = attribute(qName);
1042
1043        if (value != null) {
1044
1045            if (attribute == null) {
1046
1047                add(getNodeFactory().createAttribute(this, qName, value));
1048
1049            } else if (attribute.isReadOnly()) {
1050
1051                remove(attribute);
1052
1053                add(getNodeFactory().createAttribute(this, qName, value));
1054
1055            } else {
1056
1057                attribute.setValue(value);
1058
1059            }
1060
1061        } else if (attribute != null) {
1062
1063            remove(attribute);
1064
1065        }
1066
1067        return this;
1068
1069    }
1070
1071    public Element addCDATA(String JavaDoc cdata) {
1072
1073        CDATA node = getNodeFactory().createCDATA(cdata);
1074
1075        addNewNode(node);
1076
1077        return this;
1078
1079    }
1080
1081    public Element addComment(String JavaDoc comment) {
1082
1083        Comment node = getNodeFactory().createComment(comment);
1084
1085        addNewNode(node);
1086
1087        return this;
1088
1089    }
1090
1091    public Element addElement(String JavaDoc name) {
1092
1093        NodeFactory factory = getNodeFactory();
1094
1095        int index = name.indexOf(":");
1096
1097        String JavaDoc prefix = "";
1098
1099        String JavaDoc localName = name;
1100
1101        Namespace namespace = null;
1102
1103        if (index > 0) {
1104
1105            prefix = name.substring(0, index);
1106
1107            localName = name.substring(index + 1);
1108
1109            namespace = getNamespaceForPrefix(prefix);
1110
1111            if (namespace == null) {
1112
1113                throw new IllegalAddException(
1114                        "No such namespace prefix: "
1115                        + prefix
1116                        + " is in scope on: "
1117                        + this
1118                        + " so cannot add element: "
1119                        + name);
1120
1121            }
1122
1123        } else {
1124
1125            namespace = getNamespaceForPrefix("");
1126
1127        }
1128
1129        Element node;
1130
1131        if (namespace != null) {
1132
1133            QName qname = factory.createQName(localName, namespace);
1134
1135            node = factory.createElement(qname);
1136
1137        } else {
1138
1139            node = factory.createElement(name);
1140
1141        }
1142
1143        addNewNode(node);
1144
1145        return node;
1146
1147    }
1148
1149    public Element addEntity(String JavaDoc name, String JavaDoc text) {
1150
1151        Entity node = getNodeFactory().createEntity(name, text);
1152
1153        addNewNode(node);
1154
1155        return this;
1156
1157    }
1158
1159    public Element addNamespace(String JavaDoc prefix, String JavaDoc uri) {
1160        Namespace node = getNodeFactory().createNamespace(prefix, uri);
1161        addNewNode(node);
1162        return this;
1163    }
1164
1165    public Element addProcessingInstruction(String JavaDoc target, String JavaDoc data) {
1166        ProcessingInstruction node =
1167                getNodeFactory().createProcessingInstruction(target, data);
1168        addNewNode(node);
1169        return this;
1170    }
1171
1172    public Element addProcessingInstruction(String JavaDoc target, Map data) {
1173        ProcessingInstruction node =
1174                getNodeFactory().createProcessingInstruction(target, data);
1175        addNewNode(node);
1176        return this;
1177    }
1178
1179    public Element addText(String JavaDoc text) {
1180
1181        Text node = getNodeFactory().createText(text);
1182
1183        addNewNode(node);
1184
1185        return this;
1186
1187    }
1188
1189    // polymorphic node methods
1190

1191    public void add(Node node) {
1192
1193        switch (node.getNodeType()) {
1194
1195            case ELEMENT_NODE:
1196
1197                add((Element) node);
1198
1199                break;
1200
1201            case ATTRIBUTE_NODE:
1202
1203                add((Attribute) node);
1204
1205                break;
1206
1207            case TEXT_NODE:
1208
1209                add((Text) node);
1210
1211                break;
1212
1213            case CDATA_SECTION_NODE:
1214
1215                add((CDATA) node);
1216
1217                break;
1218
1219            case ENTITY_REFERENCE_NODE:
1220
1221                add((Entity) node);
1222
1223                break;
1224
1225            case PROCESSING_INSTRUCTION_NODE:
1226
1227                add((ProcessingInstruction) node);
1228
1229                break;
1230
1231            case COMMENT_NODE:
1232
1233                add((Comment) node);
1234
1235                break;
1236
1237                /* XXXX: to do!
1238                            case DOCUMENT_TYPE_NODE:
1239                                add((DocumentType) node);
1240                                break;
1241                */

1242
1243            case NAMESPACE_NODE:
1244
1245                add((Namespace) node);
1246
1247                break;
1248
1249            default :
1250
1251                invalidNodeTypeAddException(node);
1252
1253        }
1254
1255    }
1256
1257    public boolean remove(Node node) {
1258
1259        switch (node.getNodeType()) {
1260
1261            case ELEMENT_NODE:
1262
1263                return remove((Element) node);
1264
1265            case ATTRIBUTE_NODE:
1266
1267                return remove((Attribute) node);
1268
1269            case TEXT_NODE:
1270
1271                return remove((Text) node);
1272
1273            case CDATA_SECTION_NODE:
1274
1275                return remove((CDATA) node);
1276
1277            case ENTITY_REFERENCE_NODE:
1278
1279                return remove((Entity) node);
1280
1281            case PROCESSING_INSTRUCTION_NODE:
1282
1283                return remove((ProcessingInstruction) node);
1284
1285            case COMMENT_NODE:
1286
1287                return remove((Comment) node);
1288
1289                /*
1290                            case DOCUMENT_TYPE_NODE:
1291                                return remove((DocumentType) node);
1292                */

1293
1294            case NAMESPACE_NODE:
1295
1296                return remove((Namespace) node);
1297
1298            default :
1299
1300                return false;
1301
1302        }
1303
1304    }
1305
1306    // typesafe versions using node classes
1307

1308    public void add(CDATA cdata) {
1309
1310        addNode(cdata);
1311
1312    }
1313
1314    public void add(Comment comment) {
1315
1316        addNode(comment);
1317
1318    }
1319
1320    public void add(Element element) {
1321
1322        addNode(element);
1323
1324    }
1325
1326    public void add(Entity entity) {
1327
1328        addNode(entity);
1329
1330    }
1331
1332    public void add(Namespace namespace) {
1333        addNode(namespace);
1334    }
1335
1336    public void add(ProcessingInstruction pi) {
1337        addNode(pi);
1338    }
1339
1340    public void add(Text text) {
1341        addNode(text);
1342    }
1343
1344    public boolean remove(CDATA cdata) {
1345        return removeNode(cdata);
1346    }
1347
1348    public boolean remove(Comment comment) {
1349        return removeNode(comment);
1350    }
1351
1352    public boolean remove(Element element) {
1353        return removeNode(element);
1354    }
1355
1356    public boolean remove(Entity entity) {
1357
1358        return removeNode(entity);
1359
1360    }
1361
1362    public boolean remove(Namespace namespace) {
1363        return removeNode(namespace);
1364    }
1365
1366    public boolean remove(ProcessingInstruction pi) {
1367        return removeNode(pi);
1368    }
1369
1370    public boolean remove(Text text) {
1371        return removeNode(text);
1372    }
1373
1374    // Helper methods
1375

1376    //-------------------------------------------------------------------------
1377

1378    public boolean hasMixedContent() {
1379
1380        List content = contentList();
1381
1382        if (content == null || content.isEmpty() || content.size() < 2) {
1383
1384            return false;
1385
1386        }
1387
1388        Class JavaDoc prevClass = null;
1389
1390        for (Iterator iter = content.iterator(); iter.hasNext();) {
1391
1392            Object JavaDoc object = iter.next();
1393
1394            Class JavaDoc newClass = object.getClass();
1395
1396            if (newClass != prevClass) {
1397
1398                if (prevClass != null) {
1399
1400                    return true;
1401
1402                }
1403
1404                prevClass = newClass;
1405
1406            }
1407
1408        }
1409
1410        return false;
1411
1412    }
1413
1414    public boolean isTextOnly() {
1415
1416        List content = contentList();
1417
1418        if (content == null || content.isEmpty()) {
1419
1420            return true;
1421
1422        }
1423
1424        for (Iterator iter = content.iterator(); iter.hasNext();) {
1425
1426            Object JavaDoc object = iter.next();
1427
1428            if (!(object instanceof CharacterData) && !(object instanceof String JavaDoc)) {
1429
1430                return false;
1431
1432            }
1433
1434        }
1435
1436        return true;
1437
1438    }
1439
1440    public void setText(String JavaDoc text) {
1441
1442        /* remove all text nodes */
1443        List allContent = contentList();
1444        if (allContent != null) {
1445            Iterator it = allContent.iterator();
1446            while (it.hasNext()) {
1447                Node node = (Node) it.next();
1448                switch (node.getNodeType()) {
1449                    case CDATA_SECTION_NODE:
1450                        //case ENTITY_NODE:
1451
case ENTITY_REFERENCE_NODE:
1452                    case TEXT_NODE:
1453                        it.remove();
1454                }
1455            }
1456        }
1457
1458        addText(text);
1459
1460    }
1461
1462    public String JavaDoc getStringValue() {
1463
1464        List list = contentList();
1465
1466        int size = list.size();
1467
1468        if (size > 0) {
1469
1470            if (size == 1) {
1471
1472                // optimised to avoid StringBuffer creation
1473

1474                return getContentAsStringValue(list.get(0));
1475
1476            } else {
1477
1478                StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1479
1480                for (int i = 0; i < size; i++) {
1481
1482                    Object JavaDoc node = list.get(i);
1483
1484                    String JavaDoc string = getContentAsStringValue(node);
1485
1486                    if (string.length() > 0) {
1487
1488                        if (USE_STRINGVALUE_SEPARATOR) {
1489
1490                            if (buffer.length() > 0) {
1491
1492                                buffer.append(' ');
1493
1494                            }
1495
1496                        }
1497
1498                        buffer.append(string);
1499
1500                    }
1501
1502                }
1503
1504                return buffer.toString();
1505
1506            }
1507
1508        }
1509
1510        return "";
1511
1512    }
1513
1514    /**
1515     * Puts all <code>Text</code> nodes in the full depth of the sub-tree
1516     * underneath this <code>Node</code>, including attribute nodes, into a
1517     * "normal" form where only structure (e.g., elements, comments,
1518     * processing instructions, CDATA sections, and entity references)
1519     * separates <code>Text</code> nodes, i.e., there are neither adjacent
1520     * <code>Text</code> nodes nor empty <code>Text</code> nodes. This can
1521     * be used to ensure that the DOM view of a document is the same as if
1522     * it were saved and re-loaded, and is useful when operations (such as
1523     * XPointer lookups) that depend on a particular document tree
1524     * structure are to be used.In cases where the document contains
1525     * <code>CDATASections</code>, the normalize operation alone may not be
1526     * sufficient, since XPointers do not differentiate between
1527     * <code>Text</code> nodes and <code>CDATASection</code> nodes.
1528     * @version DOM Level 2
1529     */

1530
1531    public void normalize() {
1532        List content = contentList();
1533        Text previousText = null;
1534        int i = 0;
1535        while (i < content.size()) {
1536            Node node = (Node) content.get(i);
1537            if (node instanceof Text) {
1538                Text text = (Text) node;
1539                if (previousText != null) {
1540                    previousText.appendText(text.getText());
1541                    remove(text);
1542                } else {
1543                    String JavaDoc value = text.getText();
1544                    // only remove empty Text nodes, not whitespace nodes
1545
//if ( value == null || value.trim().length() <= 0 ) {
1546
if (value == null || value.length() <= 0) {
1547                        remove(text);
1548                    } else {
1549                        previousText = text;
1550                        i++;
1551                    }
1552                }
1553            } else {
1554                if (node instanceof Element) {
1555                    Element element = (Element) node;
1556                    element.normalize();
1557                }
1558                previousText = null;
1559                i++;
1560            }
1561        }
1562    }
1563
1564    public String JavaDoc elementText(String JavaDoc name) {
1565        Element element = element(name);
1566        return (element != null) ? element.getText() : null;
1567    }
1568
1569    public String JavaDoc elementText(QName qName) {
1570        Element element = element(qName);
1571        return (element != null) ? element.getText() : null;
1572    }
1573
1574    public String JavaDoc elementTextTrim(String JavaDoc name) {
1575        Element element = element(name);
1576        return (element != null) ? element.getTextTrim() : null;
1577    }
1578
1579    public String JavaDoc elementTextTrim(QName qName) {
1580        Element element = element(qName);
1581        return (element != null) ? element.getTextTrim() : null;
1582    }
1583
1584    // add to me content from another element
1585
// analagous to the addAll(collection) methods in Java 2 collections
1586
public void appendAttributes(Element element) {
1587        for (int i = 0, size = element.attributeCount(); i < size; i++) {
1588            Attribute attribute = element.attribute(i);
1589            if (attribute.supportsParent()) {
1590                addAttribute(attribute.getQName(), attribute.getValue());
1591            } else {
1592                add(attribute);
1593            }
1594        }
1595    }
1596
1597    /** <p>This returns a deep clone of this element.
1598     * The new element is detached from its parent, and getParent() on the
1599     * clone will return null.</p>
1600     *
1601     * @return the clone of this element
1602     */

1603    /*
1604        public Object clone() {
1605            Element clone = createElement(getQName());
1606            clone.appendAttributes(this);
1607            clone.appendContent(this);
1608            return clone;
1609        }
1610    */

1611
1612    public Element createCopy() {
1613
1614        Element clone = createElement(getQName());
1615
1616        clone.appendAttributes(this);
1617
1618        clone.appendContent(this);
1619
1620        return clone;
1621
1622    }
1623
1624    public Element createCopy(String JavaDoc name) {
1625
1626        Element clone = createElement(name);
1627
1628        clone.appendAttributes(this);
1629
1630        clone.appendContent(this);
1631
1632        return clone;
1633
1634    }
1635
1636    public Element createCopy(QName qName) {
1637
1638        Element clone = createElement(qName);
1639
1640        clone.appendAttributes(this);
1641
1642        clone.appendContent(this);
1643
1644        return clone;
1645
1646    }
1647
1648    public QName getQName(String JavaDoc qualifiedName) {
1649
1650        String JavaDoc prefix = "";
1651
1652        String JavaDoc localName = qualifiedName;
1653
1654        int index = qualifiedName.indexOf(":");
1655
1656        if (index > 0) {
1657
1658            prefix = qualifiedName.substring(0, index);
1659
1660            localName = qualifiedName.substring(index + 1);
1661
1662        }
1663
1664        Namespace namespace = getNamespaceForPrefix(prefix);
1665
1666        if (namespace != null) {
1667
1668            return getNodeFactory().createQName(localName, namespace);
1669
1670        } else {
1671
1672            return getNodeFactory().createQName(localName);
1673
1674        }
1675
1676    }
1677
1678    public Namespace getNamespaceForPrefix(String JavaDoc prefix) {
1679        if (prefix == null) {
1680            prefix = "";
1681        }
1682        if (prefix.equals(getNamespacePrefix())) {
1683            return getNamespace();
1684        } else if (prefix.equals("xml")) {
1685            return getNodeFactory().getXmlNameSpace();
1686            //return AbstractNamespace.XML_NAMESPACE;
1687
} else {
1688            List list = contentList();
1689            int size = list.size();
1690            for (int i = 0; i < size; i++) {
1691                Object JavaDoc object = list.get(i);
1692                if (object instanceof Namespace) {
1693                    Namespace namespace = (Namespace) object;
1694                    if (prefix.equals(namespace.getPrefix())) {
1695                        return namespace;
1696                    }
1697                }
1698            }
1699        }
1700        Element parent = getParent();
1701        if (parent != null) {
1702            Namespace answer = parent.getNamespaceForPrefix(prefix);
1703            if (answer != null) {
1704                return answer;
1705            }
1706        }
1707        if (prefix == null || prefix.length() <= 0) {
1708            return getNodeFactory().getNoNamespace();
1709            //return AbstractNamespace.NO_NAMESPACE;
1710
}
1711        return null;
1712    }
1713
1714    public Namespace getNamespaceForURI(String JavaDoc uri) {
1715        if (uri == null || uri.length() <= 0) {
1716            return getNodeFactory().getNoNamespace();
1717            //return AbstractNamespace.NO_NAMESPACE;
1718
} else if (uri.equals(getNamespaceURI())) {
1719            return getNamespace();
1720        } else {
1721            List list = contentList();
1722            int size = list.size();
1723            for (int i = 0; i < size; i++) {
1724                Object JavaDoc object = list.get(i);
1725                if (object instanceof Namespace) {
1726                    Namespace namespace = (Namespace) object;
1727                    if (uri.equals(namespace.getURI())) {
1728                        return namespace;
1729                    }
1730                }
1731            }
1732            return null;
1733        }
1734    }
1735
1736    public List declaredNamespaces() {
1737        BackedList answer = createResultList();
1738        if (getNamespaceURI().length() > 0) {
1739            answer.addLocal(getNamespace());
1740        }
1741        List list = contentList();
1742        int size = list.size();
1743        for (int i = 0; i < size; i++) {
1744            Object JavaDoc object = list.get(i);
1745            if (object instanceof Namespace) {
1746                answer.addLocal(object);
1747            }
1748        }
1749        return answer;
1750    }
1751
1752    public List additionalNamespaces() {
1753        List list = contentList();
1754        int size = list.size();
1755        BackedList answer = createResultList();
1756        for (int i = 0; i < size; i++) {
1757            Object JavaDoc object = list.get(i);
1758            if (object instanceof Namespace) {
1759                Namespace namespace = (Namespace) object;
1760                answer.addLocal(namespace);
1761            }
1762        }
1763        return answer;
1764    }
1765
1766    public List additionalNamespaces(String JavaDoc defaultNamespaceURI) {
1767        List list = contentList();
1768        BackedList answer = createResultList();
1769        int size = list.size();
1770        for (int i = 0; i < size; i++) {
1771            Object JavaDoc object = list.get(i);
1772            if (object instanceof Namespace) {
1773                Namespace namespace = (Namespace) object;
1774                if (!defaultNamespaceURI.equals(namespace.getURI())) {
1775                    answer.addLocal(namespace);
1776                }
1777            }
1778        }
1779        return answer;
1780    }
1781
1782    // Implementation helper methods
1783
//-------------------------------------------------------------------------
1784
/** Ensures that the list of attributes has the given size */
1785    public void ensureAttributesCapacity(int minCapacity) {
1786        if (minCapacity > 1) {
1787            List list = attributeList();
1788            if (list instanceof ArrayList) {
1789                ArrayList arrayList = (ArrayList) list;
1790                arrayList.ensureCapacity(minCapacity);
1791            }
1792        }
1793    }
1794
1795    // Implementation methods
1796
//-------------------------------------------------------------------------
1797
protected Element createElement(String JavaDoc name) {
1798        return getNodeFactory().createElement(name);
1799    }
1800
1801    protected Element createElement(QName qName) {
1802        return getNodeFactory().createElement(qName);
1803    }
1804
1805    protected void addNode(Node node) {
1806        if (node.getParent() != null) {
1807            // XXX: could clone here
1808
String JavaDoc message =
1809                    "The Node already has an existing parent of \""
1810                    + node.getParent().getQualifiedName()
1811                    + "\"";
1812
1813            throw new IllegalAddException(this, node, message);
1814
1815        }
1816
1817        addNewNode(node);
1818
1819    }
1820
1821    protected void addNode(int index, Node node) {
1822
1823        if (node.getParent() != null) {
1824
1825            // XXX: could clone here
1826

1827            String JavaDoc message =
1828                    "The Node already has an existing parent of \""
1829                    + node.getParent().getQualifiedName()
1830                    + "\"";
1831
1832            throw new IllegalAddException(this, node, message);
1833
1834        }
1835
1836        addNewNode(index, node);
1837
1838    }
1839
1840    /** Like addNode() but does not require a parent check */
1841
1842    protected void addNewNode(Node node) {
1843        contentList().add(node);
1844        childAdded(node);
1845    }
1846
1847    protected void addNewNode(int index, Node node) {
1848        contentList().add(index, node);
1849        childAdded(node);
1850    }
1851
1852    protected boolean removeNode(Node node) {
1853        boolean answer = contentList().remove(node);
1854        if (answer) {
1855            childRemoved(node);
1856        }
1857        return answer;
1858    }
1859
1860    /** Called when a new child node is added to
1861     * create any parent relationships
1862     */

1863
1864    protected void childAdded(Node node) {
1865
1866        if (node != null) {
1867
1868            node.setParent(this);
1869
1870        }
1871
1872    }
1873
1874    protected void childRemoved(Node node) {
1875
1876        if (node != null) {
1877
1878            node.setParent(null);
1879
1880            node.setDocument(null);
1881
1882        }
1883
1884    }
1885
1886    /** @return the internal List used to store attributes or
1887     * creates one if one is not available
1888     */

1889
1890    protected abstract List attributeList();
1891
1892    /** @return the internal List used to store attributes or
1893     * creates one with the specified size if one is not available
1894     */

1895
1896    protected abstract List attributeList(int attributeCount);
1897
1898    protected NodeFactory getNodeFactory() {
1899
1900        QName qName = getQName();
1901
1902        // QName might be null as we might not have been constructed yet
1903

1904        if (qName != null) {
1905
1906            NodeFactory factory = qName.getNodeFactory();
1907
1908            if (factory != null) {
1909
1910                return factory;
1911
1912            }
1913
1914        }
1915
1916        return super.getNodeFactory();
1917
1918    }
1919
1920    /** A Factory Method pattern which creates
1921     * a List implementation used to store attributes
1922     */

1923
1924    protected List createAttributeList() {
1925
1926        return createAttributeList(DEFAULT_CONTENT_LIST_SIZE);
1927
1928    }
1929
1930    /** A Factory Method pattern which creates
1931     * a List implementation used to store attributes
1932     */

1933
1934    protected List createAttributeList(int size) {
1935
1936        return new ArrayList(size);
1937
1938    }
1939
1940    protected Iterator createSingleIterator(Object JavaDoc result) {
1941
1942        return new SingleIterator(result);
1943
1944    }
1945
1946}
1947
1948/*
1949 * Redistribution and use of this software and associated documentation
1950 * ("Software"), with or without modification, are permitted provided
1951 * that the following conditions are met:
1952 *
1953 * 1. Redistributions of source code must retain copyright
1954 * statements and notices. Redistributions must also contain a
1955 * copy of this document.
1956 *
1957 * 2. Redistributions in binary form must reproduce the
1958 * above copyright notice, this list of conditions and the
1959 * following disclaimer in the documentation and/or other
1960 * materials provided with the distribution.
1961 *
1962 * 3. The name "DOM4J" must not be used to endorse or promote
1963 * products derived from this Software without prior written
1964 * permission of MetaStuff, Ltd. For written permission,
1965 * please contact dom4j-info@metastuff.com.
1966 *
1967 * 4. Products derived from this Software may not be called "DOM4J"
1968 * nor may "DOM4J" appear in their names without prior written
1969 * permission of MetaStuff, Ltd. DOM4J is a registered
1970 * trademark of MetaStuff, Ltd.
1971 *
1972 * 5. Due credit should be given to the DOM4J Project
1973 * (http://dom4j.org/).
1974 *
1975 * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
1976 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
1977 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
1978 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
1979 * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
1980 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1981 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1982 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1983 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1984 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1985 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1986 * OF THE POSSIBILITY OF SUCH DAMAGE.
1987 *
1988 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
1989 *
1990 * $Id: AbstractElement.java,v 1.1 2003/11/02 18:10:03 per_nyfelt Exp $
1991 */

1992
Popular Tags