attrimpl.java

来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 1,263 行 · 第 1/3 页

JAVA
1,263
字号
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999-2004 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 "Xerces" 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, International * Business Machines, Inc., http://www.apache.org.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */package com.sun.org.apache.xerces.internal.dom;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import org.w3c.dom.Attr;import org.w3c.dom.DOMException;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import org.w3c.dom.Text;import org.w3c.dom.TypeInfo;/** * Attribute represents an XML-style attribute of an * Element. Typically, the allowable values are controlled by its * declaration in the Document Type Definition (DTD) governing this * kind of document. * <P> * If the attribute has not been explicitly assigned a value, but has * been declared in the DTD, it will exist and have that default. Only * if neither the document nor the DTD specifies a value will the * Attribute really be considered absent and have no value; in that * case, querying the attribute will return null. * <P> * Attributes may have multiple children that contain their data. (XML * allows attributes to contain entity references, and tokenized * attribute types such as NMTOKENS may have a child for each token.) * For convenience, the Attribute object's getValue() method returns * the string version of the attribute's value. * <P> * Attributes are not children of the Elements they belong to, in the * usual sense, and have no valid Parent reference. However, the spec * says they _do_ belong to a specific Element, and an INUSE exception * is to be thrown if the user attempts to explicitly share them * between elements. * <P> * Note that Elements do not permit attributes to appear to be shared * (see the INUSE exception), so this object's mutability is * officially not an issue. * <p> * Note: The ownerNode attribute is used to store the Element the Attr * node is associated with. Attr nodes do not have parent nodes. * Besides, the getOwnerElement() method can be used to get the element node * this attribute is associated with. * <P> * AttrImpl does not support Namespaces. AttrNSImpl, which inherits from * it, does. * * <p>AttrImpl used to inherit from ParentNode. It now directly inherits from * NodeImpl and provide its own implementation of the ParentNode's behavior. * The reason is that we now try and avoid to always create a Text node to * hold the value of an attribute. The DOM spec requires it, so we still have * to do it in case getFirstChild() is called for instance. The reason * attribute values are stored as a list of nodes is so that they can carry * more than a simple string. They can also contain EntityReference nodes. * However, most of the times people only have a single string that they only * set and get through Element.set/getAttribute or Attr.set/getValue. In this * new version, the Attr node has a value pointer which can either be the * String directly or a pointer to the first ChildNode. A flag tells which one * it currently is. Note that while we try to stick with the direct String as * much as possible once we've switched to a node there is no going back. This * is because we have no way to know whether the application keeps referring to * the node we once returned. * <p> The gain in memory varies on the density of attributes in the document. * But in the tests I've run I've seen up to 12% of memory gain. And the good * thing is that it also leads to a slight gain in speed because we allocate * fewer objects! I mean, that's until we have to actually create the node... * <p> * To avoid too much duplicated code, I got rid of ParentNode and renamed * ChildAndParentNode, which I never really liked, to ParentNode for * simplicity, this doesn't make much of a difference in memory usage because * there are only very few objects that are only a Parent. This is only true * now because AttrImpl now inherits directly from NodeImpl and has its own * implementation of the ParentNode's node behavior. So there is still some * duplicated code there. * <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 * ParentNode, be careful to keep these two classes in sync! * * @see AttrNSImpl * * @author Arnaud  Le Hors, IBM * @author Joe Kesselman, IBM * @author Andy Clark, IBM * @version $Id: AttrImpl.java,v 1.55 2004/02/16 05:34:38 mrglavas Exp $ * @since PR-DOM-Level-1-19980818. * */public class AttrImpl    extends NodeImpl    implements Attr {    //    // Constants    //    /** Serialization version. */    static final long serialVersionUID = 7277707688218972102L;        /** DTD namespace. **/    static final String DTD_URI = "http://www.w3.org/TR/REC-xml";    //    // Data    //    /** This can either be a String or the first child node. */    protected Object value = null;    /** Attribute name. */    protected String name;        /** Type information */    // REVISIT: we are losing the type information in DOM during serialization    transient org.w3c.dom.TypeInfo type;    protected static TextImpl textNode = null;    //    // Constructors    //    /**     * Attribute has no public constructor. Please use the factory     * method in the Document class.     */    protected AttrImpl(CoreDocumentImpl ownerDocument, String name) {    	super(ownerDocument);        this.name = name;        /** False for default attributes. */        isSpecified(true);        hasStringValue(true);    }    // for AttrNSImpl    protected AttrImpl() {}    // Support for DOM Level 3 renameNode method.    // Note: This only deals with part of the pb. It is expected to be    // called after the Attr has been detached for one thing.    // CoreDocumentImpl does all the work.    void rename(String name) {        if (needsSyncData()) {            synchronizeData();        }        this.name = name;    }    // create a real text node as child if we don't have one yet    protected void makeChildNode() {        if (hasStringValue()) {            if (value != null) {                TextImpl text =                    (TextImpl) ownerDocument().createTextNode((String) value);                value = text;                text.isFirstChild(true);                text.previousSibling = text;                text.ownerNode = this;                text.isOwned(true);            }            hasStringValue(false);        }    }    /**     * NON-DOM     * set the ownerDocument of this node and its children     */    void setOwnerDocument(CoreDocumentImpl doc) {        if (needsSyncChildren()) {            synchronizeChildren();        }        super.setOwnerDocument(doc);        if (!hasStringValue()) {            for (ChildNode child = (ChildNode) value;                 child != null; child = child.nextSibling) {                child.setOwnerDocument(doc);            }        }    }    /**     * NON-DOM: set the type of this attribute to be ID type.     *      * @param id     */    public void setIdAttribute(boolean id){        if (needsSyncData()) {            synchronizeData();        }        isIdAttribute(id);    }    /** DOM Level 3: isId*/    public boolean isId(){        // REVISIT: should an attribute that is not in the tree return        // isID true?        return isIdAttribute();    }    //    // Node methods    //        public Node cloneNode(boolean deep) {        if (needsSyncChildren()) {            synchronizeChildren();        }        AttrImpl clone = (AttrImpl) super.cloneNode(deep);        // take care of case where there are kids    	if (!clone.hasStringValue()) {            // Need to break the association w/ original kids            clone.value = null;            // Cloning an Attribute always clones its children,             // since they represent its value, no matter whether this             // is a deep clone or not            for (Node child = (Node) value; child != null;                 child = child.getNextSibling()) {                 clone.appendChild(child.cloneNode(true));            }        }        clone.isSpecified(true);        return clone;    }    /**     * A short integer indicating what type of node this is. The named     * constants for this value are defined in the org.w3c.dom.Node interface.     */    public short getNodeType() {        return Node.ATTRIBUTE_NODE;    }    /**     * Returns the attribute name     */    public String getNodeName() {        if (needsSyncData()) {            synchronizeData();        }        return name;    }    /**     * Implicit in the rerouting of getNodeValue to getValue is the     * need to redefine setNodeValue, for symmetry's sake.  Note that     * since we're explicitly providing a value, Specified should be set     * true.... even if that value equals the default.     */    public void setNodeValue(String value) throws DOMException {    	setValue(value);    }        /**     * @see org.w3c.dom.TypeInfo#getTypeName()     */    public String getTypeName() {		 if(type != null)		 	return type.getTypeName();		 return null;    }    /**     * @see org.w3c.dom.TypeInfo#getTypeNamespace()     */    public String getTypeNamespace() {        if (type != null) {            return DTD_URI;        }        return null;    }        /**     * Method getSchemaTypeInfo.     * @return TypeInfo     */    public TypeInfo getSchemaTypeInfo(){        if (needsSyncData()) {            synchronizeData();        }        return type;    }    /**     * In Attribute objects, NodeValue is considered a synonym for     * Value.     *     * @see #getValue()     */    public String getNodeValue() {    	return getValue();    }    //    // Attr methods    //    /**     * In Attributes, NodeName is considered a synonym for the     * attribute's Name     */    public String getName() {        if (needsSyncData()) {            synchronizeData();        }    	return name;    } // getName():String    /**     * The DOM doesn't clearly define what setValue(null) means. I've taken it     * as "remove all children", which from outside should appear     * similar to setting it to the empty string.     */    public void setValue(String newvalue) {    	if (isReadOnly()) {            String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);        }        CoreDocumentImpl ownerDocument = ownerDocument();        Element ownerElement = getOwnerElement();        String oldvalue = "";        if (needsSyncData()) {            synchronizeData();        }        if (needsSyncChildren()) {            synchronizeChildren();        }        if (value != null) {            if (ownerDocument.getMutationEvents()) {                // Can no longer just discard the kids; they may have                // event listeners waiting for them to disconnect.                if (hasStringValue()) {                    oldvalue = (String) value;                    // create an actual text node as our child so                    // that we can use it in the event                    if (textNode == null) {                        textNode = (TextImpl)                            ownerDocument.createTextNode((String) value);                    }                    else {                        textNode.data = (String) value;                    }                    value = textNode;                    textNode.isFirstChild(true);                    textNode.previousSibling = textNode;                    textNode.ownerNode = this;                    textNode.isOwned(true);                    hasStringValue(false);                    internalRemoveChild(textNode, true);                }                else {                    oldvalue = getValue();

⌨️ 快捷键说明

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