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.Collections;
11  import java.util.Iterator;
12  import java.util.List;
13  
14  import org.dom4j.Document;
15  import org.dom4j.DocumentFactory;
16  import org.dom4j.DocumentType;
17  import org.dom4j.Element;
18  import org.dom4j.IllegalAddException;
19  import org.dom4j.Node;
20  import org.dom4j.ProcessingInstruction;
21  
22  import org.xml.sax.EntityResolver;
23  
24  /***
25   * <p>
26   * <code>DefaultDocument</code> is the default DOM4J default implementation of
27   * an XML document.
28   * </p>
29   * 
30   * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
31   * @version $Revision: 1.34 $
32   */
33  public class DefaultDocument extends AbstractDocument {
34      protected static final List EMPTY_LIST = Collections.EMPTY_LIST;
35  
36      protected static final Iterator EMPTY_ITERATOR = EMPTY_LIST.iterator();
37  
38      /*** The name of the document */
39      private String name;
40  
41      /*** The root element of this document */
42      private Element rootElement;
43  
44      /***
45       * Store the contents of the document as a lazily created <code>List</code>
46       */
47      private List content;
48  
49      /*** The document type for this document */
50      private DocumentType docType;
51  
52      /*** The document factory used by default */
53      private DocumentFactory documentFactory = DocumentFactory.getInstance();
54  
55      /*** The resolver of URIs */
56      private transient EntityResolver entityResolver;
57  
58      public DefaultDocument() {
59      }
60  
61      public DefaultDocument(String name) {
62          this.name = name;
63      }
64  
65      public DefaultDocument(Element rootElement) {
66          this.rootElement = rootElement;
67      }
68  
69      public DefaultDocument(DocumentType docType) {
70          this.docType = docType;
71      }
72  
73      public DefaultDocument(Element rootElement, DocumentType docType) {
74          this.rootElement = rootElement;
75          this.docType = docType;
76      }
77  
78      public DefaultDocument(String name, Element rootElement,
79              DocumentType docType) {
80          this.name = name;
81          this.rootElement = rootElement;
82          this.docType = docType;
83      }
84  
85      public String getName() {
86          return name;
87      }
88  
89      public void setName(String name) {
90          this.name = name;
91      }
92  
93      public Element getRootElement() {
94          return rootElement;
95      }
96  
97      public DocumentType getDocType() {
98          return docType;
99      }
100 
101     public void setDocType(DocumentType docType) {
102         this.docType = docType;
103     }
104 
105     public Document addDocType(String docTypeName, String publicId,
106             String systemId) {
107         setDocType(getDocumentFactory().createDocType(docTypeName, publicId,
108                 systemId));
109 
110         return this;
111     }
112 
113     public String getXMLEncoding() {
114         return encoding;
115     }
116 
117     public EntityResolver getEntityResolver() {
118         return entityResolver;
119     }
120 
121     public void setEntityResolver(EntityResolver entityResolver) {
122         this.entityResolver = entityResolver;
123     }
124 
125     public Object clone() {
126         DefaultDocument document = (DefaultDocument) super.clone();
127         document.rootElement = null;
128         document.content = null;
129         document.appendContent(this);
130 
131         return document;
132     }
133 
134     public List processingInstructions() {
135         List source = contentList();
136         List answer = createResultList();
137         int size = source.size();
138 
139         for (int i = 0; i < size; i++) {
140             Object object = source.get(i);
141 
142             if (object instanceof ProcessingInstruction) {
143                 answer.add(object);
144             }
145         }
146 
147         return answer;
148     }
149 
150     public List processingInstructions(String target) {
151         List source = contentList();
152         List answer = createResultList();
153         int size = source.size();
154 
155         for (int i = 0; i < size; i++) {
156             Object object = source.get(i);
157 
158             if (object instanceof ProcessingInstruction) {
159                 ProcessingInstruction pi = (ProcessingInstruction) object;
160 
161                 if (target.equals(pi.getName())) {
162                     answer.add(pi);
163                 }
164             }
165         }
166 
167         return answer;
168     }
169 
170     public ProcessingInstruction processingInstruction(String target) {
171         List source = contentList();
172         int size = source.size();
173 
174         for (int i = 0; i < size; i++) {
175             Object object = source.get(i);
176 
177             if (object instanceof ProcessingInstruction) {
178                 ProcessingInstruction pi = (ProcessingInstruction) object;
179 
180                 if (target.equals(pi.getName())) {
181                     return pi;
182                 }
183             }
184         }
185 
186         return null;
187     }
188 
189     public boolean removeProcessingInstruction(String target) {
190         List source = contentList();
191 
192         for (Iterator iter = source.iterator(); iter.hasNext();) {
193             Object object = iter.next();
194 
195             if (object instanceof ProcessingInstruction) {
196                 ProcessingInstruction pi = (ProcessingInstruction) object;
197 
198                 if (target.equals(pi.getName())) {
199                     iter.remove();
200 
201                     return true;
202                 }
203             }
204         }
205 
206         return false;
207     }
208 
209     public void setContent(List content) {
210         rootElement = null;
211         contentRemoved();
212 
213         if (content instanceof ContentListFacade) {
214             content = ((ContentListFacade) content).getBackingList();
215         }
216 
217         if (content == null) {
218             this.content = null;
219         } else {
220             int size = content.size();
221             List newContent = createContentList(size);
222 
223             for (int i = 0; i < size; i++) {
224                 Object object = content.get(i);
225 
226                 if (object instanceof Node) {
227                     Node node = (Node) object;
228                     Document doc = node.getDocument();
229 
230                     if ((doc != null) && (doc != this)) {
231                         node = (Node) node.clone();
232                     }
233 
234                     if (node instanceof Element) {
235                         if (rootElement == null) {
236                             rootElement = (Element) node;
237                         } else {
238                             throw new IllegalAddException(
239                                     "A document may only "
240                                             + "contain one root " + "element: "
241                                             + content);
242                         }
243                     }
244 
245                     newContent.add(node);
246                     childAdded(node);
247                 }
248             }
249 
250             this.content = newContent;
251         }
252     }
253 
254     public void clearContent() {
255         contentRemoved();
256         content = null;
257         rootElement = null;
258     }
259 
260     public void setDocumentFactory(DocumentFactory documentFactory) {
261         this.documentFactory = documentFactory;
262     }
263 
264     // Implementation methods
265     // -------------------------------------------------------------------------
266     protected List contentList() {
267         if (content == null) {
268             content = createContentList();
269 
270             if (rootElement != null) {
271                 content.add(rootElement);
272             }
273         }
274 
275         return content;
276     }
277 
278     protected void addNode(Node node) {
279         if (node != null) {
280             Document document = node.getDocument();
281 
282             if ((document != null) && (document != this)) {
283                 // XXX: could clone here
284                 String message = "The Node already has an existing document: "
285                         + document;
286                 throw new IllegalAddException(this, node, message);
287             }
288 
289             contentList().add(node);
290             childAdded(node);
291         }
292     }
293 
294     protected void addNode(int index, Node node) {
295         if (node != null) {
296             Document document = node.getDocument();
297 
298             if ((document != null) && (document != this)) {
299                 // XXX: could clone here
300                 String message = "The Node already has an existing document: "
301                         + document;
302                 throw new IllegalAddException(this, node, message);
303             }
304 
305             contentList().add(index, node);
306             childAdded(node);
307         }
308     }
309 
310     protected boolean removeNode(Node node) {
311         if (node == rootElement) {
312             rootElement = null;
313         }
314 
315         if (contentList().remove(node)) {
316             childRemoved(node);
317 
318             return true;
319         }
320 
321         return false;
322     }
323 
324     protected void rootElementAdded(Element element) {
325         this.rootElement = element;
326         element.setDocument(this);
327     }
328 
329     protected DocumentFactory getDocumentFactory() {
330         return documentFactory;
331     }
332 }
333 
334 /*
335  * Redistribution and use of this software and associated documentation
336  * ("Software"), with or without modification, are permitted provided that the
337  * following conditions are met:
338  * 
339  * 1. Redistributions of source code must retain copyright statements and
340  * notices. Redistributions must also contain a copy of this document.
341  * 
342  * 2. Redistributions in binary form must reproduce the above copyright notice,
343  * this list of conditions and the following disclaimer in the documentation
344  * and/or other materials provided with the distribution.
345  * 
346  * 3. The name "DOM4J" must not be used to endorse or promote products derived
347  * from this Software without prior written permission of MetaStuff, Ltd. For
348  * written permission, please contact dom4j-info@metastuff.com.
349  * 
350  * 4. Products derived from this Software may not be called "DOM4J" nor may
351  * "DOM4J" appear in their names without prior written permission of MetaStuff,
352  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
353  * 
354  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
355  * 
356  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
357  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
358  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
359  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
360  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
361  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
362  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
363  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
364  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
365  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
366  * POSSIBILITY OF SUCH DAMAGE.
367  * 
368  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
369  */