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: AbstractNode.java,v 1.23 2001/09/15 14:55:14 jstrachan Exp $
008 */
009
010package org.dom4j.tree;
011
012import java.io.IOException;
013import java.io.Serializable;
014import java.io.StringWriter;
015import java.io.Writer;
016import java.util.List;
017
018import org.dom4j.Document;
019import org.dom4j.DocumentFactory;
020import org.dom4j.Element;
021import org.dom4j.Node;
022import org.dom4j.NodeFilter;
023import org.dom4j.Visitor;
024import org.dom4j.XPath;
025import org.dom4j.rule.Pattern;
026
027/** <p><code>AbstractNode</code> is an abstract base class for 
028  * tree implementors to use for implementation inheritence.</p>
029 *
030 * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a>
031 * @version $Revision: 1.23 $
032 */
033public abstract class AbstractNode implements Node, Cloneable, Serializable {
034    
035    protected static final String[] NODE_TYPE_NAMES ={
036        "Node", "Element", "Attribute", "Text", "CDATA", "Entity", "Entity", "ProcessingInstruction", 
037        "Comment", "Document", "DocumentType", "DocumentFragment", "Notation", "Namespace","Unknown" 
038    };
039    
040    /** The <code>DocumentFactory</code> instance used by default */
041    private static final DocumentFactory DOCUMENT_FACTORY = DocumentFactory.getInstance();
042    
043
044    public AbstractNode() {
045    }
046
047    public short getNodeType() {
048        return UNKNOWN_NODE;
049    }
050
051    public String getNodeTypeName() {
052        int type = getNodeType();
053        if ( type < 0 || type >= NODE_TYPE_NAMES.length ) {
054            return "Unknown";
055        }
056        return NODE_TYPE_NAMES[type];
057    }
058    
059    public Document getDocument() {
060        Element element = getParent();
061        return ( element != null ) ? element.getDocument() : null;
062    }
063    
064    public void setDocument(Document document) {
065    }
066    
067    public Element getParent() {
068        return null;
069    }
070
071    public void setParent(Element parent) {
072    }
073    
074    public boolean supportsParent() {
075        return false;
076    }
077
078    public boolean isReadOnly() {
079        return true;
080    }
081    
082    public boolean hasContent() {
083        return false;
084    }
085    
086    public String getPath() {
087        return getPath(null);
088    }
089    
090    public String getUniquePath() {
091        return getUniquePath(null);
092    }
093    
094
095    public Object clone() {
096        if ( isReadOnly() ) {
097            return this;
098        }
099        else {
100            try {
101                Node answer = (Node) super.clone();
102                answer.setParent( null );
103                answer.setDocument( null );
104                return answer;
105            }
106            catch (CloneNotSupportedException e) {
107                // should never happen
108                throw new RuntimeException( "This should never happen. Caught: " + e );
109            }
110        }
111    }
112
113    public Node detach() {
114        Element parent = getParent();
115        if ( parent != null ) {
116            parent.remove( this );
117        }
118        else {
119            Document document = getDocument();
120            if ( document != null ) {
121                document.remove( this );
122            }
123        }
124        setParent(null);
125        setDocument(null);
126        return this;
127    }
128    
129    public String getName() {
130        return null;
131    }
132
133    public void setName(String name) {
134        throw new UnsupportedOperationException( "This node cannot be modified" );
135    }
136
137    public String getText() {
138        return null;
139    }
140    
141    public String getStringValue() {
142        return getText();
143    }
144    
145    public void setText(String text) {
146        throw new UnsupportedOperationException( "This node cannot be modified" );
147    }
148    
149    
150    public void write(Writer writer) throws IOException {
151        writer.write( asXML() );
152    }
153        
154
155    // XPath methods
156    
157    public Object selectObject(String xpathExpression) {
158        XPath xpath = createXPath(xpathExpression);
159        return xpath.selectObject(this);
160    }
161    
162    public List selectNodes(String xpathExpression) {
163        XPath xpath = createXPath(xpathExpression);
164        return xpath.selectNodes(this);
165    }
166    
167    public List selectNodes( 
168        String xpathExpression, 
169        String comparisonXPathExpression 
170    ) {
171        return selectNodes( 
172            xpathExpression,  comparisonXPathExpression, false 
173        );
174    }
175    
176    public List selectNodes(
177        String xpathExpression, 
178        String comparisonXPathExpression, 
179        boolean removeDuplicates
180    ) {
181        XPath xpath = createXPath(xpathExpression);
182        XPath sortBy = createXPath(comparisonXPathExpression);
183        return xpath.selectNodes(this, sortBy, removeDuplicates);
184    }
185    
186    public Node selectSingleNode(String xpathExpression) {
187        XPath xpath = createXPath(xpathExpression);
188        return xpath.selectSingleNode(this);
189    }
190    
191    public String valueOf(String xpathExpression) {
192        XPath xpath = createXPath(xpathExpression);
193        return xpath.valueOf(this);
194    }
195    
196    public Number numberValueOf(String xpathExpression) {
197        XPath xpath = createXPath(xpathExpression);
198        return xpath.numberValueOf(this);
199    }
200    
201    public boolean matches(String patternText) {        
202        NodeFilter filter = createXPathFilter(patternText);
203        return filter.matches(this);
204    }
205    
206    public XPath createXPath(String xpathExpression) {
207        return getDocumentFactory().createXPath(xpathExpression);
208    }
209    
210    public NodeFilter createXPathFilter(String patternText) {
211        return getDocumentFactory().createXPathFilter(patternText);
212    }
213    
214    public Pattern createPattern(String patternText) {
215        return getDocumentFactory().createPattern(patternText);
216    }
217    
218    
219    public Node asXPathResult(Element parent) {
220        if (supportsParent()) {
221            return this;
222        }
223        return createXPathResult(parent);
224    }
225    
226    protected DocumentFactory getDocumentFactory() {
227        return DOCUMENT_FACTORY;
228    }
229    
230    protected Node createXPathResult(Element parent) {
231        throw new RuntimeException("asXPathResult() not yet implemented fully for: " + this );
232    }
233    
234}
235
236
237
238
239/*
240 * Redistribution and use of this software and associated documentation
241 * ("Software"), with or without modification, are permitted provided
242 * that the following conditions are met:
243 *
244 * 1. Redistributions of source code must retain copyright
245 *    statements and notices.  Redistributions must also contain a
246 *    copy of this document.
247 *
248 * 2. Redistributions in binary form must reproduce the
249 *    above copyright notice, this list of conditions and the
250 *    following disclaimer in the documentation and/or other
251 *    materials provided with the distribution.
252 *
253 * 3. The name "DOM4J" must not be used to endorse or promote
254 *    products derived from this Software without prior written
255 *    permission of MetaStuff, Ltd.  For written permission,
256 *    please contact dom4j-info@metastuff.com.
257 *
258 * 4. Products derived from this Software may not be called "DOM4J"
259 *    nor may "DOM4J" appear in their names without prior written
260 *    permission of MetaStuff, Ltd. DOM4J is a registered
261 *    trademark of MetaStuff, Ltd.
262 *
263 * 5. Due credit should be given to the DOM4J Project
264 *    (http://dom4j.org/).
265 *
266 * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
267 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
268 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
269 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
270 * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
271 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
272 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
273 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
274 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
275 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
276 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
277 * OF THE POSSIBILITY OF SUCH DAMAGE.
278 *
279 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
280 *
281 * $Id: AbstractNode.java,v 1.23 2001/09/15 14:55:14 jstrachan Exp $
282 */