parentnode.java

来自「JAVA 所有包」· Java 代码 · 共 1,032 行 · 第 1/3 页

JAVA
1,032
字号
/* * Copyright 1999-2002,2004,2005 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.sun.org.apache.xerces.internal.dom;import java.io.Serializable;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import org.w3c.dom.DOMException;import org.w3c.dom.Document;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import org.w3c.dom.UserDataHandler;/** * ParentNode inherits from ChildNode and adds the capability of having child * nodes. Not every node in the DOM can have children, so only nodes that can * should inherit from this class and pay the price for it. * <P> * ParentNode, just like NodeImpl, also implements NodeList, so it can * return itself in response to the getChildNodes() query. This eliminiates * the need for a separate ChildNodeList object. Note that this is an * IMPLEMENTATION DETAIL; applications should _never_ assume that * this identity exists. On the other hand, subclasses may need to override * this, in case of conflicting names. This is the case for the classes * HTMLSelectElementImpl and HTMLFormElementImpl of the HTML DOM. * <P> * While we have a direct reference to the first child, the last child is * stored as the previous sibling of the first child. First child nodes are * marked as being so, and getNextSibling hides this fact. * <P>Note: Not all parent nodes actually need to also be a child. At some * point we used to have ParentNode inheriting from NodeImpl and another class * called ChildAndParentNode that inherited from ChildNode. But due to the lack * of multiple inheritance a lot of code had to be duplicated which led to a * maintenance nightmare. At the same time only a few nodes (Document, * DocumentFragment, Entity, and Attribute) cannot be a child so the gain in * memory wasn't really worth it. The only type for which this would be the * case is Attribute, but we deal with there in another special way, so this is * not applicable. * <p> * This class doesn't directly support mutation events, however, it notifies * the document when mutations are performed so that the document class do so. * * <p><b>WARNING</b>: Some of the code here is partially duplicated in * AttrImpl, be careful to keep these two classes in sync! *  * @xerces.internal * * @author Arnaud  Le Hors, IBM * @author Joe Kesselman, IBM * @author Andy Clark, IBM * @version $Id: ParentNode.java,v 1.2.6.1 2005/08/31 12:39:32 sunithareddy Exp $ */public abstract class ParentNode    extends ChildNode {    /** Serialization version. */    static final long serialVersionUID = 2815829867152120872L;    /** Owner document. */    protected CoreDocumentImpl ownerDocument;    /** First child. */    protected ChildNode firstChild = null;    // transients    /** NodeList cache */    protected transient NodeListCache fNodeListCache = null;    //    // Constructors    //    /**     * No public constructor; only subclasses of ParentNode should be     * instantiated, and those normally via a Document's factory methods     */    protected ParentNode(CoreDocumentImpl ownerDocument) {        super(ownerDocument);        this.ownerDocument = ownerDocument;    }    /** Constructor for serialization. */    public ParentNode() {}    //    // NodeList methods    //    /**     * Returns a duplicate of a given node. You can consider this a     * generic "copy constructor" for nodes. The newly returned object should     * be completely independent of the source object's subtree, so changes     * in one after the clone has been made will not affect the other.     * <p>     * Example: Cloning a Text node will copy both the node and the text it     * contains.     * <p>     * Example: Cloning something that has children -- Element or Attr, for     * example -- will _not_ clone those children unless a "deep clone"     * has been requested. A shallow clone of an Attr node will yield an     * empty Attr of the same name.     * <p>     * NOTE: Clones will always be read/write, even if the node being cloned     * is read-only, to permit applications using only the DOM API to obtain     * editable copies of locked portions of the tree.     */    public Node cloneNode(boolean deep) {    	        if (needsSyncChildren()) {            synchronizeChildren();        }    	ParentNode newnode = (ParentNode) super.cloneNode(deep);        // set owner document        newnode.ownerDocument = ownerDocument;    	// Need to break the association w/ original kids    	newnode.firstChild      = null;        // invalidate cache for children NodeList        newnode.fNodeListCache = null;        // Then, if deep, clone the kids too.    	if (deep) {            for (ChildNode child = firstChild;                 child != null;                 child = child.nextSibling) {                newnode.appendChild(child.cloneNode(true));            }        }    	return newnode;    } // cloneNode(boolean):Node    /**     * Find the Document that this Node belongs to (the document in     * whose context the Node was created). The Node may or may not     * currently be part of that Document's actual contents.     */    public Document getOwnerDocument() {        return ownerDocument;    }    /**     * same as above but returns internal type and this one is not overridden     * by CoreDocumentImpl to return null     */    CoreDocumentImpl ownerDocument() {        return ownerDocument;    }    /**     * NON-DOM     * set the ownerDocument of this node and its children     */    void setOwnerDocument(CoreDocumentImpl doc) {        if (needsSyncChildren()) {            synchronizeChildren();        }       for (ChildNode child = firstChild;	     child != null; child = child.nextSibling) {             child.setOwnerDocument(doc);	}        /* setting the owner document of self, after it's children makes the            data of children available to the new document. */        super.setOwnerDocument(doc);        ownerDocument = doc;    }    /**     * Test whether this node has any children. Convenience shorthand     * for (Node.getFirstChild()!=null)     */    public boolean hasChildNodes() {        if (needsSyncChildren()) {            synchronizeChildren();        }        return firstChild != null;    }    /**     * Obtain a NodeList enumerating all children of this node. If there     * are none, an (initially) empty NodeList is returned.     * <p>     * NodeLists are "live"; as children are added/removed the NodeList     * will immediately reflect those changes. Also, the NodeList refers     * to the actual nodes, so changes to those nodes made via the DOM tree     * will be reflected in the NodeList and vice versa.     * <p>     * In this implementation, Nodes implement the NodeList interface and     * provide their own getChildNodes() support. Other DOMs may solve this     * differently.     */    public NodeList getChildNodes() {        if (needsSyncChildren()) {            synchronizeChildren();        }        return this;    } // getChildNodes():NodeList    /** The first child of this Node, or null if none. */    public Node getFirstChild() {        if (needsSyncChildren()) {            synchronizeChildren();        }    	return firstChild;    }   // getFirstChild():Node    /** The last child of this Node, or null if none. */    public Node getLastChild() {        if (needsSyncChildren()) {            synchronizeChildren();        }        return lastChild();    } // getLastChild():Node    final ChildNode lastChild() {        // last child is stored as the previous sibling of first child        return firstChild != null ? firstChild.previousSibling : null;    }    final void lastChild(ChildNode node) {        // store lastChild as previous sibling of first child        if (firstChild != null) {            firstChild.previousSibling = node;        }    }    /**     * Move one or more node(s) to our list of children. Note that this     * implicitly removes them from their previous parent.     *     * @param newChild The Node to be moved to our subtree. As a     * convenience feature, inserting a DocumentNode will instead insert     * all its children.     *     * @param refChild Current child which newChild should be placed     * immediately before. If refChild is null, the insertion occurs     * after all existing Nodes, like appendChild().     *     * @return newChild, in its new state (relocated, or emptied in the case of     * DocumentNode.)     *     * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a     * type that shouldn't be a child of this node, or if newChild is an     * ancestor of this node.     *     * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a     * different owner document than we do.     *     * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of     * this node.     *     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is     * read-only.     */    public Node insertBefore(Node newChild, Node refChild)         throws DOMException {        // Tail-call; optimizer should be able to do good things with.        return internalInsertBefore(newChild, refChild, false);    } // insertBefore(Node,Node):Node         /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able     * to control which mutation events are spawned. This version of the     * insertBefore operation allows us to do so. It is not intended     * for use by application programs.     */    Node internalInsertBefore(Node newChild, Node refChild, boolean replace)         throws DOMException {        boolean errorChecking = ownerDocument.errorChecking;        if (newChild.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {            // SLOW BUT SAFE: We could insert the whole subtree without            // juggling so many next/previous pointers. (Wipe out the            // parent's child-list, patch the parent pointers, set the            // ends of the list.) But we know some subclasses have special-            // case behavior they add to insertBefore(), so we don't risk it.            // This approch also takes fewer bytecodes.            // NOTE: If one of the children is not a legal child of this            // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children            // have been transferred. (Alternative behaviors would be to            // reparent up to the first failure point or reparent all those            // which are acceptable to the target node, neither of which is            // as robust. PR-DOM-0818 isn't entirely clear on which it            // recommends?????            // No need to check kids for right-document; if they weren't,            // they wouldn't be kids of that DocFrag.            if (errorChecking) {                for (Node kid = newChild.getFirstChild(); // Prescan                     kid != null; kid = kid.getNextSibling()) {                    if (!ownerDocument.isKidOK(this, kid)) {                        throw new DOMException(                              DOMException.HIERARCHY_REQUEST_ERR,                               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null));                    }                }            }            while (newChild.hasChildNodes()) {                insertBefore(newChild.getFirstChild(), refChild);            }            return newChild;        }        if (newChild == refChild) {            // stupid case that must be handled as a no-op triggering events...            refChild = refChild.getNextSibling();            removeChild(newChild);            insertBefore(newChild, refChild);            return newChild;        }        if (needsSyncChildren()) {            synchronizeChildren();        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?