| /* |
| * $Id$ |
| * |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 2000 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Crimson" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 1999, Sun Microsystems, Inc., |
| * http://www.sun.com. For more information on the Apache Software |
| * Foundation, please see <http://www.apache.org/>. |
| */ |
| |
| package org.apache.xerces.tree; |
| |
| |
| import java.io.Writer; |
| import java.io.IOException; |
| import java.util.Locale; |
| |
| import org.w3c.dom.*; |
| |
| |
| /** |
| * Base class for DOM parse tree nodes which may appear in XmlDocument nodes. |
| * This implements "parented by" and "owning document" relationships. If |
| * the parent is not null, this also supports sibling relationships through |
| * that parent. Children may be directly accessed through this class, |
| * although it is subclasses which implement that access. |
| * |
| * @author David Brownell |
| * @version $Revision$ |
| */ |
| // not public ... javadoc looks a bit odd (hidden base class) |
| // but it's only subclassable within this package anyway |
| abstract class NodeBase |
| implements Node, NodeEx, NodeList, XmlWritable |
| { |
| private ParentNode parent; |
| private int parentIndex = -1; // cache |
| |
| // package private for speed ... |
| XmlDocument ownerDocument; |
| boolean readonly; |
| |
| /** |
| * Constructs a node which will later have its parent set |
| * by some other member of this package. |
| */ |
| // package private |
| NodeBase () { } |
| |
| /* Returns the node's parent; typesafe convenience rtn. */ |
| // package private ... |
| ParentNode getParentImpl () { return parent; } |
| |
| /* not public yet ... */ |
| // package private |
| public boolean isReadonly () |
| { return readonly; } |
| |
| /* not public yet ... */ |
| // package private |
| public void setReadonly (boolean deep) |
| { |
| readonly = true; |
| if (deep) { |
| TreeWalker walker = new TreeWalker (this); |
| Node next; |
| while ((next = walker.getNext ()) != null) |
| ((NodeBase)next).setReadonly (false); |
| } |
| } |
| |
| /** |
| * Returns the language id (value of <code>xml:lang</code> |
| * attribute) applicable to this node, if known. Traces up |
| * through ancestors as needed. |
| */ |
| public String getLanguage () { |
| return getInheritedAttribute ("xml:lang"); |
| } |
| |
| /** |
| * Returns the value of a given attribute, tracing up through |
| * ancestors if needed. In the XML standard, two attributes are |
| * inherited: <em>xml:lang</em> and <em>xml:space</em>. This |
| * mechanism can also be involved with Cascading Style Sheets (CSS). |
| * The current version of XML Namespaces also uses inheritance. |
| * |
| * @param name identifies the attribute; colons may be included, |
| * but namespace prefixes are not interpreted |
| * @return the value of the inherited attribute, or null if |
| * no value was inherited. |
| */ |
| public String getInheritedAttribute (String name) |
| { |
| NodeBase current = this; |
| Attr value = null; |
| |
| do { |
| if (current instanceof ElementNode) { |
| ElementNode e = (ElementNode) current; |
| |
| if ((value = e.getAttributeNode (name)) != null) |
| break; |
| } |
| current = current.getParentImpl (); |
| } while (current != null); |
| if (value != null) |
| return value.getValue (); |
| return null; |
| } |
| |
| /** |
| * Returns the value of a given attribute, tracing up through |
| * ancestors if needed. This version accounts for namespaces, |
| * so that the prefix used to identify the namespace of any |
| * particular attribute is ignored when returning its value. |
| * |
| * @param namespace URI associated with the namespace, or null |
| * to indicate the default namespace |
| * @param name colon-free "local part" of the attribute name |
| * @return the value of the inherited attribute, or null if |
| * no value was inherited. |
| */ |
| public String getInheritedAttribute (String namespace, String name) |
| { |
| NodeBase current = this; |
| Attr value = null; |
| |
| do { |
| if (current instanceof ElementNode) { |
| ElementNode e = (ElementNode) current; |
| |
| if ((value = e.getAttributeNode (namespace, name)) != null) |
| break; |
| } |
| current = current.getParentImpl (); |
| } while (current != null); |
| if (value != null) |
| return value.getValue (); |
| return null; |
| } |
| |
| /** |
| * Does nothing; this type of node has no children. |
| */ |
| public void writeChildrenXml (XmlWriteContext context) throws IOException |
| { |
| } |
| |
| // DOM support from W3C recommendation |
| |
| /** |
| * <b>DOM:</b> Returns the node's parent. This will be null in cases such |
| * as newly created or removed nodes, and for attributes, fragments, |
| * and documents. |
| */ |
| public Node getParentNode () { |
| return parent; |
| } |
| |
| |
| /* |
| * Assigns the node's parent, and remove it from its current parent. |
| * The caller is responsible for letting the new parent know about |
| * this child by inserting it into the set of children at the |
| * appropriate place, if it's not null. |
| * |
| * <P> Note that this method, of necessity, involves the DOM being in |
| * an internally inconsistent state, either with the new parent not yet |
| * knowing about its child-to-be after this call, or this node not |
| * knowing its true parent before the call. That's why it's not a |
| * public API, here or in DOM. |
| */ |
| void setParentNode (ParentNode arg, int index) |
| throws DOMException |
| { |
| if (parent != null && arg != null) |
| parent.removeChild (this); |
| parent = arg; |
| parentIndex = index; |
| } |
| |
| |
| // assigns the owner of this document |
| void setOwnerDocument (XmlDocument doc) |
| { |
| ownerDocument = doc; |
| } |
| |
| /** |
| * <b>DOM:</b> Returns the document to which this node belongs. |
| */ |
| public Document getOwnerDocument () |
| { |
| return ownerDocument; |
| } |
| |
| |
| /** |
| * <b>DOM:</b> Returns false. |
| * Overridden by subclasses which support children. |
| */ |
| public boolean hasChildNodes() { return false; } |
| |
| /** |
| * <b>DOM:</b> does nothing; overridden by subclasses as needed. |
| */ |
| public void setNodeValue (String value) |
| { |
| if (readonly) |
| throw new DomEx (DomEx.NO_MODIFICATION_ALLOWED_ERR); |
| } |
| |
| /** |
| * <b>DOM:</b> Returns null; overridden by subclasses as needed. |
| */ |
| public String getNodeValue () |
| { return null; } |
| |
| /** |
| * <b>DOM:</b> Returns null. |
| * Overridden by subclasses which support children. |
| */ |
| public Node getFirstChild () { return null; } |
| |
| |
| /** |
| * <b>DOM:</b> Returns zero. |
| * Overridden by subclasses which support children. |
| */ |
| public int getLength () { return 0; } |
| |
| |
| /** |
| * <b>DOM:</b> Returns null. |
| * Overridden by subclasses which support children. |
| */ |
| public Node item (int i) { return null; } |
| |
| |
| /** |
| * <b>DOM:</b> Returns an object which permits "live" access to all |
| * this node's children. |
| * |
| * <P> In this implementation, nodes provide such access without |
| * needing another node as an intermediary; "this" is returned. |
| */ |
| public NodeList getChildNodes () |
| { return this; } |
| |
| /** |
| * <b>DOM:</b> returns null. |
| * Overridden by subclasses which support children. |
| */ |
| public Node getLastChild () |
| { return null; } |
| |
| /** |
| * <b>DOM:</b> Throws a HIERARCHY_REQUEST_ERR DOMException. |
| * Overridden by subclasses which support children. |
| * @exception DOMException thrown always. |
| */ |
| public Node appendChild (Node newChild) |
| throws DOMException |
| { throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR); } |
| |
| /** |
| * <b>DOM:</b> Throws a HIERARCHY_REQUEST_ERR DOMException. |
| * Overridden by subclasses which support children. |
| * @exception DOMException thrown always. |
| */ |
| public Node insertBefore (Node newChild, Node refChild) |
| throws DOMException |
| { throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR); } |
| |
| /** |
| * <b>DOM:</b> Throws a HIERARCHY_REQUEST_ERR DOMException. |
| * Overridden by subclasses which support children. |
| * @exception DOMException thrown always. |
| */ |
| public Node replaceChild (Node newChild, Node refChild) |
| throws DOMException |
| { throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR); } |
| |
| /** |
| * <b>DOM:</b> Throws a HIERARCHY_REQUEST_ERR DOMException. |
| * Overridden by subclasses which support children. |
| * @exception DOMException thrown always. |
| */ |
| public Node removeChild (Node oldChild) |
| throws DOMException |
| { throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR); } |
| |
| |
| /** |
| * <b>DOM:</b> Returns the node immediately following this node in a |
| * breadth first traversal of the tree, or null if there is no |
| * such sibling. In this implementation, sibling access from a |
| * node is slower than indexed access from its parent. |
| */ |
| public Node getNextSibling () |
| { |
| if (parent == null) |
| return null; |
| if (parentIndex < 0 || parent.item (parentIndex) != this) |
| parentIndex = parent.getIndexOf (this); |
| return parent.item (parentIndex + 1); |
| } |
| |
| /** |
| * <b>DOM:</b> Returns the node immediately preceding this node in a |
| * breadth first traversal of the tree, or null if there is no |
| * such sibling. In this implementation, sibling access from a |
| * node is slower than indexed access from its parent. |
| */ |
| public Node getPreviousSibling () |
| { |
| if (parent == null) |
| return null; |
| if (parentIndex < 0 || parent.item (parentIndex) != this) |
| parentIndex = parent.getIndexOf (this); |
| return parent.item (parentIndex - 1); |
| } |
| |
| /** |
| * <b>DOM:</b> returns null. |
| * Overridden by the ElementNode subclass. |
| */ |
| public NamedNodeMap getAttributes () |
| { return null; } |
| |
| /** |
| * <b>DOM2:</b> noop. |
| * @since DOM Level 2 |
| * Overridden by subclasses that need to support normalization. |
| */ |
| public void normalize() { |
| } |
| |
| /** |
| * <b>DOM2:</b> |
| * @since DOM Level 2 |
| */ |
| public boolean supports(String feature, String version) { |
| return XmlDocument.hasFeature0(feature, version); |
| } |
| |
| /** |
| * <b>DOM2:</b> returns null. |
| * Overridden by subclasses that support namespaces, ie. ElementNode and |
| * AttributeNode. |
| */ |
| public String getNamespaceURI() { |
| return null; |
| } |
| |
| /** |
| * <b>DOM2:</b> returns null. |
| * Overridden by subclasses that support namespaces. |
| */ |
| public String getPrefix() { |
| return null; |
| } |
| |
| /** |
| * <b>DOM2:</b> throws DOMException.NAMESPACE_ERR |
| * Overridden by subclasses that support namespaces. |
| */ |
| public void setPrefix(String prefix) throws DOMException { |
| throw new DomEx(DomEx.NAMESPACE_ERR); |
| } |
| |
| /** |
| * <b>DOM2:</b> returns null. |
| * Overridden by subclasses that support namespaces. |
| */ |
| public String getLocalName() { |
| return null; |
| } |
| |
| public int getIndexOf (Node maybeChild) |
| { return -1; } |
| |
| /* |
| * Gets the messages from the resource bundles for the given messageId. |
| */ |
| String getMessage (String messageId) { |
| return getMessage (messageId, null); |
| } |
| |
| /* |
| * Gets the messages from the resource bundles for the given messageId |
| * after formatting it with the parameters passed to it. |
| */ |
| String getMessage (String messageId, Object[] parameters) { |
| Locale locale; |
| |
| if (this instanceof XmlDocument) |
| locale = ((XmlDocument)this).getLocale (); |
| else if (ownerDocument == null) |
| locale = Locale.getDefault (); // sigh |
| else |
| locale = ownerDocument.getLocale (); |
| return XmlDocument.catalog.getMessage (locale, messageId, parameters); |
| } |
| } |