View Javadoc

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