001/*
002 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
003 * 
004 * This software is open source. 
005 * See the bottom of this file for the licence.
006 * 
007 * $Id: AbstractDocument.java,v 1.22 2001/07/25 10:51:11 jstrachan Exp $
008 */
009
010package org.dom4j.tree;
011
012import java.io.IOException;
013import java.io.StringWriter;
014import java.io.Writer;
015import java.util.Iterator;
016import java.util.List;
017import java.util.Map;
018
019import org.dom4j.Attribute;
020import org.dom4j.CDATA;
021import org.dom4j.Comment;
022import org.dom4j.Document;
023import org.dom4j.DocumentType;
024import org.dom4j.Element;
025import org.dom4j.IllegalAddException;
026import org.dom4j.Node;
027import org.dom4j.Namespace;
028import org.dom4j.ProcessingInstruction;
029import org.dom4j.QName;
030import org.dom4j.Text;
031import org.dom4j.Visitor;
032import org.dom4j.io.XMLWriter;
033
034/** <p><code>AbstractDocument</code> is an abstract base class for 
035  * tree implementors to use for implementation inheritence.</p>
036  *
037  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
038  * @version $Revision: 1.22 $
039  */
040public abstract class AbstractDocument extends AbstractBranch implements Document {
041    
042    public AbstractDocument() { 
043    }
044 
045    public short getNodeType() {
046        return DOCUMENT_NODE;
047    }
048
049    public String getPath(Element context) {
050        return "/";
051    }
052    
053    public String getUniquePath(Element context) {
054        return "/";
055    }
056    
057    public Document getDocument() {
058        return this;
059    }
060    
061    public String getStringValue() {
062        Element root = getRootElement();
063        return ( root != null ) ? root.getStringValue() : "";
064    }
065    
066    public String asXML() {
067        try {
068            StringWriter out = new StringWriter();
069            XMLWriter writer = new XMLWriter( out, outputFormat );
070            writer.write(this);
071            return out.toString();
072        } 
073        catch (IOException e) {
074            throw new RuntimeException("Wierd IOException while generating textual representation: " + e.getMessage());
075        }
076    }
077
078    public void write(Writer out) throws IOException {
079        XMLWriter writer = new XMLWriter( out, outputFormat );
080        writer.write(this);
081    }
082        
083    /** <p><code>accept</code> method is the <code>Visitor Pattern</code> method.
084      * </p>
085      *
086      * @param visitor <code>Visitor</code> is the visitor.
087      */
088    public void accept(Visitor visitor) {
089        visitor.visit(this);
090
091        DocumentType docType = getDocType();
092        if ( docType != null ) {
093            visitor.visit( docType );
094        }
095        
096        // visit content
097        List content = content();
098        if (content != null) {
099            for ( Iterator iter = content.iterator(); iter.hasNext(); ) {
100                Object object = iter.next();
101                if (object instanceof String) {
102                    Text text = getDocumentFactory().createText((String) object);
103                    visitor.visit(text);
104                } 
105                else {
106                    Node node = (Node) object;
107                    node.accept(visitor);
108                }
109            }            
110        }
111    }
112    
113    public String toString() {
114        return super.toString() + " [Document: name " + getName() + "]";
115    }
116    
117    public void normalize() {
118        Element element = getRootElement();
119        if ( element != null ) {
120            element.normalize();
121        }
122    }
123    
124    public Document addComment(String comment) {
125        Comment node = getDocumentFactory().createComment( comment );
126        add( node );
127        return this;
128    }
129       
130    public Document addProcessingInstruction(String target, String data) {
131        ProcessingInstruction node = getDocumentFactory().createProcessingInstruction( target, data );
132        add( node );
133        return this;
134    }
135    
136    public Document addProcessingInstruction(String target, Map data) {
137        ProcessingInstruction node = getDocumentFactory().createProcessingInstruction( target, data );
138        add( node );
139        return this;
140    }
141    
142    public Element addElement(String name) {
143        checkAddElementAllowed();
144        Element node = super.addElement(name);
145        rootElementAdded(node);
146        return node;
147    }
148    
149    public Element addElement(String qualifiedName, String namespaceURI) {
150        checkAddElementAllowed();
151        Element node = super.addElement(qualifiedName, namespaceURI);
152        rootElementAdded(node);
153        return node;
154    }
155    
156    public Element addElement(QName qName) {
157        checkAddElementAllowed();
158        Element node = super.addElement(qName);
159        rootElementAdded(node);
160        return node;
161    }
162
163    public void setRootElement(Element rootElement) {
164        clearContent();
165        if ( rootElement != null ) {
166            super.add(rootElement);
167            rootElementAdded(rootElement);
168        }
169    }
170
171    public void add(Element element) {
172        checkAddElementAllowed();
173        super.add(element);
174        rootElementAdded(element);
175    }
176    
177    public boolean remove(Element element) {
178        boolean answer = super.remove(element);        
179        Element root = getRootElement();
180        if ( root != null && answer ) {
181            setRootElement(null);
182        }
183        element.setDocument(null);
184        return answer;
185    }
186        
187    public Node asXPathResult(Element parent) {
188        return this;
189    }
190    
191    
192    
193    
194    protected void childAdded(Node node) {
195        if (node != null ) {
196            node.setDocument(this);
197        }
198    }
199    
200    protected void childRemoved(Node node) {
201        if ( node != null ) {
202            node.setDocument(null);
203        }
204    }     
205
206    protected void checkAddElementAllowed() {
207        Element root = getRootElement();
208        if ( root != null ) {
209            throw new IllegalAddException(  
210                this, 
211                root, 
212                "Cannot add another element to this Document as it already has "
213                + " a root element of: " + root.getQualifiedName()
214            );
215        }
216    }
217
218    /** Called to set the root element variable */
219    protected abstract void rootElementAdded(Element rootElement);
220    
221}
222
223
224
225
226/*
227 * Redistribution and use of this software and associated documentation
228 * ("Software"), with or without modification, are permitted provided
229 * that the following conditions are met:
230 *
231 * 1. Redistributions of source code must retain copyright
232 *    statements and notices.  Redistributions must also contain a
233 *    copy of this document.
234 *
235 * 2. Redistributions in binary form must reproduce the
236 *    above copyright notice, this list of conditions and the
237 *    following disclaimer in the documentation and/or other
238 *    materials provided with the distribution.
239 *
240 * 3. The name "DOM4J" must not be used to endorse or promote
241 *    products derived from this Software without prior written
242 *    permission of MetaStuff, Ltd.  For written permission,
243 *    please contact dom4j-info@metastuff.com.
244 *
245 * 4. Products derived from this Software may not be called "DOM4J"
246 *    nor may "DOM4J" appear in their names without prior written
247 *    permission of MetaStuff, Ltd. DOM4J is a registered
248 *    trademark of MetaStuff, Ltd.
249 *
250 * 5. Due credit should be given to the DOM4J Project
251 *    (http://dom4j.org/).
252 *
253 * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
254 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
255 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
256 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
257 * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
258 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
259 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
260 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
261 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
262 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
263 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
264 * OF THE POSSIBILITY OF SUCH DAMAGE.
265 *
266 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
267 *
268 * $Id: AbstractDocument.java,v 1.22 2001/07/25 10:51:11 jstrachan Exp $
269 */