0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.xerces.dom;
0019:
0020: import java.io.IOException;
0021: import java.io.ObjectOutputStream;
0022: import java.io.Serializable;
0023: import java.util.Hashtable;
0024:
0025: import org.w3c.dom.UserDataHandler;
0026: import org.w3c.dom.DOMException;
0027: import org.w3c.dom.Document;
0028: import org.w3c.dom.DocumentType;
0029: import org.w3c.dom.NamedNodeMap;
0030: import org.w3c.dom.Node;
0031: import org.w3c.dom.NodeList;
0032: import org.w3c.dom.events.Event;
0033: import org.w3c.dom.events.EventListener;
0034: import org.w3c.dom.events.EventTarget;
0035:
0036: /**
0037: * NodeImpl provides the basic structure of a DOM tree. It is never used
0038: * directly, but instead is subclassed to add type and data
0039: * information, and additional methods, appropriate to each node of
0040: * the tree. Only its subclasses should be instantiated -- and those,
0041: * with the exception of Document itself, only through a specific
0042: * Document's factory methods.
0043: * <P>
0044: * The Node interface provides shared behaviors such as siblings and
0045: * children, both for consistancy and so that the most common tree
0046: * operations may be performed without constantly having to downcast
0047: * to specific node types. When there is no obvious mapping for one of
0048: * these queries, it will respond with null.
0049: * Note that the default behavior is that children are forbidden. To
0050: * permit them, the subclass ParentNode overrides several methods.
0051: * <P>
0052: * NodeImpl also implements NodeList, so it can return itself in
0053: * response to the getChildNodes() query. This eliminiates the need
0054: * for a separate ChildNodeList object. Note that this is an
0055: * IMPLEMENTATION DETAIL; applications should _never_ assume that
0056: * this identity exists.
0057: * <P>
0058: * All nodes in a single document must originate
0059: * in that document. (Note that this is much tighter than "must be
0060: * same implementation") Nodes are all aware of their ownerDocument,
0061: * and attempts to mismatch will throw WRONG_DOCUMENT_ERR.
0062: * <P>
0063: * However, to save memory not all nodes always have a direct reference
0064: * to their ownerDocument. When a node is owned by another node it relies
0065: * on its owner to store its ownerDocument. Parent nodes always store it
0066: * though, so there is never more than one level of indirection.
0067: * And when a node doesn't have an owner, ownerNode refers to its
0068: * ownerDocument.
0069: * <p>
0070: * This class doesn't directly support mutation events, however, it still
0071: * implements the EventTarget interface and forward all related calls to the
0072: * document so that the document class do so.
0073: *
0074: * @xerces.internal
0075: *
0076: * @author Arnaud Le Hors, IBM
0077: * @author Joe Kesselman, IBM
0078: * @version $Id: NodeImpl.java 449328 2006-09-23 22:58:23Z mrglavas $
0079: * @since PR-DOM-Level-1-19980818.
0080: */
0081: public abstract class NodeImpl implements Node, NodeList, EventTarget,
0082: Cloneable, Serializable {
0083:
0084: //
0085: // Constants
0086: //
0087:
0088: // TreePosition Constants.
0089: // Taken from DOM L3 Node interface.
0090: /**
0091: * The node precedes the reference node.
0092: */
0093: public static final short TREE_POSITION_PRECEDING = 0x01;
0094: /**
0095: * The node follows the reference node.
0096: */
0097: public static final short TREE_POSITION_FOLLOWING = 0x02;
0098: /**
0099: * The node is an ancestor of the reference node.
0100: */
0101: public static final short TREE_POSITION_ANCESTOR = 0x04;
0102: /**
0103: * The node is a descendant of the reference node.
0104: */
0105: public static final short TREE_POSITION_DESCENDANT = 0x08;
0106: /**
0107: * The two nodes have an equivalent position. This is the case of two
0108: * attributes that have the same <code>ownerElement</code>, and two
0109: * nodes that are the same.
0110: */
0111: public static final short TREE_POSITION_EQUIVALENT = 0x10;
0112: /**
0113: * The two nodes are the same. Two nodes that are the same have an
0114: * equivalent position, though the reverse may not be true.
0115: */
0116: public static final short TREE_POSITION_SAME_NODE = 0x20;
0117: /**
0118: * The two nodes are disconnected, they do not have any common ancestor.
0119: * This is the case of two nodes that are not in the same document.
0120: */
0121: public static final short TREE_POSITION_DISCONNECTED = 0x00;
0122:
0123: // DocumentPosition
0124: public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
0125: public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
0126: public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
0127: public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
0128: public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
0129: public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
0130:
0131: /** Serialization version. */
0132: static final long serialVersionUID = -6316591992167219696L;
0133:
0134: // public
0135:
0136: /** Element definition node type. */
0137: public static final short ELEMENT_DEFINITION_NODE = 21;
0138:
0139: //
0140: // Data
0141: //
0142:
0143: // links
0144:
0145: protected NodeImpl ownerNode; // typically the parent but not always!
0146:
0147: // data
0148:
0149: protected short flags;
0150:
0151: protected final static short READONLY = 0x1 << 0;
0152: protected final static short SYNCDATA = 0x1 << 1;
0153: protected final static short SYNCCHILDREN = 0x1 << 2;
0154: protected final static short OWNED = 0x1 << 3;
0155: protected final static short FIRSTCHILD = 0x1 << 4;
0156: protected final static short SPECIFIED = 0x1 << 5;
0157: protected final static short IGNORABLEWS = 0x1 << 6;
0158: protected final static short HASSTRING = 0x1 << 7;
0159: protected final static short NORMALIZED = 0x1 << 8;
0160: protected final static short ID = 0x1 << 9;
0161:
0162: //
0163: // Constructors
0164: //
0165:
0166: /**
0167: * No public constructor; only subclasses of Node should be
0168: * instantiated, and those normally via a Document's factory methods
0169: * <p>
0170: * Every Node knows what Document it belongs to.
0171: */
0172: protected NodeImpl(CoreDocumentImpl ownerDocument) {
0173: // as long as we do not have any owner, ownerNode is our ownerDocument
0174: ownerNode = ownerDocument;
0175: } // <init>(CoreDocumentImpl)
0176:
0177: /** Constructor for serialization. */
0178: public NodeImpl() {
0179: }
0180:
0181: //
0182: // Node methods
0183: //
0184:
0185: /**
0186: * A short integer indicating what type of node this is. The named
0187: * constants for this value are defined in the org.w3c.dom.Node interface.
0188: */
0189: public abstract short getNodeType();
0190:
0191: /**
0192: * the name of this node.
0193: */
0194: public abstract String getNodeName();
0195:
0196: /**
0197: * Returns the node value.
0198: * @throws DOMException(DOMSTRING_SIZE_ERR)
0199: */
0200: public String getNodeValue() throws DOMException {
0201: return null; // overridden in some subclasses
0202: }
0203:
0204: /**
0205: * Sets the node value.
0206: * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
0207: */
0208: public void setNodeValue(String x) throws DOMException {
0209: // Default behavior is to do nothing, overridden in some subclasses
0210: }
0211:
0212: /**
0213: * Adds a child node to the end of the list of children for this node.
0214: * Convenience shorthand for insertBefore(newChild,null).
0215: * @see #insertBefore(Node, Node)
0216: * <P>
0217: * By default we do not accept any children, ParentNode overrides this.
0218: * @see ParentNode
0219: *
0220: * @return newChild, in its new state (relocated, or emptied in the case of
0221: * DocumentNode.)
0222: *
0223: * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
0224: * type that shouldn't be a child of this node.
0225: *
0226: * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
0227: * different owner document than we do.
0228: *
0229: * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0230: * read-only.
0231: */
0232: public Node appendChild(Node newChild) throws DOMException {
0233: return insertBefore(newChild, null);
0234: }
0235:
0236: /**
0237: * Returns a duplicate of a given node. You can consider this a
0238: * generic "copy constructor" for nodes. The newly returned object should
0239: * be completely independent of the source object's subtree, so changes
0240: * in one after the clone has been made will not affect the other.
0241: * <P>
0242: * Note: since we never have any children deep is meaningless here,
0243: * ParentNode overrides this behavior.
0244: * @see ParentNode
0245: *
0246: * <p>
0247: * Example: Cloning a Text node will copy both the node and the text it
0248: * contains.
0249: * <p>
0250: * Example: Cloning something that has children -- Element or Attr, for
0251: * example -- will _not_ clone those children unless a "deep clone"
0252: * has been requested. A shallow clone of an Attr node will yield an
0253: * empty Attr of the same name.
0254: * <p>
0255: * NOTE: Clones will always be read/write, even if the node being cloned
0256: * is read-only, to permit applications using only the DOM API to obtain
0257: * editable copies of locked portions of the tree.
0258: */
0259: public Node cloneNode(boolean deep) {
0260:
0261: if (needsSyncData()) {
0262: synchronizeData();
0263: }
0264:
0265: NodeImpl newnode;
0266: try {
0267: newnode = (NodeImpl) clone();
0268: } catch (CloneNotSupportedException e) {
0269: // if we get here we have an error in our program we may as well
0270: // be vocal about it, so that people can take appropriate action.
0271: throw new RuntimeException("**Internal Error**" + e);
0272: }
0273:
0274: // Need to break the association w/ original kids
0275: newnode.ownerNode = ownerDocument();
0276: newnode.isOwned(false);
0277:
0278: // By default we make all clones readwrite,
0279: // this is overriden in readonly subclasses
0280: newnode.isReadOnly(false);
0281:
0282: ownerDocument().callUserDataHandlers(this , newnode,
0283: UserDataHandler.NODE_CLONED);
0284:
0285: return newnode;
0286:
0287: } // cloneNode(boolean):Node
0288:
0289: /**
0290: * Find the Document that this Node belongs to (the document in
0291: * whose context the Node was created). The Node may or may not
0292: * currently be part of that Document's actual contents.
0293: */
0294: public Document getOwnerDocument() {
0295: // if we have an owner simply forward the request
0296: // otherwise ownerNode is our ownerDocument
0297: if (isOwned()) {
0298: return ownerNode.ownerDocument();
0299: } else {
0300: return (Document) ownerNode;
0301: }
0302: }
0303:
0304: /**
0305: * same as above but returns internal type and this one is not overridden
0306: * by CoreDocumentImpl to return null
0307: */
0308: CoreDocumentImpl ownerDocument() {
0309: // if we have an owner simply forward the request
0310: // otherwise ownerNode is our ownerDocument
0311: if (isOwned()) {
0312: return ownerNode.ownerDocument();
0313: } else {
0314: return (CoreDocumentImpl) ownerNode;
0315: }
0316: }
0317:
0318: /**
0319: * NON-DOM
0320: * set the ownerDocument of this node
0321: */
0322: protected void setOwnerDocument(CoreDocumentImpl doc) {
0323: if (needsSyncData()) {
0324: synchronizeData();
0325: }
0326: // if we have an owner we rely on it to have it right
0327: // otherwise ownerNode is our ownerDocument
0328: if (!isOwned()) {
0329: ownerNode = doc;
0330: }
0331: }
0332:
0333: /**
0334: * Returns the node number
0335: */
0336: protected int getNodeNumber() {
0337: int nodeNumber;
0338: CoreDocumentImpl cd = (CoreDocumentImpl) (this
0339: .getOwnerDocument());
0340: nodeNumber = cd.getNodeNumber(this );
0341: return nodeNumber;
0342: }
0343:
0344: /**
0345: * Obtain the DOM-tree parent of this node, or null if it is not
0346: * currently active in the DOM tree (perhaps because it has just been
0347: * created or removed). Note that Document, DocumentFragment, and
0348: * Attribute will never have parents.
0349: */
0350: public Node getParentNode() {
0351: return null; // overriden by ChildNode
0352: }
0353:
0354: /*
0355: * same as above but returns internal type
0356: */
0357: NodeImpl parentNode() {
0358: return null;
0359: }
0360:
0361: /** The next child of this node's parent, or null if none */
0362: public Node getNextSibling() {
0363: return null; // default behavior, overriden in ChildNode
0364: }
0365:
0366: /** The previous child of this node's parent, or null if none */
0367: public Node getPreviousSibling() {
0368: return null; // default behavior, overriden in ChildNode
0369: }
0370:
0371: ChildNode previousSibling() {
0372: return null; // default behavior, overriden in ChildNode
0373: }
0374:
0375: /**
0376: * Return the collection of attributes associated with this node,
0377: * or null if none. At this writing, Element is the only type of node
0378: * which will ever have attributes.
0379: *
0380: * @see ElementImpl
0381: */
0382: public NamedNodeMap getAttributes() {
0383: return null; // overridden in ElementImpl
0384: }
0385:
0386: /**
0387: * Returns whether this node (if it is an element) has any attributes.
0388: * @return <code>true</code> if this node has any attributes,
0389: * <code>false</code> otherwise.
0390: * @since DOM Level 2
0391: * @see ElementImpl
0392: */
0393: public boolean hasAttributes() {
0394: return false; // overridden in ElementImpl
0395: }
0396:
0397: /**
0398: * Test whether this node has any children. Convenience shorthand
0399: * for (Node.getFirstChild()!=null)
0400: * <P>
0401: * By default we do not have any children, ParentNode overrides this.
0402: * @see ParentNode
0403: */
0404: public boolean hasChildNodes() {
0405: return false;
0406: }
0407:
0408: /**
0409: * Obtain a NodeList enumerating all children of this node. If there
0410: * are none, an (initially) empty NodeList is returned.
0411: * <p>
0412: * NodeLists are "live"; as children are added/removed the NodeList
0413: * will immediately reflect those changes. Also, the NodeList refers
0414: * to the actual nodes, so changes to those nodes made via the DOM tree
0415: * will be reflected in the NodeList and vice versa.
0416: * <p>
0417: * In this implementation, Nodes implement the NodeList interface and
0418: * provide their own getChildNodes() support. Other DOMs may solve this
0419: * differently.
0420: */
0421: public NodeList getChildNodes() {
0422: return this ;
0423: }
0424:
0425: /** The first child of this Node, or null if none.
0426: * <P>
0427: * By default we do not have any children, ParentNode overrides this.
0428: * @see ParentNode
0429: */
0430: public Node getFirstChild() {
0431: return null;
0432: }
0433:
0434: /** The first child of this Node, or null if none.
0435: * <P>
0436: * By default we do not have any children, ParentNode overrides this.
0437: * @see ParentNode
0438: */
0439: public Node getLastChild() {
0440: return null;
0441: }
0442:
0443: /**
0444: * Move one or more node(s) to our list of children. Note that this
0445: * implicitly removes them from their previous parent.
0446: * <P>
0447: * By default we do not accept any children, ParentNode overrides this.
0448: * @see ParentNode
0449: *
0450: * @param newChild The Node to be moved to our subtree. As a
0451: * convenience feature, inserting a DocumentNode will instead insert
0452: * all its children.
0453: *
0454: * @param refChild Current child which newChild should be placed
0455: * immediately before. If refChild is null, the insertion occurs
0456: * after all existing Nodes, like appendChild().
0457: *
0458: * @return newChild, in its new state (relocated, or emptied in the case of
0459: * DocumentNode.)
0460: *
0461: * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
0462: * type that shouldn't be a child of this node, or if newChild is an
0463: * ancestor of this node.
0464: *
0465: * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
0466: * different owner document than we do.
0467: *
0468: * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
0469: * this node.
0470: *
0471: * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0472: * read-only.
0473: */
0474: public Node insertBefore(Node newChild, Node refChild)
0475: throws DOMException {
0476: throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
0477: DOMMessageFormatter.formatMessage(
0478: DOMMessageFormatter.DOM_DOMAIN,
0479: "HIERARCHY_REQUEST_ERR", null));
0480: }
0481:
0482: /**
0483: * Remove a child from this Node. The removed child's subtree
0484: * remains intact so it may be re-inserted elsewhere.
0485: * <P>
0486: * By default we do not have any children, ParentNode overrides this.
0487: * @see ParentNode
0488: *
0489: * @return oldChild, in its new state (removed).
0490: *
0491: * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
0492: * this node.
0493: *
0494: * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0495: * read-only.
0496: */
0497: public Node removeChild(Node oldChild) throws DOMException {
0498: throw new DOMException(DOMException.NOT_FOUND_ERR,
0499: DOMMessageFormatter.formatMessage(
0500: DOMMessageFormatter.DOM_DOMAIN,
0501: "NOT_FOUND_ERR", null));
0502: }
0503:
0504: /**
0505: * Make newChild occupy the location that oldChild used to
0506: * have. Note that newChild will first be removed from its previous
0507: * parent, if any. Equivalent to inserting newChild before oldChild,
0508: * then removing oldChild.
0509: * <P>
0510: * By default we do not have any children, ParentNode overrides this.
0511: * @see ParentNode
0512: *
0513: * @return oldChild, in its new state (removed).
0514: *
0515: * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
0516: * type that shouldn't be a child of this node, or if newChild is
0517: * one of our ancestors.
0518: *
0519: * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
0520: * different owner document than we do.
0521: *
0522: * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
0523: * this node.
0524: *
0525: * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
0526: * read-only.
0527: */
0528: public Node replaceChild(Node newChild, Node oldChild)
0529: throws DOMException {
0530: throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
0531: DOMMessageFormatter.formatMessage(
0532: DOMMessageFormatter.DOM_DOMAIN,
0533: "HIERARCHY_REQUEST_ERR", null));
0534: }
0535:
0536: //
0537: // NodeList methods
0538: //
0539:
0540: /**
0541: * NodeList method: Count the immediate children of this node
0542: * <P>
0543: * By default we do not have any children, ParentNode overrides this.
0544: * @see ParentNode
0545: *
0546: * @return int
0547: */
0548: public int getLength() {
0549: return 0;
0550: }
0551:
0552: /**
0553: * NodeList method: Return the Nth immediate child of this node, or
0554: * null if the index is out of bounds.
0555: * <P>
0556: * By default we do not have any children, ParentNode overrides this.
0557: * @see ParentNode
0558: *
0559: * @return org.w3c.dom.Node
0560: * @param index int
0561: */
0562: public Node item(int index) {
0563: return null;
0564: }
0565:
0566: //
0567: // DOM2: methods, getters, setters
0568: //
0569:
0570: /**
0571: * Puts all <code>Text</code> nodes in the full depth of the sub-tree
0572: * underneath this <code>Node</code>, including attribute nodes, into a
0573: * "normal" form where only markup (e.g., tags, comments, processing
0574: * instructions, CDATA sections, and entity references) separates
0575: * <code>Text</code> nodes, i.e., there are no adjacent <code>Text</code>
0576: * nodes. This can be used to ensure that the DOM view of a document is
0577: * the same as if it were saved and re-loaded, and is useful when
0578: * operations (such as XPointer lookups) that depend on a particular
0579: * document tree structure are to be used.In cases where the document
0580: * contains <code>CDATASections</code>, the normalize operation alone may
0581: * not be sufficient, since XPointers do not differentiate between
0582: * <code>Text</code> nodes and <code>CDATASection</code> nodes.
0583: * <p>
0584: * Note that this implementation simply calls normalize() on this Node's
0585: * children. It is up to implementors or Node to override normalize()
0586: * to take action.
0587: */
0588: public void normalize() {
0589: /* by default we do not have any children,
0590: ParentNode overrides this behavior */
0591: }
0592:
0593: /**
0594: * Introduced in DOM Level 2. <p>
0595: * Tests whether the DOM implementation implements a specific feature and
0596: * that feature is supported by this node.
0597: * @param feature The package name of the feature to test. This is the same
0598: * name as what can be passed to the method hasFeature on
0599: * DOMImplementation.
0600: * @param version This is the version number of the package name to
0601: * test. In Level 2, version 1, this is the string "2.0". If the version is
0602: * not specified, supporting any version of the feature will cause the
0603: * method to return true.
0604: * @return boolean Returns true if this node defines a subtree within which
0605: * the specified feature is supported, false otherwise.
0606: * @since WD-DOM-Level-2-19990923
0607: */
0608: public boolean isSupported(String feature, String version) {
0609: return ownerDocument().getImplementation().hasFeature(feature,
0610: version);
0611: }
0612:
0613: /**
0614: * Introduced in DOM Level 2. <p>
0615: *
0616: * The namespace URI of this node, or null if it is unspecified. When this
0617: * node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE, this is
0618: * always null and setting it has no effect. <p>
0619: *
0620: * This is not a computed value that is the result of a namespace lookup
0621: * based on an examination of the namespace declarations in scope. It is
0622: * merely the namespace URI given at creation time.<p>
0623: *
0624: * For nodes created with a DOM Level 1 method, such as createElement
0625: * from the Document interface, this is null.
0626: * @since WD-DOM-Level-2-19990923
0627: * @see AttrNSImpl
0628: * @see ElementNSImpl
0629: */
0630: public String getNamespaceURI() {
0631: return null;
0632: }
0633:
0634: /**
0635: * Introduced in DOM Level 2. <p>
0636: *
0637: * The namespace prefix of this node, or null if it is unspecified. When
0638: * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE this
0639: * is always null and setting it has no effect.<p>
0640: *
0641: * For nodes created with a DOM Level 1 method, such as createElement
0642: * from the Document interface, this is null. <p>
0643: *
0644: * @since WD-DOM-Level-2-19990923
0645: * @see AttrNSImpl
0646: * @see ElementNSImpl
0647: */
0648: public String getPrefix() {
0649: return null;
0650: }
0651:
0652: /**
0653: * Introduced in DOM Level 2. <p>
0654: *
0655: * The namespace prefix of this node, or null if it is unspecified. When
0656: * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE
0657: * this is always null and setting it has no effect.<p>
0658: *
0659: * For nodes created with a DOM Level 1 method, such as createElement from
0660: * the Document interface, this is null.<p>
0661: *
0662: * Note that setting this attribute changes the nodeName attribute, which
0663: * holds the qualified name, as well as the tagName and name attributes of
0664: * the Element and Attr interfaces, when applicable.<p>
0665: *
0666: * @throws INVALID_CHARACTER_ERR Raised if the specified
0667: * prefix contains an invalid character.
0668: *
0669: * @since WD-DOM-Level-2-19990923
0670: * @see AttrNSImpl
0671: * @see ElementNSImpl
0672: */
0673: public void setPrefix(String prefix) throws DOMException {
0674: throw new DOMException(DOMException.NAMESPACE_ERR,
0675: DOMMessageFormatter.formatMessage(
0676: DOMMessageFormatter.DOM_DOMAIN,
0677: "NAMESPACE_ERR", null));
0678: }
0679:
0680: /**
0681: * Introduced in DOM Level 2. <p>
0682: *
0683: * Returns the local part of the qualified name of this node.
0684: * For nodes created with a DOM Level 1 method, such as createElement
0685: * from the Document interface, and for nodes of any type other than
0686: * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName
0687: * attribute.
0688: * @since WD-DOM-Level-2-19990923
0689: * @see AttrNSImpl
0690: * @see ElementNSImpl
0691: */
0692: public String getLocalName() {
0693: return null;
0694: }
0695:
0696: //
0697: // EventTarget support
0698: //
0699:
0700: public void addEventListener(String type, EventListener listener,
0701: boolean useCapture) {
0702: // simply forward to Document
0703: ownerDocument().addEventListener(this , type, listener,
0704: useCapture);
0705: }
0706:
0707: public void removeEventListener(String type,
0708: EventListener listener, boolean useCapture) {
0709: // simply forward to Document
0710: ownerDocument().removeEventListener(this , type, listener,
0711: useCapture);
0712: }
0713:
0714: public boolean dispatchEvent(Event event) {
0715: // simply forward to Document
0716: return ownerDocument().dispatchEvent(this , event);
0717: }
0718:
0719: //
0720: // Public DOM Level 3 methods
0721: //
0722:
0723: /**
0724: * The absolute base URI of this node or <code>null</code> if undefined.
0725: * This value is computed according to . However, when the
0726: * <code>Document</code> supports the feature "HTML" , the base URI is
0727: * computed using first the value of the href attribute of the HTML BASE
0728: * element if any, and the value of the <code>documentURI</code>
0729: * attribute from the <code>Document</code> interface otherwise.
0730: * <br> When the node is an <code>Element</code>, a <code>Document</code>
0731: * or a a <code>ProcessingInstruction</code>, this attribute represents
0732: * the properties [base URI] defined in . When the node is a
0733: * <code>Notation</code>, an <code>Entity</code>, or an
0734: * <code>EntityReference</code>, this attribute represents the
0735: * properties [declaration base URI] in the . How will this be affected
0736: * by resolution of relative namespace URIs issue?It's not.Should this
0737: * only be on Document, Element, ProcessingInstruction, Entity, and
0738: * Notation nodes, according to the infoset? If not, what is it equal to
0739: * on other nodes? Null? An empty string? I think it should be the
0740: * parent's.No.Should this be read-only and computed or and actual
0741: * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and
0742: * teleconference 30 May 2001).If the base HTML element is not yet
0743: * attached to a document, does the insert change the Document.baseURI?
0744: * Yes. (F2F 26 Sep 2001)
0745: * @since DOM Level 3
0746: */
0747: public String getBaseURI() {
0748: return null;
0749: }
0750:
0751: /**
0752: * Compares a node with this node with regard to their position in the
0753: * tree and according to the document order. This order can be extended
0754: * by module that define additional types of nodes.
0755: * @param other The node to compare against this node.
0756: * @return Returns how the given node is positioned relatively to this
0757: * node.
0758: * @since DOM Level 3
0759: * @deprecated
0760: */
0761: public short compareTreePosition(Node other) {
0762: // Questions of clarification for this method - to be answered by the
0763: // DOM WG. Current assumptions listed - LM
0764: //
0765: // 1. How do ENTITY nodes compare?
0766: // Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
0767: // aren't really 'in the tree'
0768: //
0769: // 2. How do NOTATION nodes compare?
0770: // Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
0771: // aren't really 'in the tree'
0772: //
0773: // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
0774: // only relevant for nodes that are "part of the document tree"?
0775: // <outer>
0776: // <inner myattr="true"/>
0777: // </outer>
0778: // Is the element node "outer" considered an ancestor of "myattr"?
0779: // Current assumption: No.
0780: //
0781: // 4. How do children of ATTRIBUTE nodes compare (with eachother, or
0782: // with children of other attribute nodes with the same element)
0783: // Current assumption: Children of ATTRIBUTE nodes are treated as if
0784: // they they are the attribute node itself, unless the 2 nodes
0785: // are both children of the same attribute.
0786: //
0787: // 5. How does an ENTITY_REFERENCE node compare with it's children?
0788: // Given the DOM, it should precede its children as an ancestor.
0789: // Given "document order", does it represent the same position?
0790: // Current assumption: An ENTITY_REFERENCE node is an ancestor of its
0791: // children.
0792: //
0793: // 6. How do children of a DocumentFragment compare?
0794: // Current assumption: If both nodes are part of the same document
0795: // fragment, there are compared as if they were part of a document.
0796:
0797: // If the nodes are the same...
0798: if (this == other)
0799: return (TREE_POSITION_SAME_NODE | TREE_POSITION_EQUIVALENT);
0800:
0801: // If either node is of type ENTITY or NOTATION, compare as disconnected
0802: short this Type = this .getNodeType();
0803: short otherType = other.getNodeType();
0804:
0805: // If either node is of type ENTITY or NOTATION, compare as disconnected
0806: if (this Type == Node.ENTITY_NODE
0807: || this Type == Node.NOTATION_NODE
0808: || otherType == Node.ENTITY_NODE
0809: || otherType == Node.NOTATION_NODE) {
0810: return TREE_POSITION_DISCONNECTED;
0811: }
0812:
0813: // Find the ancestor of each node, and the distance each node is from
0814: // its ancestor.
0815: // During this traversal, look for ancestor/descendent relationships
0816: // between the 2 nodes in question.
0817: // We do this now, so that we get this info correct for attribute nodes
0818: // and their children.
0819:
0820: Node node;
0821: Node this Ancestor = this ;
0822: Node otherAncestor = other;
0823: int this Depth = 0;
0824: int otherDepth = 0;
0825: for (node = this ; node != null; node = node.getParentNode()) {
0826: this Depth += 1;
0827: if (node == other)
0828: // The other node is an ancestor of this one.
0829: return (TREE_POSITION_ANCESTOR | TREE_POSITION_PRECEDING);
0830: this Ancestor = node;
0831: }
0832:
0833: for (node = other; node != null; node = node.getParentNode()) {
0834: otherDepth += 1;
0835: if (node == this )
0836: // The other node is a descendent of the reference node.
0837: return (TREE_POSITION_DESCENDANT | TREE_POSITION_FOLLOWING);
0838: otherAncestor = node;
0839: }
0840:
0841: Node this Node = this ;
0842: Node otherNode = other;
0843:
0844: int this AncestorType = this Ancestor.getNodeType();
0845: int otherAncestorType = otherAncestor.getNodeType();
0846:
0847: // if the ancestor is an attribute, get owning element.
0848: // we are now interested in the owner to determine position.
0849:
0850: if (this AncestorType == Node.ATTRIBUTE_NODE) {
0851: this Node = ((AttrImpl) this Ancestor).getOwnerElement();
0852: }
0853: if (otherAncestorType == Node.ATTRIBUTE_NODE) {
0854: otherNode = ((AttrImpl) otherAncestor).getOwnerElement();
0855: }
0856:
0857: // Before proceeding, we should check if both ancestor nodes turned
0858: // out to be attributes for the same element
0859: if (this AncestorType == Node.ATTRIBUTE_NODE
0860: && otherAncestorType == Node.ATTRIBUTE_NODE
0861: && this Node == otherNode)
0862: return TREE_POSITION_EQUIVALENT;
0863:
0864: // Now, find the ancestor of the owning element, if the original
0865: // ancestor was an attribute
0866:
0867: // Note: the following 2 loops are quite close to the ones above.
0868: // May want to common them up. LM.
0869: if (this AncestorType == Node.ATTRIBUTE_NODE) {
0870: this Depth = 0;
0871: for (node = this Node; node != null; node = node
0872: .getParentNode()) {
0873: this Depth += 1;
0874: if (node == otherNode)
0875: // The other node is an ancestor of the owning element
0876: {
0877: return TREE_POSITION_PRECEDING;
0878: }
0879: this Ancestor = node;
0880: }
0881: }
0882:
0883: // Now, find the ancestor of the owning element, if the original
0884: // ancestor was an attribute
0885: if (otherAncestorType == Node.ATTRIBUTE_NODE) {
0886: otherDepth = 0;
0887: for (node = otherNode; node != null; node = node
0888: .getParentNode()) {
0889: otherDepth += 1;
0890: if (node == this Node)
0891: // The other node is a descendent of the reference
0892: // node's element
0893: return TREE_POSITION_FOLLOWING;
0894: otherAncestor = node;
0895: }
0896: }
0897:
0898: // thisAncestor and otherAncestor must be the same at this point,
0899: // otherwise, we are not in the same tree or document fragment
0900: if (this Ancestor != otherAncestor)
0901: return TREE_POSITION_DISCONNECTED;
0902:
0903: // Go up the parent chain of the deeper node, until we find a node
0904: // with the same depth as the shallower node
0905:
0906: if (this Depth > otherDepth) {
0907: for (int i = 0; i < this Depth - otherDepth; i++)
0908: this Node = this Node.getParentNode();
0909: // Check if the node we have reached is in fact "otherNode". This can
0910: // happen in the case of attributes. In this case, otherNode
0911: // "precedes" this.
0912: if (this Node == otherNode)
0913: return TREE_POSITION_PRECEDING;
0914: }
0915:
0916: else {
0917: for (int i = 0; i < otherDepth - this Depth; i++)
0918: otherNode = otherNode.getParentNode();
0919: // Check if the node we have reached is in fact "thisNode". This can
0920: // happen in the case of attributes. In this case, otherNode
0921: // "follows" this.
0922: if (otherNode == this Node)
0923: return TREE_POSITION_FOLLOWING;
0924: }
0925:
0926: // We now have nodes at the same depth in the tree. Find a common
0927: // ancestor.
0928: Node this NodeP, otherNodeP;
0929: for (this NodeP = this Node.getParentNode(), otherNodeP = otherNode
0930: .getParentNode(); this NodeP != otherNodeP;) {
0931: this Node = this NodeP;
0932: otherNode = otherNodeP;
0933: this NodeP = this NodeP.getParentNode();
0934: otherNodeP = otherNodeP.getParentNode();
0935: }
0936:
0937: // At this point, thisNode and otherNode are direct children of
0938: // the common ancestor.
0939: // See whether thisNode or otherNode is the leftmost
0940:
0941: for (Node current = this NodeP.getFirstChild(); current != null; current = current
0942: .getNextSibling()) {
0943: if (current == otherNode) {
0944: return TREE_POSITION_PRECEDING;
0945: } else if (current == this Node) {
0946: return TREE_POSITION_FOLLOWING;
0947: }
0948: }
0949: // REVISIT: shouldn't get here. Should probably throw an
0950: // exception
0951: return 0;
0952:
0953: }
0954:
0955: /**
0956: * Compares a node with this node with regard to their position in the
0957: * document.
0958: * @param other The node to compare against this node.
0959: * @return Returns how the given node is positioned relatively to this
0960: * node.
0961: * @since DOM Level 3
0962: */
0963: public short compareDocumentPosition(Node other)
0964: throws DOMException {
0965:
0966: // If the nodes are the same, no flags should be set
0967: if (this == other)
0968: return 0;
0969:
0970: // check if other is from a different implementation
0971: if (other != null && !(other instanceof NodeImpl)) {
0972: // other comes from a different implementation
0973: String msg = DOMMessageFormatter.formatMessage(
0974: DOMMessageFormatter.DOM_DOMAIN,
0975: "NOT_SUPPORTED_ERR", null);
0976: throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
0977: }
0978:
0979: Document this OwnerDoc, otherOwnerDoc;
0980: // get the respective Document owners.
0981: if (this .getNodeType() == Node.DOCUMENT_NODE)
0982: this OwnerDoc = (Document) this ;
0983: else
0984: this OwnerDoc = this .getOwnerDocument();
0985: if (other.getNodeType() == Node.DOCUMENT_NODE)
0986: otherOwnerDoc = (Document) other;
0987: else
0988: otherOwnerDoc = other.getOwnerDocument();
0989:
0990: // If from different documents, we know they are disconnected.
0991: // and have an implementation dependent order
0992: if (this OwnerDoc != otherOwnerDoc && this OwnerDoc != null
0993: && otherOwnerDoc != null) {
0994: int otherDocNum = ((CoreDocumentImpl) otherOwnerDoc)
0995: .getNodeNumber();
0996: int this DocNum = ((CoreDocumentImpl) this OwnerDoc)
0997: .getNodeNumber();
0998: if (otherDocNum > this DocNum)
0999: return DOCUMENT_POSITION_DISCONNECTED
1000: | DOCUMENT_POSITION_FOLLOWING
1001: | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1002: else
1003: return DOCUMENT_POSITION_DISCONNECTED
1004: | DOCUMENT_POSITION_PRECEDING
1005: | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1006:
1007: }
1008:
1009: // Find the ancestor of each node, and the distance each node is from
1010: // its ancestor.
1011: // During this traversal, look for ancestor/descendent relationships
1012: // between the 2 nodes in question.
1013: // We do this now, so that we get this info correct for attribute nodes
1014: // and their children.
1015:
1016: Node node;
1017: Node this Ancestor = this ;
1018: Node otherAncestor = other;
1019:
1020: int this Depth = 0;
1021: int otherDepth = 0;
1022: for (node = this ; node != null; node = node.getParentNode()) {
1023: this Depth += 1;
1024: if (node == other)
1025: // The other node is an ancestor of this one.
1026: return (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
1027: this Ancestor = node;
1028: }
1029:
1030: for (node = other; node != null; node = node.getParentNode()) {
1031: otherDepth += 1;
1032: if (node == this )
1033: // The other node is a descendent of the reference node.
1034: return (DOCUMENT_POSITION_IS_CONTAINED | DOCUMENT_POSITION_FOLLOWING);
1035: otherAncestor = node;
1036: }
1037:
1038: int this AncestorType = this Ancestor.getNodeType();
1039: int otherAncestorType = otherAncestor.getNodeType();
1040: Node this Node = this ;
1041: Node otherNode = other;
1042:
1043: // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
1044: // LM: should rewrite this.
1045: switch (this AncestorType) {
1046: case Node.NOTATION_NODE:
1047: case Node.ENTITY_NODE: {
1048: DocumentType container = this OwnerDoc.getDoctype();
1049: if (container == otherAncestor)
1050: return (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
1051: switch (otherAncestorType) {
1052: case Node.NOTATION_NODE:
1053: case Node.ENTITY_NODE: {
1054: if (this AncestorType != otherAncestorType)
1055: // the nodes are of different types
1056: return ((this AncestorType > otherAncestorType) ? DOCUMENT_POSITION_PRECEDING
1057: : DOCUMENT_POSITION_FOLLOWING);
1058: else {
1059: // the nodes are of the same type. Find order.
1060: if (this AncestorType == Node.NOTATION_NODE)
1061:
1062: if (((NamedNodeMapImpl) container
1063: .getNotations()).precedes(
1064: otherAncestor, this Ancestor))
1065: return (DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1066: else
1067: return (DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1068: else if (((NamedNodeMapImpl) container
1069: .getEntities()).precedes(otherAncestor,
1070: this Ancestor))
1071: return (DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1072: else
1073: return (DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1074: }
1075: }
1076: }
1077: this Node = this Ancestor = this OwnerDoc;
1078: break;
1079: }
1080: case Node.DOCUMENT_TYPE_NODE: {
1081: if (otherNode == this OwnerDoc)
1082: return (DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS);
1083: else if (this OwnerDoc != null
1084: && this OwnerDoc == otherOwnerDoc)
1085: return (DOCUMENT_POSITION_FOLLOWING);
1086: break;
1087: }
1088: case Node.ATTRIBUTE_NODE: {
1089: this Node = ((AttrImpl) this Ancestor).getOwnerElement();
1090: if (otherAncestorType == Node.ATTRIBUTE_NODE) {
1091: otherNode = ((AttrImpl) otherAncestor)
1092: .getOwnerElement();
1093: if (otherNode == this Node) {
1094: if (((NamedNodeMapImpl) this Node.getAttributes())
1095: .precedes(other, this ))
1096: return (DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1097: else
1098: return (DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1099: }
1100: }
1101:
1102: // Now, find the ancestor of the element
1103: this Depth = 0;
1104: for (node = this Node; node != null; node = node
1105: .getParentNode()) {
1106: this Depth += 1;
1107: if (node == otherNode) {
1108: // The other node is an ancestor of the owning element
1109: return (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
1110: }
1111: this Ancestor = node;
1112: }
1113: }
1114: }
1115: switch (otherAncestorType) {
1116: case Node.NOTATION_NODE:
1117: case Node.ENTITY_NODE: {
1118: DocumentType container = this OwnerDoc.getDoctype();
1119: if (container == this )
1120: return (DOCUMENT_POSITION_IS_CONTAINED | DOCUMENT_POSITION_FOLLOWING);
1121: otherNode = otherAncestor = this OwnerDoc;
1122: break;
1123: }
1124: case Node.DOCUMENT_TYPE_NODE: {
1125: if (this Node == otherOwnerDoc)
1126: return (DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_IS_CONTAINED);
1127: else if (otherOwnerDoc != null
1128: && this OwnerDoc == otherOwnerDoc)
1129: return (DOCUMENT_POSITION_PRECEDING);
1130: break;
1131: }
1132: case Node.ATTRIBUTE_NODE: {
1133: otherDepth = 0;
1134: otherNode = ((AttrImpl) otherAncestor).getOwnerElement();
1135: for (node = otherNode; node != null; node = node
1136: .getParentNode()) {
1137: otherDepth += 1;
1138: if (node == this Node)
1139: // The other node is a descendent of the reference
1140: // node's element
1141: return DOCUMENT_POSITION_FOLLOWING
1142: | DOCUMENT_POSITION_IS_CONTAINED;
1143: otherAncestor = node;
1144: }
1145:
1146: }
1147: }
1148:
1149: // thisAncestor and otherAncestor must be the same at this point,
1150: // otherwise, the original nodes are disconnected
1151: if (this Ancestor != otherAncestor) {
1152: int this AncestorNum, otherAncestorNum;
1153: this AncestorNum = ((NodeImpl) this Ancestor).getNodeNumber();
1154: otherAncestorNum = ((NodeImpl) otherAncestor)
1155: .getNodeNumber();
1156:
1157: if (this AncestorNum > otherAncestorNum)
1158: return DOCUMENT_POSITION_DISCONNECTED
1159: | DOCUMENT_POSITION_FOLLOWING
1160: | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1161: else
1162: return DOCUMENT_POSITION_DISCONNECTED
1163: | DOCUMENT_POSITION_PRECEDING
1164: | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1165: }
1166:
1167: // Go up the parent chain of the deeper node, until we find a node
1168: // with the same depth as the shallower node
1169:
1170: if (this Depth > otherDepth) {
1171: for (int i = 0; i < this Depth - otherDepth; i++)
1172: this Node = this Node.getParentNode();
1173: // Check if the node we have reached is in fact "otherNode". This can
1174: // happen in the case of attributes. In this case, otherNode
1175: // "precedes" this.
1176: if (this Node == otherNode) {
1177: return DOCUMENT_POSITION_PRECEDING;
1178: }
1179: }
1180:
1181: else {
1182: for (int i = 0; i < otherDepth - this Depth; i++)
1183: otherNode = otherNode.getParentNode();
1184: // Check if the node we have reached is in fact "thisNode". This can
1185: // happen in the case of attributes. In this case, otherNode
1186: // "follows" this.
1187: if (otherNode == this Node)
1188: return DOCUMENT_POSITION_FOLLOWING;
1189: }
1190:
1191: // We now have nodes at the same depth in the tree. Find a common
1192: // ancestor.
1193: Node this NodeP, otherNodeP;
1194: for (this NodeP = this Node.getParentNode(), otherNodeP = otherNode
1195: .getParentNode(); this NodeP != otherNodeP;) {
1196: this Node = this NodeP;
1197: otherNode = otherNodeP;
1198: this NodeP = this NodeP.getParentNode();
1199: otherNodeP = otherNodeP.getParentNode();
1200: }
1201:
1202: // At this point, thisNode and otherNode are direct children of
1203: // the common ancestor.
1204: // See whether thisNode or otherNode is the leftmost
1205:
1206: for (Node current = this NodeP.getFirstChild(); current != null; current = current
1207: .getNextSibling()) {
1208: if (current == otherNode) {
1209: return DOCUMENT_POSITION_PRECEDING;
1210: } else if (current == this Node) {
1211: return DOCUMENT_POSITION_FOLLOWING;
1212: }
1213: }
1214: // REVISIT: shouldn't get here. Should probably throw an
1215: // exception
1216: return 0;
1217:
1218: }
1219:
1220: /**
1221: * This attribute returns the text content of this node and its
1222: * descendants. When it is defined to be null, setting it has no effect.
1223: * When set, any possible children this node may have are removed and
1224: * replaced by a single <code>Text</code> node containing the string
1225: * this attribute is set to. On getting, no serialization is performed,
1226: * the returned string does not contain any markup. No whitespace
1227: * normalization is performed, the returned string does not contain the
1228: * element content whitespaces . Similarly, on setting, no parsing is
1229: * performed either, the input string is taken as pure textual content.
1230: * <br>The string returned is made of the text content of this node
1231: * depending on its type, as defined below:
1232: * <table border='1'>
1233: * <tr>
1234: * <th>Node type</th>
1235: * <th>Content</th>
1236: * </tr>
1237:
1238: /**
1239: * This attribute returns the text content of this node and its
1240: * descendants. When it is defined to be null, setting it has no effect.
1241: * When set, any possible children this node may have are removed and
1242: * replaced by a single <code>Text</code> node containing the string
1243: * this attribute is set to. On getting, no serialization is performed,
1244: * the returned string does not contain any markup. No whitespace
1245: * normalization is performed, the returned string does not contain the
1246: * element content whitespaces . Similarly, on setting, no parsing is
1247: * performed either, the input string is taken as pure textual content.
1248: * <br>The string returned is made of the text content of this node
1249: * depending on its type, as defined below:
1250: * <table border='1'>
1251: * <tr>
1252: * <th>Node type</th>
1253: * <th>Content</th>
1254: * </tr>
1255: * <tr>
1256: * <td valign='top' rowspan='1' colspan='1'>
1257: * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
1258: * DOCUMENT_FRAGMENT_NODE</td>
1259: * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
1260: * attribute value of every child node, excluding COMMENT_NODE and
1261: * PROCESSING_INSTRUCTION_NODE nodes</td>
1262: * </tr>
1263: * <tr>
1264: * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
1265: * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
1266: * <td valign='top' rowspan='1' colspan='1'>
1267: * <code>nodeValue</code></td>
1268: * </tr>
1269: * <tr>
1270: * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
1271: * <td valign='top' rowspan='1' colspan='1'>
1272: * null</td>
1273: * </tr>
1274: * </table>
1275: * @exception DOMException
1276: * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1277: * @exception DOMException
1278: * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
1279: * fit in a <code>DOMString</code> variable on the implementation
1280: * platform.
1281: * @since DOM Level 3
1282: */
1283: public String getTextContent() throws DOMException {
1284: return getNodeValue(); // overriden in some subclasses
1285: }
1286:
1287: // internal method taking a StringBuffer in parameter
1288: void getTextContent(StringBuffer buf) throws DOMException {
1289: String content = getNodeValue();
1290: if (content != null) {
1291: buf.append(content);
1292: }
1293: }
1294:
1295: /**
1296: * This attribute returns the text content of this node and its
1297: * descendants. When it is defined to be null, setting it has no effect.
1298: * When set, any possible children this node may have are removed and
1299: * replaced by a single <code>Text</code> node containing the string
1300: * this attribute is set to. On getting, no serialization is performed,
1301: * the returned string does not contain any markup. No whitespace
1302: * normalization is performed, the returned string does not contain the
1303: * element content whitespaces . Similarly, on setting, no parsing is
1304: * performed either, the input string is taken as pure textual content.
1305: * <br>The string returned is made of the text content of this node
1306: * depending on its type, as defined below:
1307: * <table border='1'>
1308: * <tr>
1309: * <th>Node type</th>
1310: * <th>Content</th>
1311: * </tr>
1312: * <tr>
1313: * <td valign='top' rowspan='1' colspan='1'>
1314: * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
1315: * DOCUMENT_FRAGMENT_NODE</td>
1316: * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
1317: * attribute value of every child node, excluding COMMENT_NODE and
1318: * PROCESSING_INSTRUCTION_NODE nodes</td>
1319: * </tr>
1320: * <tr>
1321: * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
1322: * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
1323: * <td valign='top' rowspan='1' colspan='1'>
1324: * <code>nodeValue</code></td>
1325: * </tr>
1326: * <tr>
1327: * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
1328: * <td valign='top' rowspan='1' colspan='1'>
1329: * null</td>
1330: * </tr>
1331: * </table>
1332: * @exception DOMException
1333: * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1334: * @exception DOMException
1335: * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
1336: * fit in a <code>DOMString</code> variable on the implementation
1337: * platform.
1338: * @since DOM Level 3
1339: */
1340: public void setTextContent(String textContent) throws DOMException {
1341: setNodeValue(textContent);
1342: }
1343:
1344: /**
1345: * Returns whether this node is the same node as the given one.
1346: * <br>This method provides a way to determine whether two
1347: * <code>Node</code> references returned by the implementation reference
1348: * the same object. When two <code>Node</code> references are references
1349: * to the same object, even if through a proxy, the references may be
1350: * used completely interchangably, such that all attributes have the
1351: * same values and calling the same DOM method on either reference
1352: * always has exactly the same effect.
1353: * @param other The node to test against.
1354: * @return Returns <code>true</code> if the nodes are the same,
1355: * <code>false</code> otherwise.
1356: * @since DOM Level 3
1357: */
1358: public boolean isSameNode(Node other) {
1359: // we do not use any wrapper so the answer is obvious
1360: return this == other;
1361: }
1362:
1363: /**
1364: * DOM Level 3: Experimental
1365: * This method checks if the specified <code>namespaceURI</code> is the
1366: * default namespace or not.
1367: * @param namespaceURI The namespace URI to look for.
1368: * @return <code>true</code> if the specified <code>namespaceURI</code>
1369: * is the default namespace, <code>false</code> otherwise.
1370: * @since DOM Level 3
1371: */
1372: public boolean isDefaultNamespace(String namespaceURI) {
1373: // REVISIT: remove casts when DOM L3 becomes REC.
1374: short type = this .getNodeType();
1375: switch (type) {
1376: case Node.ELEMENT_NODE: {
1377: String namespace = this .getNamespaceURI();
1378: String prefix = this .getPrefix();
1379:
1380: // REVISIT: is it possible that prefix is empty string?
1381: if (prefix == null || prefix.length() == 0) {
1382: if (namespaceURI == null) {
1383: return (namespace == namespaceURI);
1384: }
1385: return namespaceURI.equals(namespace);
1386: }
1387: if (this .hasAttributes()) {
1388: ElementImpl elem = (ElementImpl) this ;
1389: NodeImpl attr = (NodeImpl) elem.getAttributeNodeNS(
1390: "http://www.w3.org/2000/xmlns/", "xmlns");
1391: if (attr != null) {
1392: String value = attr.getNodeValue();
1393: if (namespaceURI == null) {
1394: return (namespace == value);
1395: }
1396: return namespaceURI.equals(value);
1397: }
1398: }
1399:
1400: NodeImpl ancestor = (NodeImpl) getElementAncestor(this );
1401: if (ancestor != null) {
1402: return ancestor.isDefaultNamespace(namespaceURI);
1403: }
1404: return false;
1405: }
1406: case Node.DOCUMENT_NODE: {
1407: return ((NodeImpl) ((Document) this ).getDocumentElement())
1408: .isDefaultNamespace(namespaceURI);
1409: }
1410:
1411: case Node.ENTITY_NODE:
1412: case Node.NOTATION_NODE:
1413: case Node.DOCUMENT_FRAGMENT_NODE:
1414: case Node.DOCUMENT_TYPE_NODE:
1415: // type is unknown
1416: return false;
1417: case Node.ATTRIBUTE_NODE: {
1418: if (this .ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1419: return ownerNode.isDefaultNamespace(namespaceURI);
1420:
1421: }
1422: return false;
1423: }
1424: default: {
1425: NodeImpl ancestor = (NodeImpl) getElementAncestor(this );
1426: if (ancestor != null) {
1427: return ancestor.isDefaultNamespace(namespaceURI);
1428: }
1429: return false;
1430: }
1431:
1432: }
1433:
1434: }
1435:
1436: /**
1437: *
1438: * DOM Level 3 - Experimental:
1439: * Look up the prefix associated to the given namespace URI, starting from this node.
1440: *
1441: * @param namespaceURI
1442: * @return the prefix for the namespace
1443: */
1444: public String lookupPrefix(String namespaceURI) {
1445:
1446: // REVISIT: When Namespaces 1.1 comes out this may not be true
1447: // Prefix can't be bound to null namespace
1448: if (namespaceURI == null) {
1449: return null;
1450: }
1451:
1452: short type = this .getNodeType();
1453:
1454: switch (type) {
1455: case Node.ELEMENT_NODE: {
1456: this .getNamespaceURI(); // to flip out children
1457: return lookupNamespacePrefix(namespaceURI,
1458: (ElementImpl) this );
1459: }
1460: case Node.DOCUMENT_NODE: {
1461: return ((NodeImpl) ((Document) this ).getDocumentElement())
1462: .lookupPrefix(namespaceURI);
1463: }
1464:
1465: case Node.ENTITY_NODE:
1466: case Node.NOTATION_NODE:
1467: case Node.DOCUMENT_FRAGMENT_NODE:
1468: case Node.DOCUMENT_TYPE_NODE:
1469: // type is unknown
1470: return null;
1471: case Node.ATTRIBUTE_NODE: {
1472: if (this .ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1473: return ownerNode.lookupPrefix(namespaceURI);
1474:
1475: }
1476: return null;
1477: }
1478: default: {
1479: NodeImpl ancestor = (NodeImpl) getElementAncestor(this );
1480: if (ancestor != null) {
1481: return ancestor.lookupPrefix(namespaceURI);
1482: }
1483: return null;
1484: }
1485:
1486: }
1487: }
1488:
1489: /**
1490: * DOM Level 3 - Experimental:
1491: * Look up the namespace URI associated to the given prefix, starting from this node.
1492: * Use lookupNamespaceURI(null) to lookup the default namespace
1493: *
1494: * @param specifiedPrefix
1495: * @return the URI for the namespace
1496: * @since DOM Level 3
1497: */
1498: public String lookupNamespaceURI(String specifiedPrefix) {
1499: short type = this .getNodeType();
1500: switch (type) {
1501: case Node.ELEMENT_NODE: {
1502:
1503: String namespace = this .getNamespaceURI();
1504: String prefix = this .getPrefix();
1505: if (namespace != null) {
1506: // REVISIT: is it possible that prefix is empty string?
1507: if (specifiedPrefix == null
1508: && prefix == specifiedPrefix) {
1509: // looking for default namespace
1510: return namespace;
1511: } else if (prefix != null
1512: && prefix.equals(specifiedPrefix)) {
1513: // non default namespace
1514: return namespace;
1515: }
1516: }
1517: if (this .hasAttributes()) {
1518: NamedNodeMap map = this .getAttributes();
1519: int length = map.getLength();
1520: for (int i = 0; i < length; i++) {
1521: Node attr = map.item(i);
1522: String attrPrefix = attr.getPrefix();
1523: String value = attr.getNodeValue();
1524: namespace = attr.getNamespaceURI();
1525: if (namespace != null
1526: && namespace
1527: .equals("http://www.w3.org/2000/xmlns/")) {
1528: // at this point we are dealing with DOM Level 2 nodes only
1529: if (specifiedPrefix == null
1530: && attr.getNodeName().equals("xmlns")) {
1531: // default namespace
1532: return value;
1533: } else if (attrPrefix != null
1534: && attrPrefix.equals("xmlns")
1535: && attr.getLocalName().equals(
1536: specifiedPrefix)) {
1537: // non default namespace
1538: return value;
1539: }
1540: }
1541: }
1542: }
1543: NodeImpl ancestor = (NodeImpl) getElementAncestor(this );
1544: if (ancestor != null) {
1545: return ancestor.lookupNamespaceURI(specifiedPrefix);
1546: }
1547:
1548: return null;
1549:
1550: }
1551: case Node.DOCUMENT_NODE: {
1552: return ((NodeImpl) ((Document) this ).getDocumentElement())
1553: .lookupNamespaceURI(specifiedPrefix);
1554: }
1555: case Node.ENTITY_NODE:
1556: case Node.NOTATION_NODE:
1557: case Node.DOCUMENT_FRAGMENT_NODE:
1558: case Node.DOCUMENT_TYPE_NODE:
1559: // type is unknown
1560: return null;
1561: case Node.ATTRIBUTE_NODE: {
1562: if (this .ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1563: return ownerNode.lookupNamespaceURI(specifiedPrefix);
1564:
1565: }
1566: return null;
1567: }
1568: default: {
1569: NodeImpl ancestor = (NodeImpl) getElementAncestor(this );
1570: if (ancestor != null) {
1571: return ancestor.lookupNamespaceURI(specifiedPrefix);
1572: }
1573: return null;
1574: }
1575:
1576: }
1577: }
1578:
1579: Node getElementAncestor(Node currentNode) {
1580: Node parent = currentNode.getParentNode();
1581: if (parent != null) {
1582: short type = parent.getNodeType();
1583: if (type == Node.ELEMENT_NODE) {
1584: return parent;
1585: }
1586: return getElementAncestor(parent);
1587: }
1588: return null;
1589: }
1590:
1591: String lookupNamespacePrefix(String namespaceURI, ElementImpl el) {
1592: String namespace = this .getNamespaceURI();
1593: // REVISIT: if no prefix is available is it null or empty string, or
1594: // could be both?
1595: String prefix = this .getPrefix();
1596:
1597: if (namespace != null && namespace.equals(namespaceURI)) {
1598: if (prefix != null) {
1599: String foundNamespace = el.lookupNamespaceURI(prefix);
1600: if (foundNamespace != null
1601: && foundNamespace.equals(namespaceURI)) {
1602: return prefix;
1603: }
1604:
1605: }
1606: }
1607: if (this .hasAttributes()) {
1608: NamedNodeMap map = this .getAttributes();
1609: int length = map.getLength();
1610: for (int i = 0; i < length; i++) {
1611: Node attr = map.item(i);
1612: String attrPrefix = attr.getPrefix();
1613: String value = attr.getNodeValue();
1614: namespace = attr.getNamespaceURI();
1615: if (namespace != null
1616: && namespace
1617: .equals("http://www.w3.org/2000/xmlns/")) {
1618: // DOM Level 2 nodes
1619: if (((attr.getNodeName().equals("xmlns")) || (attrPrefix != null && attrPrefix
1620: .equals("xmlns"))
1621: && value.equals(namespaceURI))) {
1622:
1623: String localname = attr.getLocalName();
1624: String foundNamespace = el
1625: .lookupNamespaceURI(localname);
1626: if (foundNamespace != null
1627: && foundNamespace.equals(namespaceURI)) {
1628: return localname;
1629: }
1630: }
1631:
1632: }
1633: }
1634: }
1635: NodeImpl ancestor = (NodeImpl) getElementAncestor(this );
1636:
1637: if (ancestor != null) {
1638: return ancestor.lookupNamespacePrefix(namespaceURI, el);
1639: }
1640: return null;
1641: }
1642:
1643: /**
1644: * Tests whether two nodes are equal.
1645: * <br>This method tests for equality of nodes, not sameness (i.e.,
1646: * whether the two nodes are references to the same object) which can be
1647: * tested with <code>Node.isSameNode</code>. All nodes that are the same
1648: * will also be equal, though the reverse may not be true.
1649: * <br>Two nodes are equal if and only if the following conditions are
1650: * satisfied: The two nodes are of the same type.The following string
1651: * attributes are equal: <code>nodeName</code>, <code>localName</code>,
1652: * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code>
1653: * , <code>baseURI</code>. This is: they are both <code>null</code>, or
1654: * they have the same length and are character for character identical.
1655: * The <code>attributes</code> <code>NamedNodeMaps</code> are equal.
1656: * This is: they are both <code>null</code>, or they have the same
1657: * length and for each node that exists in one map there is a node that
1658: * exists in the other map and is equal, although not necessarily at the
1659: * same index.The <code>childNodes</code> <code>NodeLists</code> are
1660: * equal. This is: they are both <code>null</code>, or they have the
1661: * same length and contain equal nodes at the same index. This is true
1662: * for <code>Attr</code> nodes as for any other type of node. Note that
1663: * normalization can affect equality; to avoid this, nodes should be
1664: * normalized before being compared.
1665: * <br>For two <code>DocumentType</code> nodes to be equal, the following
1666: * conditions must also be satisfied: The following string attributes
1667: * are equal: <code>publicId</code>, <code>systemId</code>,
1668: * <code>internalSubset</code>.The <code>entities</code>
1669: * <code>NamedNodeMaps</code> are equal.The <code>notations</code>
1670: * <code>NamedNodeMaps</code> are equal.
1671: * <br>On the other hand, the following do not affect equality: the
1672: * <code>ownerDocument</code> attribute, the <code>specified</code>
1673: * attribute for <code>Attr</code> nodes, the
1674: * <code>isWhitespaceInElementContent</code> attribute for
1675: * <code>Text</code> nodes, as well as any user data or event listeners
1676: * registered on the nodes.
1677: * @param arg The node to compare equality with.
1678: * @return If the nodes, and possibly subtrees are equal,
1679: * <code>true</code> otherwise <code>false</code>.
1680: * @since DOM Level 3
1681: */
1682: public boolean isEqualNode(Node arg) {
1683: if (arg == this ) {
1684: return true;
1685: }
1686: if (arg.getNodeType() != getNodeType()) {
1687: return false;
1688: }
1689: // in theory nodeName can't be null but better be careful
1690: // who knows what other implementations may be doing?...
1691: if (getNodeName() == null) {
1692: if (arg.getNodeName() != null) {
1693: return false;
1694: }
1695: } else if (!getNodeName().equals(arg.getNodeName())) {
1696: return false;
1697: }
1698:
1699: if (getLocalName() == null) {
1700: if (arg.getLocalName() != null) {
1701: return false;
1702: }
1703: } else if (!getLocalName().equals(arg.getLocalName())) {
1704: return false;
1705: }
1706:
1707: if (getNamespaceURI() == null) {
1708: if (arg.getNamespaceURI() != null) {
1709: return false;
1710: }
1711: } else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
1712: return false;
1713: }
1714:
1715: if (getPrefix() == null) {
1716: if (arg.getPrefix() != null) {
1717: return false;
1718: }
1719: } else if (!getPrefix().equals(arg.getPrefix())) {
1720: return false;
1721: }
1722:
1723: if (getNodeValue() == null) {
1724: if (arg.getNodeValue() != null) {
1725: return false;
1726: }
1727: } else if (!getNodeValue().equals(arg.getNodeValue())) {
1728: return false;
1729: }
1730:
1731: return true;
1732: }
1733:
1734: /**
1735: * @since DOM Level 3
1736: */
1737: public Object getFeature(String feature, String version) {
1738: // we don't have any alternate node, either this node does the job
1739: // or we don't have anything that does
1740: return isSupported(feature, version) ? this : null;
1741: }
1742:
1743: /**
1744: * Associate an object to a key on this node. The object can later be
1745: * retrieved from this node by calling <code>getUserData</code> with the
1746: * same key.
1747: * @param key The key to associate the object to.
1748: * @param data The object to associate to the given key, or
1749: * <code>null</code> to remove any existing association to that key.
1750: * @param handler The handler to associate to that key, or
1751: * <code>null</code>.
1752: * @return Returns the <code>DOMObject</code> previously associated to
1753: * the given key on this node, or <code>null</code> if there was none.
1754: * @since DOM Level 3
1755: */
1756: public Object setUserData(String key, Object data,
1757: UserDataHandler handler) {
1758: return ownerDocument().setUserData(this , key, data, handler);
1759: }
1760:
1761: /**
1762: * Retrieves the object associated to a key on a this node. The object
1763: * must first have been set to this node by calling
1764: * <code>setUserData</code> with the same key.
1765: * @param key The key the object is associated to.
1766: * @return Returns the <code>DOMObject</code> associated to the given key
1767: * on this node, or <code>null</code> if there was none.
1768: * @since DOM Level 3
1769: */
1770: public Object getUserData(String key) {
1771: return ownerDocument().getUserData(this , key);
1772: }
1773:
1774: protected Hashtable getUserDataRecord() {
1775: return ownerDocument().getUserDataRecord(this );
1776: }
1777:
1778: //
1779: // Public methods
1780: //
1781:
1782: /**
1783: * NON-DOM: PR-DOM-Level-1-19980818 mentions readonly nodes in conjunction
1784: * with Entities, but provides no API to support this.
1785: * <P>
1786: * Most DOM users should not touch this method. Its anticpated use
1787: * is during construction of EntityRefernces, where it will be used to
1788: * lock the contents replicated from Entity so they can't be casually
1789: * altered. It _could_ be published as a DOM extension, if desired.
1790: * <P>
1791: * Note: since we never have any children deep is meaningless here,
1792: * ParentNode overrides this behavior.
1793: * @see ParentNode
1794: *
1795: * @param readOnly True or false as desired.
1796: * @param deep If true, children are also toggled. Note that this will
1797: * not change the state of an EntityReference or its children,
1798: * which are always read-only.
1799: */
1800: public void setReadOnly(boolean readOnly, boolean deep) {
1801:
1802: if (needsSyncData()) {
1803: synchronizeData();
1804: }
1805: isReadOnly(readOnly);
1806:
1807: } // setReadOnly(boolean,boolean)
1808:
1809: /**
1810: * NON-DOM: Returns true if this node is read-only. This is a
1811: * shallow check.
1812: */
1813: public boolean getReadOnly() {
1814:
1815: if (needsSyncData()) {
1816: synchronizeData();
1817: }
1818: return isReadOnly();
1819:
1820: } // getReadOnly():boolean
1821:
1822: /**
1823: * NON-DOM: As an alternative to subclassing the DOM, this implementation
1824: * has been extended with the ability to attach an object to each node.
1825: * (If you need multiple objects, you can attach a collection such as a
1826: * vector or hashtable, then attach your application information to that.)
1827: * <p><b>Important Note:</b> You are responsible for removing references
1828: * to your data on nodes that are no longer used. Failure to do so will
1829: * prevent the nodes, your data is attached to, to be garbage collected
1830: * until the whole document is.
1831: *
1832: * @param data the object to store or null to remove any existing reference
1833: */
1834: public void setUserData(Object data) {
1835: ownerDocument().setUserData(this , data);
1836: }
1837:
1838: /**
1839: * NON-DOM:
1840: * Returns the user data associated to this node.
1841: */
1842: public Object getUserData() {
1843: return ownerDocument().getUserData(this );
1844: }
1845:
1846: //
1847: // Protected methods
1848: //
1849:
1850: /**
1851: * Denotes that this node has changed.
1852: */
1853: protected void changed() {
1854: // we do not actually store this information on every node, we only
1855: // have a global indicator on the Document. Doing otherwise cost us too
1856: // much for little gain.
1857: ownerDocument().changed();
1858: }
1859:
1860: /**
1861: * Returns the number of changes to this node.
1862: */
1863: protected int changes() {
1864: // we do not actually store this information on every node, we only
1865: // have a global indicator on the Document. Doing otherwise cost us too
1866: // much for little gain.
1867: return ownerDocument().changes();
1868: }
1869:
1870: /**
1871: * Override this method in subclass to hook in efficient
1872: * internal data structure.
1873: */
1874: protected void synchronizeData() {
1875: // By default just change the flag to avoid calling this method again
1876: needsSyncData(false);
1877: }
1878:
1879: /**
1880: * For non-child nodes, the node which "points" to this node.
1881: * For example, the owning element for an attribute
1882: */
1883: protected Node getContainer() {
1884: return null;
1885: }
1886:
1887: /*
1888: * Flags setters and getters
1889: */
1890:
1891: final boolean isReadOnly() {
1892: return (flags & READONLY) != 0;
1893: }
1894:
1895: final void isReadOnly(boolean value) {
1896: flags = (short) (value ? flags | READONLY : flags & ~READONLY);
1897: }
1898:
1899: final boolean needsSyncData() {
1900: return (flags & SYNCDATA) != 0;
1901: }
1902:
1903: final void needsSyncData(boolean value) {
1904: flags = (short) (value ? flags | SYNCDATA : flags & ~SYNCDATA);
1905: }
1906:
1907: final boolean needsSyncChildren() {
1908: return (flags & SYNCCHILDREN) != 0;
1909: }
1910:
1911: public final void needsSyncChildren(boolean value) {
1912: flags = (short) (value ? flags | SYNCCHILDREN : flags
1913: & ~SYNCCHILDREN);
1914: }
1915:
1916: final boolean isOwned() {
1917: return (flags & OWNED) != 0;
1918: }
1919:
1920: final void isOwned(boolean value) {
1921: flags = (short) (value ? flags | OWNED : flags & ~OWNED);
1922: }
1923:
1924: final boolean isFirstChild() {
1925: return (flags & FIRSTCHILD) != 0;
1926: }
1927:
1928: final void isFirstChild(boolean value) {
1929: flags = (short) (value ? flags | FIRSTCHILD : flags
1930: & ~FIRSTCHILD);
1931: }
1932:
1933: final boolean isSpecified() {
1934: return (flags & SPECIFIED) != 0;
1935: }
1936:
1937: final void isSpecified(boolean value) {
1938: flags = (short) (value ? flags | SPECIFIED : flags & ~SPECIFIED);
1939: }
1940:
1941: // inconsistent name to avoid clash with public method on TextImpl
1942: final boolean internalIsIgnorableWhitespace() {
1943: return (flags & IGNORABLEWS) != 0;
1944: }
1945:
1946: final void isIgnorableWhitespace(boolean value) {
1947: flags = (short) (value ? flags | IGNORABLEWS : flags
1948: & ~IGNORABLEWS);
1949: }
1950:
1951: final boolean hasStringValue() {
1952: return (flags & HASSTRING) != 0;
1953: }
1954:
1955: final void hasStringValue(boolean value) {
1956: flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
1957: }
1958:
1959: final boolean isNormalized() {
1960: return (flags & NORMALIZED) != 0;
1961: }
1962:
1963: final void isNormalized(boolean value) {
1964: // See if flag should propagate to parent.
1965: if (!value && isNormalized() && ownerNode != null) {
1966: ownerNode.isNormalized(false);
1967: }
1968: flags = (short) (value ? flags | NORMALIZED : flags
1969: & ~NORMALIZED);
1970: }
1971:
1972: final boolean isIdAttribute() {
1973: return (flags & ID) != 0;
1974: }
1975:
1976: final void isIdAttribute(boolean value) {
1977: flags = (short) (value ? flags | ID : flags & ~ID);
1978: }
1979:
1980: //
1981: // Object methods
1982: //
1983:
1984: /** NON-DOM method for debugging convenience. */
1985: public String toString() {
1986: return "[" + getNodeName() + ": " + getNodeValue() + "]";
1987: }
1988:
1989: //
1990: // Serialization methods
1991: //
1992:
1993: /** Serialize object. */
1994: private void writeObject(ObjectOutputStream out) throws IOException {
1995:
1996: // synchronize data
1997: if (needsSyncData()) {
1998: synchronizeData();
1999: }
2000: // write object
2001: out.defaultWriteObject();
2002:
2003: } // writeObject(ObjectOutputStream)
2004:
2005: } // class NodeImpl
|