View Javadoc

1   /*
2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3    *
4    * This software is open source.
5    * See the bottom of this file for the licence.
6    */
7   
8   package org.dom4j.tree;
9   
10  import java.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                     // optimised to avoid StringBuffer creation
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         // if (getNamespaceURI().length() > 0) {
299         //
300         // answer.addLocal(getNamespace());
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     // Processing instruction API
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             // try remove a previous attribute with the same
837             // name since adding an attribute with a null value
838             // is equivalent to removing it.
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                 // we may have a copy of the attribute
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                 // we may have a copy of the attribute
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     // Implementation methods
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  * Redistribution and use of this software and associated documentation
1022  * ("Software"), with or without modification, are permitted provided that the
1023  * following conditions are met:
1024  * 
1025  * 1. Redistributions of source code must retain copyright statements and
1026  * notices. Redistributions must also contain a copy of this document.
1027  * 
1028  * 2. Redistributions in binary form must reproduce the above copyright notice,
1029  * this list of conditions and the following disclaimer in the documentation
1030  * and/or other materials provided with the distribution.
1031  * 
1032  * 3. The name "DOM4J" must not be used to endorse or promote products derived
1033  * from this Software without prior written permission of MetaStuff, Ltd. For
1034  * written permission, please contact dom4j-info@metastuff.com.
1035  * 
1036  * 4. Products derived from this Software may not be called "DOM4J" nor may
1037  * "DOM4J" appear in their names without prior written permission of MetaStuff,
1038  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
1039  * 
1040  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
1041  * 
1042  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
1043  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1044  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1045  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
1046  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1047  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1048  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1049  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1050  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1051  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1052  * POSSIBILITY OF SUCH DAMAGE.
1053  * 
1054  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
1055  */