1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.dom;
  58. import java.io.IOException;
  59. import java.io.ObjectOutputStream;
  60. import java.io.Serializable;
  61. import java.util.Hashtable;
  62. import org.w3c.dom.UserDataHandler;
  63. import org.w3c.dom.DOMException;
  64. import org.w3c.dom.Document;
  65. import org.w3c.dom.DocumentType;
  66. import org.w3c.dom.NamedNodeMap;
  67. import org.w3c.dom.Node;
  68. import org.w3c.dom.NodeList;
  69. import org.w3c.dom.events.Event;
  70. import org.w3c.dom.events.EventListener;
  71. import org.w3c.dom.events.EventTarget;
  72. /**
  73. * NodeImpl provides the basic structure of a DOM tree. It is never used
  74. * directly, but instead is subclassed to add type and data
  75. * information, and additional methods, appropriate to each node of
  76. * the tree. Only its subclasses should be instantiated -- and those,
  77. * with the exception of Document itself, only through a specific
  78. * Document's factory methods.
  79. * <P>
  80. * The Node interface provides shared behaviors such as siblings and
  81. * children, both for consistancy and so that the most common tree
  82. * operations may be performed without constantly having to downcast
  83. * to specific node types. When there is no obvious mapping for one of
  84. * these queries, it will respond with null.
  85. * Note that the default behavior is that children are forbidden. To
  86. * permit them, the subclass ParentNode overrides several methods.
  87. * <P>
  88. * NodeImpl also implements NodeList, so it can return itself in
  89. * response to the getChildNodes() query. This eliminiates the need
  90. * for a separate ChildNodeList object. Note that this is an
  91. * IMPLEMENTATION DETAIL; applications should _never_ assume that
  92. * this identity exists.
  93. * <P>
  94. * All nodes in a single document must originate
  95. * in that document. (Note that this is much tighter than "must be
  96. * same implementation") Nodes are all aware of their ownerDocument,
  97. * and attempts to mismatch will throw WRONG_DOCUMENT_ERR.
  98. * <P>
  99. * However, to save memory not all nodes always have a direct reference
  100. * to their ownerDocument. When a node is owned by another node it relies
  101. * on its owner to store its ownerDocument. Parent nodes always store it
  102. * though, so there is never more than one level of indirection.
  103. * And when a node doesn't have an owner, ownerNode refers to its
  104. * ownerDocument.
  105. * <p>
  106. * This class doesn't directly support mutation events, however, it still
  107. * implements the EventTarget interface and forward all related calls to the
  108. * document so that the document class do so.
  109. *
  110. * @author Arnaud Le Hors, IBM
  111. * @author Joe Kesselman, IBM
  112. * @version $Id: NodeImpl.java,v 1.71 2004/01/16 16:23:50 elena Exp $
  113. * @since PR-DOM-Level-1-19980818.
  114. */
  115. public abstract class NodeImpl
  116. implements Node, NodeList, EventTarget, Cloneable, Serializable{
  117. //
  118. // Constants
  119. //
  120. // TreePosition Constants.
  121. // Taken from DOM L3 Node interface.
  122. /**
  123. * The node precedes the reference node.
  124. */
  125. public static final short TREE_POSITION_PRECEDING = 0x01;
  126. /**
  127. * The node follows the reference node.
  128. */
  129. public static final short TREE_POSITION_FOLLOWING = 0x02;
  130. /**
  131. * The node is an ancestor of the reference node.
  132. */
  133. public static final short TREE_POSITION_ANCESTOR = 0x04;
  134. /**
  135. * The node is a descendant of the reference node.
  136. */
  137. public static final short TREE_POSITION_DESCENDANT = 0x08;
  138. /**
  139. * The two nodes have an equivalent position. This is the case of two
  140. * attributes that have the same <code>ownerElement</code>, and two
  141. * nodes that are the same.
  142. */
  143. public static final short TREE_POSITION_EQUIVALENT = 0x10;
  144. /**
  145. * The two nodes are the same. Two nodes that are the same have an
  146. * equivalent position, though the reverse may not be true.
  147. */
  148. public static final short TREE_POSITION_SAME_NODE = 0x20;
  149. /**
  150. * The two nodes are disconnected, they do not have any common ancestor.
  151. * This is the case of two nodes that are not in the same document.
  152. */
  153. public static final short TREE_POSITION_DISCONNECTED = 0x00;
  154. // DocumentPosition
  155. public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
  156. public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
  157. public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
  158. public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
  159. public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
  160. public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
  161. /** Serialization version. */
  162. static final long serialVersionUID = -6316591992167219696L;
  163. // public
  164. /** Element definition node type. */
  165. public static final short ELEMENT_DEFINITION_NODE = 21;
  166. //
  167. // Data
  168. //
  169. // links
  170. protected NodeImpl ownerNode; // typically the parent but not always!
  171. // data
  172. protected short flags;
  173. protected final static short READONLY = 0x1<<0;
  174. protected final static short SYNCDATA = 0x1<<1;
  175. protected final static short SYNCCHILDREN = 0x1<<2;
  176. protected final static short OWNED = 0x1<<3;
  177. protected final static short FIRSTCHILD = 0x1<<4;
  178. protected final static short SPECIFIED = 0x1<<5;
  179. protected final static short IGNORABLEWS = 0x1<<6;
  180. protected final static short HASSTRING = 0x1<<7;
  181. protected final static short NORMALIZED = 0x1<<8;
  182. protected final static short ID = 0x1<<9;
  183. //
  184. // Constructors
  185. //
  186. /**
  187. * No public constructor; only subclasses of Node should be
  188. * instantiated, and those normally via a Document's factory methods
  189. * <p>
  190. * Every Node knows what Document it belongs to.
  191. */
  192. protected NodeImpl(CoreDocumentImpl ownerDocument) {
  193. // as long as we do not have any owner, ownerNode is our ownerDocument
  194. ownerNode = ownerDocument;
  195. } // <init>(CoreDocumentImpl)
  196. /** Constructor for serialization. */
  197. public NodeImpl() {}
  198. //
  199. // Node methods
  200. //
  201. /**
  202. * A short integer indicating what type of node this is. The named
  203. * constants for this value are defined in the org.w3c.dom.Node interface.
  204. */
  205. public abstract short getNodeType();
  206. /**
  207. * the name of this node.
  208. */
  209. public abstract String getNodeName();
  210. /**
  211. * Returns the node value.
  212. * @throws DOMException(DOMSTRING_SIZE_ERR)
  213. */
  214. public String getNodeValue()
  215. throws DOMException {
  216. return null; // overridden in some subclasses
  217. }
  218. /**
  219. * Sets the node value.
  220. * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
  221. */
  222. public void setNodeValue(String x)
  223. throws DOMException {
  224. // Default behavior is to do nothing, overridden in some subclasses
  225. }
  226. /**
  227. * Adds a child node to the end of the list of children for this node.
  228. * Convenience shorthand for insertBefore(newChild,null).
  229. * @see #insertBefore(Node, Node)
  230. * <P>
  231. * By default we do not accept any children, ParentNode overrides this.
  232. * @see ParentNode
  233. *
  234. * @return newChild, in its new state (relocated, or emptied in the case of
  235. * DocumentNode.)
  236. *
  237. * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
  238. * type that shouldn't be a child of this node.
  239. *
  240. * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
  241. * different owner document than we do.
  242. *
  243. * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
  244. * read-only.
  245. */
  246. public Node appendChild(Node newChild) throws DOMException {
  247. return insertBefore(newChild, null);
  248. }
  249. /**
  250. * Returns a duplicate of a given node. You can consider this a
  251. * generic "copy constructor" for nodes. The newly returned object should
  252. * be completely independent of the source object's subtree, so changes
  253. * in one after the clone has been made will not affect the other.
  254. * <P>
  255. * Note: since we never have any children deep is meaningless here,
  256. * ParentNode overrides this behavior.
  257. * @see ParentNode
  258. *
  259. * <p>
  260. * Example: Cloning a Text node will copy both the node and the text it
  261. * contains.
  262. * <p>
  263. * Example: Cloning something that has children -- Element or Attr, for
  264. * example -- will _not_ clone those children unless a "deep clone"
  265. * has been requested. A shallow clone of an Attr node will yield an
  266. * empty Attr of the same name.
  267. * <p>
  268. * NOTE: Clones will always be read/write, even if the node being cloned
  269. * is read-only, to permit applications using only the DOM API to obtain
  270. * editable copies of locked portions of the tree.
  271. */
  272. public Node cloneNode(boolean deep) {
  273. if (needsSyncData()) {
  274. synchronizeData();
  275. }
  276. NodeImpl newnode;
  277. try {
  278. newnode = (NodeImpl)clone();
  279. }
  280. catch (CloneNotSupportedException e) {
  281. // if we get here we have an error in our program we may as well
  282. // be vocal about it, so that people can take appropriate action.
  283. throw new RuntimeException("**Internal Error**" + e);
  284. }
  285. // Need to break the association w/ original kids
  286. newnode.ownerNode = ownerDocument();
  287. newnode.isOwned(false);
  288. // By default we make all clones readwrite,
  289. // this is overriden in readonly subclasses
  290. newnode.isReadOnly(false);
  291. ownerDocument().callUserDataHandlers(this, newnode,
  292. UserDataHandler.NODE_CLONED);
  293. return newnode;
  294. } // cloneNode(boolean):Node
  295. /**
  296. * Find the Document that this Node belongs to (the document in
  297. * whose context the Node was created). The Node may or may not
  298. * currently be part of that Document's actual contents.
  299. */
  300. public Document getOwnerDocument() {
  301. // if we have an owner simply forward the request
  302. // otherwise ownerNode is our ownerDocument
  303. if (isOwned()) {
  304. return ownerNode.ownerDocument();
  305. } else {
  306. return (Document) ownerNode;
  307. }
  308. }
  309. /**
  310. * same as above but returns internal type and this one is not overridden
  311. * by CoreDocumentImpl to return null
  312. */
  313. CoreDocumentImpl ownerDocument() {
  314. // if we have an owner simply forward the request
  315. // otherwise ownerNode is our ownerDocument
  316. if (isOwned()) {
  317. return ownerNode.ownerDocument();
  318. } else {
  319. return (CoreDocumentImpl) ownerNode;
  320. }
  321. }
  322. /**
  323. * NON-DOM
  324. * set the ownerDocument of this node
  325. */
  326. void setOwnerDocument(CoreDocumentImpl doc) {
  327. if (needsSyncData()) {
  328. synchronizeData();
  329. }
  330. // if we have an owner we rely on it to have it right
  331. // otherwise ownerNode is our ownerDocument
  332. if (!isOwned()) {
  333. ownerNode = doc;
  334. }
  335. }
  336. /**
  337. * Returns the node number
  338. */
  339. protected int getNodeNumber() {
  340. int nodeNumber;
  341. CoreDocumentImpl cd = (CoreDocumentImpl)(this.getOwnerDocument());
  342. nodeNumber = cd.getNodeNumber(this);
  343. return nodeNumber;
  344. }
  345. /**
  346. * Obtain the DOM-tree parent of this node, or null if it is not
  347. * currently active in the DOM tree (perhaps because it has just been
  348. * created or removed). Note that Document, DocumentFragment, and
  349. * Attribute will never have parents.
  350. */
  351. public Node getParentNode() {
  352. return null; // overriden by ChildNode
  353. }
  354. /*
  355. * same as above but returns internal type
  356. */
  357. NodeImpl parentNode() {
  358. return null;
  359. }
  360. /** The next child of this node's parent, or null if none */
  361. public Node getNextSibling() {
  362. return null; // default behavior, overriden in ChildNode
  363. }
  364. /** The previous child of this node's parent, or null if none */
  365. public Node getPreviousSibling() {
  366. return null; // default behavior, overriden in ChildNode
  367. }
  368. ChildNode previousSibling() {
  369. return null; // default behavior, overriden in ChildNode
  370. }
  371. /**
  372. * Return the collection of attributes associated with this node,
  373. * or null if none. At this writing, Element is the only type of node
  374. * which will ever have attributes.
  375. *
  376. * @see ElementImpl
  377. */
  378. public NamedNodeMap getAttributes() {
  379. return null; // overridden in ElementImpl
  380. }
  381. /**
  382. * Returns whether this node (if it is an element) has any attributes.
  383. * @return <code>true</code> if this node has any attributes,
  384. * <code>false</code> otherwise.
  385. * @since DOM Level 2
  386. * @see ElementImpl
  387. */
  388. public boolean hasAttributes() {
  389. return false; // overridden in ElementImpl
  390. }
  391. /**
  392. * Test whether this node has any children. Convenience shorthand
  393. * for (Node.getFirstChild()!=null)
  394. * <P>
  395. * By default we do not have any children, ParentNode overrides this.
  396. * @see ParentNode
  397. */
  398. public boolean hasChildNodes() {
  399. return false;
  400. }
  401. /**
  402. * Obtain a NodeList enumerating all children of this node. If there
  403. * are none, an (initially) empty NodeList is returned.
  404. * <p>
  405. * NodeLists are "live"; as children are added/removed the NodeList
  406. * will immediately reflect those changes. Also, the NodeList refers
  407. * to the actual nodes, so changes to those nodes made via the DOM tree
  408. * will be reflected in the NodeList and vice versa.
  409. * <p>
  410. * In this implementation, Nodes implement the NodeList interface and
  411. * provide their own getChildNodes() support. Other DOMs may solve this
  412. * differently.
  413. */
  414. public NodeList getChildNodes() {
  415. return this;
  416. }
  417. /** The first child of this Node, or null if none.
  418. * <P>
  419. * By default we do not have any children, ParentNode overrides this.
  420. * @see ParentNode
  421. */
  422. public Node getFirstChild() {
  423. return null;
  424. }
  425. /** The first child of this Node, or null if none.
  426. * <P>
  427. * By default we do not have any children, ParentNode overrides this.
  428. * @see ParentNode
  429. */
  430. public Node getLastChild() {
  431. return null;
  432. }
  433. /**
  434. * Move one or more node(s) to our list of children. Note that this
  435. * implicitly removes them from their previous parent.
  436. * <P>
  437. * By default we do not accept any children, ParentNode overrides this.
  438. * @see ParentNode
  439. *
  440. * @param newChild The Node to be moved to our subtree. As a
  441. * convenience feature, inserting a DocumentNode will instead insert
  442. * all its children.
  443. *
  444. * @param refChild Current child which newChild should be placed
  445. * immediately before. If refChild is null, the insertion occurs
  446. * after all existing Nodes, like appendChild().
  447. *
  448. * @return newChild, in its new state (relocated, or emptied in the case of
  449. * DocumentNode.)
  450. *
  451. * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
  452. * type that shouldn't be a child of this node, or if newChild is an
  453. * ancestor of this node.
  454. *
  455. * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
  456. * different owner document than we do.
  457. *
  458. * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
  459. * this node.
  460. *
  461. * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
  462. * read-only.
  463. */
  464. public Node insertBefore(Node newChild, Node refChild)
  465. throws DOMException {
  466. throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
  467. DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  468. "HIERARCHY_REQUEST_ERR", null));
  469. }
  470. /**
  471. * Remove a child from this Node. The removed child's subtree
  472. * remains intact so it may be re-inserted elsewhere.
  473. * <P>
  474. * By default we do not have any children, ParentNode overrides this.
  475. * @see ParentNode
  476. *
  477. * @return oldChild, in its new state (removed).
  478. *
  479. * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
  480. * this node.
  481. *
  482. * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
  483. * read-only.
  484. */
  485. public Node removeChild(Node oldChild)
  486. throws DOMException {
  487. throw new DOMException(DOMException.NOT_FOUND_ERR,
  488. DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  489. "NOT_FOUND_ERR", null));
  490. }
  491. /**
  492. * Make newChild occupy the location that oldChild used to
  493. * have. Note that newChild will first be removed from its previous
  494. * parent, if any. Equivalent to inserting newChild before oldChild,
  495. * then removing oldChild.
  496. * <P>
  497. * By default we do not have any children, ParentNode overrides this.
  498. * @see ParentNode
  499. *
  500. * @return oldChild, in its new state (removed).
  501. *
  502. * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
  503. * type that shouldn't be a child of this node, or if newChild is
  504. * one of our ancestors.
  505. *
  506. * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
  507. * different owner document than we do.
  508. *
  509. * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
  510. * this node.
  511. *
  512. * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
  513. * read-only.
  514. */
  515. public Node replaceChild(Node newChild, Node oldChild)
  516. throws DOMException {
  517. throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
  518. DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  519. "HIERARCHY_REQUEST_ERR", null));
  520. }
  521. //
  522. // NodeList methods
  523. //
  524. /**
  525. * NodeList method: Count the immediate children of this node
  526. * <P>
  527. * By default we do not have any children, ParentNode overrides this.
  528. * @see ParentNode
  529. *
  530. * @return int
  531. */
  532. public int getLength() {
  533. return 0;
  534. }
  535. /**
  536. * NodeList method: Return the Nth immediate child of this node, or
  537. * null if the index is out of bounds.
  538. * <P>
  539. * By default we do not have any children, ParentNode overrides this.
  540. * @see ParentNode
  541. *
  542. * @return org.w3c.dom.Node
  543. * @param Index int
  544. */
  545. public Node item(int index) {
  546. return null;
  547. }
  548. //
  549. // DOM2: methods, getters, setters
  550. //
  551. /**
  552. * Puts all <code>Text</code> nodes in the full depth of the sub-tree
  553. * underneath this <code>Node</code>, including attribute nodes, into a
  554. * "normal" form where only markup (e.g., tags, comments, processing
  555. * instructions, CDATA sections, and entity references) separates
  556. * <code>Text</code> nodes, i.e., there are no adjacent <code>Text</code>
  557. * nodes. This can be used to ensure that the DOM view of a document is
  558. * the same as if it were saved and re-loaded, and is useful when
  559. * operations (such as XPointer lookups) that depend on a particular
  560. * document tree structure are to be used.In cases where the document
  561. * contains <code>CDATASections</code>, the normalize operation alone may
  562. * not be sufficient, since XPointers do not differentiate between
  563. * <code>Text</code> nodes and <code>CDATASection</code> nodes.
  564. * <p>
  565. * Note that this implementation simply calls normalize() on this Node's
  566. * children. It is up to implementors or Node to override normalize()
  567. * to take action.
  568. */
  569. public void normalize() {
  570. /* by default we do not have any children,
  571. ParentNode overrides this behavior */
  572. }
  573. /**
  574. * Introduced in DOM Level 2. <p>
  575. * Tests whether the DOM implementation implements a specific feature and
  576. * that feature is supported by this node.
  577. * @param feature The package name of the feature to test. This is the same
  578. * name as what can be passed to the method hasFeature on
  579. * DOMImplementation.
  580. * @param version This is the version number of the package name to
  581. * test. In Level 2, version 1, this is the string "2.0". If the version is
  582. * not specified, supporting any version of the feature will cause the
  583. * method to return true.
  584. * @return boolean Returns true if this node defines a subtree within which
  585. * the specified feature is supported, false otherwise.
  586. * @since WD-DOM-Level-2-19990923
  587. */
  588. public boolean isSupported(String feature, String version)
  589. {
  590. return ownerDocument().getImplementation().hasFeature(feature,
  591. version);
  592. }
  593. /**
  594. * Introduced in DOM Level 2. <p>
  595. *
  596. * The namespace URI of this node, or null if it is unspecified. When this
  597. * node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE, this is
  598. * always null and setting it has no effect. <p>
  599. *
  600. * This is not a computed value that is the result of a namespace lookup
  601. * based on an examination of the namespace declarations in scope. It is
  602. * merely the namespace URI given at creation time.<p>
  603. *
  604. * For nodes created with a DOM Level 1 method, such as createElement
  605. * from the Document interface, this is null.
  606. * @since WD-DOM-Level-2-19990923
  607. * @see AttrNSImpl
  608. * @see ElementNSImpl
  609. */
  610. public String getNamespaceURI()
  611. {
  612. return null;
  613. }
  614. /**
  615. * Introduced in DOM Level 2. <p>
  616. *
  617. * The namespace prefix of this node, or null if it is unspecified. When
  618. * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE this
  619. * is always null and setting it has no effect.<p>
  620. *
  621. * For nodes created with a DOM Level 1 method, such as createElement
  622. * from the Document interface, this is null. <p>
  623. *
  624. * @since WD-DOM-Level-2-19990923
  625. * @see AttrNSImpl
  626. * @see ElementNSImpl
  627. */
  628. public String getPrefix()
  629. {
  630. return null;
  631. }
  632. /**
  633. * Introduced in DOM Level 2. <p>
  634. *
  635. * The namespace prefix of this node, or null if it is unspecified. When
  636. * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE
  637. * this is always null and setting it has no effect.<p>
  638. *
  639. * For nodes created with a DOM Level 1 method, such as createElement from
  640. * the Document interface, this is null.<p>
  641. *
  642. * Note that setting this attribute changes the nodeName attribute, which
  643. * holds the qualified name, as well as the tagName and name attributes of
  644. * the Element and Attr interfaces, when applicable.<p>
  645. *
  646. * @throws INVALID_CHARACTER_ERR Raised if the specified
  647. * prefix contains an invalid character.
  648. *
  649. * @since WD-DOM-Level-2-19990923
  650. * @see AttrNSImpl
  651. * @see ElementNSImpl
  652. */
  653. public void setPrefix(String prefix)
  654. throws DOMException
  655. {
  656. throw new DOMException(DOMException.NAMESPACE_ERR,
  657. DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  658. "NAMESPACE_ERR", null));
  659. }
  660. /**
  661. * Introduced in DOM Level 2. <p>
  662. *
  663. * Returns the local part of the qualified name of this node.
  664. * For nodes created with a DOM Level 1 method, such as createElement
  665. * from the Document interface, and for nodes of any type other than
  666. * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName
  667. * attribute.
  668. * @since WD-DOM-Level-2-19990923
  669. * @see AttrNSImpl
  670. * @see ElementNSImpl
  671. */
  672. public String getLocalName()
  673. {
  674. return null;
  675. }
  676. //
  677. // EventTarget support
  678. //
  679. public void addEventListener(String type, EventListener listener,
  680. boolean useCapture) {
  681. // simply forward to Document
  682. ownerDocument().addEventListener(this, type, listener, useCapture);
  683. }
  684. public void removeEventListener(String type, EventListener listener,
  685. boolean useCapture) {
  686. // simply forward to Document
  687. ownerDocument().removeEventListener(this, type, listener, useCapture);
  688. }
  689. public boolean dispatchEvent(Event event) {
  690. // simply forward to Document
  691. return ownerDocument().dispatchEvent(this, event);
  692. }
  693. //
  694. // Public DOM Level 3 methods
  695. //
  696. /**
  697. * The absolute base URI of this node or <code>null</code> if undefined.
  698. * This value is computed according to . However, when the
  699. * <code>Document</code> supports the feature "HTML" , the base URI is
  700. * computed using first the value of the href attribute of the HTML BASE
  701. * element if any, and the value of the <code>documentURI</code>
  702. * attribute from the <code>Document</code> interface otherwise.
  703. * <br> When the node is an <code>Element</code>, a <code>Document</code>
  704. * or a a <code>ProcessingInstruction</code>, this attribute represents
  705. * the properties [base URI] defined in . When the node is a
  706. * <code>Notation</code>, an <code>Entity</code>, or an
  707. * <code>EntityReference</code>, this attribute represents the
  708. * properties [declaration base URI] in the . How will this be affected
  709. * by resolution of relative namespace URIs issue?It's not.Should this
  710. * only be on Document, Element, ProcessingInstruction, Entity, and
  711. * Notation nodes, according to the infoset? If not, what is it equal to
  712. * on other nodes? Null? An empty string? I think it should be the
  713. * parent's.No.Should this be read-only and computed or and actual
  714. * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and
  715. * teleconference 30 May 2001).If the base HTML element is not yet
  716. * attached to a document, does the insert change the Document.baseURI?
  717. * Yes. (F2F 26 Sep 2001)
  718. * @since DOM Level 3
  719. */
  720. public String getBaseURI() {
  721. return null;
  722. }
  723. /**
  724. * Compares a node with this node with regard to their position in the
  725. * tree and according to the document order. This order can be extended
  726. * by module that define additional types of nodes.
  727. * @param other The node to compare against this node.
  728. * @return Returns how the given node is positioned relatively to this
  729. * node.
  730. * @since DOM Level 3
  731. * @deprecated
  732. */
  733. public short compareTreePosition(Node other) {
  734. // Questions of clarification for this method - to be answered by the
  735. // DOM WG. Current assumptions listed - LM
  736. //
  737. // 1. How do ENTITY nodes compare?
  738. // Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
  739. // aren't really 'in the tree'
  740. //
  741. // 2. How do NOTATION nodes compare?
  742. // Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
  743. // aren't really 'in the tree'
  744. //
  745. // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
  746. // only relevant for nodes that are "part of the document tree"?
  747. // <outer>
  748. // <inner myattr="true"/>
  749. // </outer>
  750. // Is the element node "outer" considered an ancestor of "myattr"?
  751. // Current assumption: No.
  752. //
  753. // 4. How do children of ATTRIBUTE nodes compare (with eachother, or
  754. // with children of other attribute nodes with the same element)
  755. // Current assumption: Children of ATTRIBUTE nodes are treated as if
  756. // they they are the attribute node itself, unless the 2 nodes
  757. // are both children of the same attribute.
  758. //
  759. // 5. How does an ENTITY_REFERENCE node compare with it's children?
  760. // Given the DOM, it should precede its children as an ancestor.
  761. // Given "document order", does it represent the same position?
  762. // Current assumption: An ENTITY_REFERENCE node is an ancestor of its
  763. // children.
  764. //
  765. // 6. How do children of a DocumentFragment compare?
  766. // Current assumption: If both nodes are part of the same document
  767. // fragment, there are compared as if they were part of a document.
  768. // If the nodes are the same...
  769. if (this==other)
  770. return (TREE_POSITION_SAME_NODE | TREE_POSITION_EQUIVALENT);
  771. // If either node is of type ENTITY or NOTATION, compare as disconnected
  772. short thisType = this.getNodeType();
  773. short otherType = other.getNodeType();
  774. // If either node is of type ENTITY or NOTATION, compare as disconnected
  775. if (thisType == Node.ENTITY_NODE ||
  776. thisType == Node.NOTATION_NODE ||
  777. otherType == Node.ENTITY_NODE ||
  778. otherType == Node.NOTATION_NODE ) {
  779. return TREE_POSITION_DISCONNECTED;
  780. }
  781. // Find the ancestor of each node, and the distance each node is from
  782. // its ancestor.
  783. // During this traversal, look for ancestor/descendent relationships
  784. // between the 2 nodes in question.
  785. // We do this now, so that we get this info correct for attribute nodes
  786. // and their children.
  787. Node node;
  788. Node thisAncestor = this;
  789. Node otherAncestor = other;
  790. int thisDepth=0;
  791. int otherDepth=0;
  792. for (node=this; node != null; node = node.getParentNode()) {
  793. thisDepth +=1;
  794. if (node == other)
  795. // The other node is an ancestor of this one.
  796. return (TREE_POSITION_ANCESTOR | TREE_POSITION_PRECEDING);
  797. thisAncestor = node;
  798. }
  799. for (node=other; node!=null; node=node.getParentNode()) {
  800. otherDepth +=1;
  801. if (node == this)
  802. // The other node is a descendent of the reference node.
  803. return (TREE_POSITION_DESCENDANT | TREE_POSITION_FOLLOWING);
  804. otherAncestor = node;
  805. }
  806. Node thisNode = this;
  807. Node otherNode = other;
  808. int thisAncestorType = thisAncestor.getNodeType();
  809. int otherAncestorType = otherAncestor.getNodeType();
  810. // if the ancestor is an attribute, get owning element.
  811. // we are now interested in the owner to determine position.
  812. if (thisAncestorType == Node.ATTRIBUTE_NODE) {
  813. thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
  814. }
  815. if (otherAncestorType == Node.ATTRIBUTE_NODE) {
  816. otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
  817. }
  818. // Before proceeding, we should check if both ancestor nodes turned
  819. // out to be attributes for the same element
  820. if (thisAncestorType == Node.ATTRIBUTE_NODE &&
  821. otherAncestorType == Node.ATTRIBUTE_NODE &&
  822. thisNode==otherNode)
  823. return TREE_POSITION_EQUIVALENT;
  824. // Now, find the ancestor of the owning element, if the original
  825. // ancestor was an attribute
  826. // Note: the following 2 loops are quite close to the ones above.
  827. // May want to common them up. LM.
  828. if (thisAncestorType == Node.ATTRIBUTE_NODE) {
  829. thisDepth=0;
  830. for (node=thisNode; node != null; node=node.getParentNode()) {
  831. thisDepth +=1;
  832. if (node == otherNode)
  833. // The other node is an ancestor of the owning element
  834. {
  835. return TREE_POSITION_PRECEDING;
  836. }
  837. thisAncestor = node;
  838. }
  839. }
  840. // Now, find the ancestor of the owning element, if the original
  841. // ancestor was an attribute
  842. if (otherAncestorType == Node.ATTRIBUTE_NODE) {
  843. otherDepth=0;
  844. for (node=otherNode; node != null; node=node.getParentNode()) {
  845. otherDepth +=1;
  846. if (node == thisNode)
  847. // The other node is a descendent of the reference
  848. // node's element
  849. return TREE_POSITION_FOLLOWING;
  850. otherAncestor = node;
  851. }
  852. }
  853. // thisAncestor and otherAncestor must be the same at this point,
  854. // otherwise, we are not in the same tree or document fragment
  855. if (thisAncestor != otherAncestor)
  856. return TREE_POSITION_DISCONNECTED;
  857. // Go up the parent chain of the deeper node, until we find a node
  858. // with the same depth as the shallower node
  859. if (thisDepth > otherDepth) {
  860. for (int i=0; i<thisDepth - otherDepth; i++)
  861. thisNode = thisNode.getParentNode();
  862. // Check if the node we have reached is in fact "otherNode". This can
  863. // happen in the case of attributes. In this case, otherNode
  864. // "precedes" this.
  865. if (thisNode == otherNode)
  866. return TREE_POSITION_PRECEDING;
  867. }
  868. else {
  869. for (int i=0; i<otherDepth - thisDepth; i++)
  870. otherNode = otherNode.getParentNode();
  871. // Check if the node we have reached is in fact "thisNode". This can
  872. // happen in the case of attributes. In this case, otherNode
  873. // "follows" this.
  874. if (otherNode == thisNode)
  875. return TREE_POSITION_FOLLOWING;
  876. }
  877. // We now have nodes at the same depth in the tree. Find a common
  878. // ancestor.
  879. Node thisNodeP, otherNodeP;
  880. for (thisNodeP=thisNode.getParentNode(),
  881. otherNodeP=otherNode.getParentNode();
  882. thisNodeP!=otherNodeP;) {
  883. thisNode = thisNodeP;
  884. otherNode = otherNodeP;
  885. thisNodeP = thisNodeP.getParentNode();
  886. otherNodeP = otherNodeP.getParentNode();
  887. }
  888. // At this point, thisNode and otherNode are direct children of
  889. // the common ancestor.
  890. // See whether thisNode or otherNode is the leftmost
  891. for (Node current=thisNodeP.getFirstChild();
  892. current!=null;
  893. current=current.getNextSibling()) {
  894. if (current==otherNode) {
  895. return TREE_POSITION_PRECEDING;
  896. }
  897. else if (current==thisNode) {
  898. return TREE_POSITION_FOLLOWING;
  899. }
  900. }
  901. // REVISIT: shouldn't get here. Should probably throw an
  902. // exception
  903. return 0;
  904. }
  905. /**
  906. * Compares a node with this node with regard to their position in the
  907. * document.
  908. * @param other The node to compare against this node.
  909. * @return Returns how the given node is positioned relatively to this
  910. * node.
  911. * @since DOM Level 3
  912. */
  913. public short compareDocumentPosition(Node other) throws DOMException {
  914. // If the nodes are the same, no flags should be set
  915. if (this==other)
  916. return 0;
  917. // check if other is from a different implementation
  918. try {
  919. NodeImpl node = (NodeImpl) other;
  920. } catch (ClassCastException e) {
  921. // other comes from a different implementation
  922. String msg = DOMMessageFormatter.formatMessage(
  923. DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
  924. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
  925. }
  926. Document thisOwnerDoc, otherOwnerDoc;
  927. // get the respective Document owners.
  928. if (this.getNodeType() == Node.DOCUMENT_NODE)
  929. thisOwnerDoc = (Document)this;
  930. else
  931. thisOwnerDoc = this.getOwnerDocument();
  932. if (other.getNodeType() == Node.DOCUMENT_NODE)
  933. otherOwnerDoc = (Document)other;
  934. else
  935. otherOwnerDoc = other.getOwnerDocument();
  936. // If from different documents, we know they are disconnected.
  937. // and have an implementation dependent order
  938. if (thisOwnerDoc != otherOwnerDoc &&
  939. thisOwnerDoc !=null &&
  940. otherOwnerDoc !=null)
  941. {
  942. int otherDocNum = ((CoreDocumentImpl)otherOwnerDoc).getNodeNumber();
  943. int thisDocNum = ((CoreDocumentImpl)thisOwnerDoc).getNodeNumber();
  944. if (otherDocNum > thisDocNum)
  945. return DOCUMENT_POSITION_DISCONNECTED |
  946. DOCUMENT_POSITION_FOLLOWING |
  947. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
  948. else
  949. return DOCUMENT_POSITION_DISCONNECTED |
  950. DOCUMENT_POSITION_PRECEDING |
  951. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
  952. }
  953. // Find the ancestor of each node, and the distance each node is from
  954. // its ancestor.
  955. // During this traversal, look for ancestor/descendent relationships
  956. // between the 2 nodes in question.
  957. // We do this now, so that we get this info correct for attribute nodes
  958. // and their children.
  959. Node node;
  960. Node thisAncestor = this;
  961. Node otherAncestor = other;
  962. int thisDepth=0;
  963. int otherDepth=0;
  964. for (node=this; node != null; node = node.getParentNode()) {
  965. thisDepth +=1;
  966. if (node == other)
  967. // The other node is an ancestor of this one.
  968. return (DOCUMENT_POSITION_CONTAINS |
  969. DOCUMENT_POSITION_PRECEDING);
  970. thisAncestor = node;
  971. }
  972. for (node=other; node!=null; node=node.getParentNode()) {
  973. otherDepth +=1;
  974. if (node == this)
  975. // The other node is a descendent of the reference node.
  976. return (DOCUMENT_POSITION_IS_CONTAINED |
  977. DOCUMENT_POSITION_FOLLOWING);
  978. otherAncestor = node;
  979. }
  980. int thisAncestorType = thisAncestor.getNodeType();
  981. int otherAncestorType = otherAncestor.getNodeType();
  982. Node thisNode = this;
  983. Node otherNode = other;
  984. // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
  985. // LM: should rewrite this.
  986. switch (thisAncestorType) {
  987. case Node.NOTATION_NODE:
  988. case Node.ENTITY_NODE: {
  989. DocumentType container = thisOwnerDoc.getDoctype();
  990. if (container == otherAncestor) return
  991. (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
  992. switch (otherAncestorType) {
  993. case Node.NOTATION_NODE:
  994. case Node.ENTITY_NODE: {
  995. if (thisAncestorType != otherAncestorType)
  996. // the nodes are of different types
  997. return ((thisAncestorType>otherAncestorType) ?
  998. DOCUMENT_POSITION_PRECEDING:DOCUMENT_POSITION_FOLLOWING);
  999. else {
  1000. // the nodes are of the same type. Find order.
  1001. if (thisAncestorType == Node.NOTATION_NODE)
  1002. if (((NamedNodeMapImpl)container.getNotations()).precedes(otherAncestor,thisAncestor))
  1003. return (DOCUMENT_POSITION_PRECEDING |
  1004. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
  1005. else
  1006. return (DOCUMENT_POSITION_FOLLOWING |
  1007. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
  1008. else
  1009. if (((NamedNodeMapImpl)container.getEntities()).precedes(otherAncestor,thisAncestor))
  1010. return (DOCUMENT_POSITION_PRECEDING |
  1011. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
  1012. else
  1013. return (DOCUMENT_POSITION_FOLLOWING |
  1014. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
  1015. }
  1016. }
  1017. }
  1018. thisNode = thisAncestor = thisOwnerDoc;
  1019. break;
  1020. }
  1021. case Node.DOCUMENT_TYPE_NODE: {
  1022. if (otherNode == thisOwnerDoc)
  1023. return (DOCUMENT_POSITION_PRECEDING |
  1024. DOCUMENT_POSITION_CONTAINS);
  1025. else if (thisOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
  1026. return (DOCUMENT_POSITION_FOLLOWING);
  1027. break;
  1028. }
  1029. case Node.ATTRIBUTE_NODE: {
  1030. thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
  1031. if (otherAncestorType==Node.ATTRIBUTE_NODE) {
  1032. otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
  1033. if (otherNode == thisNode) {
  1034. if (((NamedNodeMapImpl)thisNode.getAttributes()).precedes(other,this))
  1035. return (DOCUMENT_POSITION_PRECEDING |
  1036. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
  1037. else
  1038. return (DOCUMENT_POSITION_FOLLOWING |
  1039. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
  1040. }
  1041. }
  1042. // Now, find the ancestor of the element
  1043. thisDepth=0;
  1044. for (node=thisNode; node != null; node=node.getParentNode()) {
  1045. thisDepth +=1;
  1046. if (node == otherNode)
  1047. {
  1048. // The other node is an ancestor of the owning element
  1049. return (DOCUMENT_POSITION_CONTAINS |
  1050. DOCUMENT_POSITION_PRECEDING);
  1051. }
  1052. thisAncestor = node;
  1053. }
  1054. }
  1055. }
  1056. switch (otherAncestorType) {
  1057. case Node.NOTATION_NODE:
  1058. case Node.ENTITY_NODE: {
  1059. DocumentType container = thisOwnerDoc.getDoctype();
  1060. if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED |
  1061. DOCUMENT_POSITION_FOLLOWING);
  1062. otherNode = otherAncestor = thisOwnerDoc;
  1063. break;
  1064. }
  1065. case Node.DOCUMENT_TYPE_NODE: {
  1066. if (thisNode == otherOwnerDoc)
  1067. return (DOCUMENT_POSITION_FOLLOWING |
  1068. DOCUMENT_POSITION_IS_CONTAINED);
  1069. else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
  1070. return (DOCUMENT_POSITION_PRECEDING);
  1071. break;
  1072. }
  1073. case Node.ATTRIBUTE_NODE: {
  1074. otherDepth=0;
  1075. otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
  1076. for (node=otherNode; node != null; node=node.getParentNode()) {
  1077. otherDepth +=1;
  1078. if (node == thisNode)
  1079. // The other node is a descendent of the reference
  1080. // node's element
  1081. return DOCUMENT_POSITION_FOLLOWING |
  1082. DOCUMENT_POSITION_IS_CONTAINED;
  1083. otherAncestor = node;
  1084. }
  1085. }
  1086. }
  1087. // thisAncestor and otherAncestor must be the same at this point,
  1088. // otherwise, the original nodes are disconnected
  1089. if (thisAncestor != otherAncestor) {
  1090. int thisAncestorNum, otherAncestorNum;
  1091. thisAncestorNum = ((NodeImpl)thisAncestor).getNodeNumber();
  1092. otherAncestorNum = ((NodeImpl)otherAncestor).getNodeNumber();
  1093. if (thisAncestorNum > otherAncestorNum)
  1094. return DOCUMENT_POSITION_DISCONNECTED |
  1095. DOCUMENT_POSITION_FOLLOWING |
  1096. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
  1097. else
  1098. return DOCUMENT_POSITION_DISCONNECTED |
  1099. DOCUMENT_POSITION_PRECEDING |
  1100. DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
  1101. }
  1102. // Go up the parent chain of the deeper node, until we find a node
  1103. // with the same depth as the shallower node
  1104. if (thisDepth > otherDepth) {
  1105. for (int i=0; i<thisDepth - otherDepth; i++)
  1106. thisNode = thisNode.getParentNode();
  1107. // Check if the node we have reached is in fact "otherNode". This can
  1108. // happen in the case of attributes. In this case, otherNode
  1109. // "precedes" this.
  1110. if (thisNode == otherNode)
  1111. {
  1112. return DOCUMENT_POSITION_PRECEDING;
  1113. }
  1114. }
  1115. else {
  1116. for (int i=0; i<otherDepth - thisDepth; i++)
  1117. otherNode = otherNode.getParentNode();
  1118. // Check if the node we have reached is in fact "thisNode". This can
  1119. // happen in the case of attributes. In this case, otherNode
  1120. // "follows" this.
  1121. if (otherNode == thisNode)
  1122. return DOCUMENT_POSITION_FOLLOWING;
  1123. }
  1124. // We now have nodes at the same depth in the tree. Find a common
  1125. // ancestor.
  1126. Node thisNodeP, otherNodeP;
  1127. for (thisNodeP=thisNode.getParentNode(),
  1128. otherNodeP=otherNode.getParentNode();
  1129. thisNodeP!=otherNodeP;) {
  1130. thisNode = thisNodeP;
  1131. otherNode = otherNodeP;
  1132. thisNodeP = thisNodeP.getParentNode();
  1133. otherNodeP = otherNodeP.getParentNode();
  1134. }
  1135. // At this point, thisNode and otherNode are direct children of
  1136. // the common ancestor.
  1137. // See whether thisNode or otherNode is the leftmost
  1138. for (Node current=thisNodeP.getFirstChild();
  1139. current!=null;
  1140. current=current.getNextSibling()) {
  1141. if (current==otherNode) {
  1142. return DOCUMENT_POSITION_PRECEDING;
  1143. }
  1144. else if (current==thisNode) {
  1145. return DOCUMENT_POSITION_FOLLOWING;
  1146. }
  1147. }
  1148. // REVISIT: shouldn't get here. Should probably throw an
  1149. // exception
  1150. return 0;
  1151. }
  1152. /**
  1153. * This attribute returns the text content of this node and its
  1154. * descendants. When it is defined to be null, setting it has no effect.
  1155. * When set, any possible children this node may have are removed and
  1156. * replaced by a single <code>Text</code> node containing the string
  1157. * this attribute is set to. On getting, no serialization is performed,
  1158. * the returned string does not contain any markup. No whitespace
  1159. * normalization is performed, the returned string does not contain the
  1160. * element content whitespaces . Similarly, on setting, no parsing is
  1161. * performed either, the input string is taken as pure textual content.
  1162. * <br>The string returned is made of the text content of this node
  1163. * depending on its type, as defined below:
  1164. * <table border='1'>
  1165. * <tr>
  1166. * <th>Node type</th>
  1167. * <th>Content</th>
  1168. * </tr>
  1169. /**
  1170. * This attribute returns the text content of this node and its
  1171. * descendants. When it is defined to be null, setting it has no effect.
  1172. * When set, any possible children this node may have are removed and
  1173. * replaced by a single <code>Text</code> node containing the string
  1174. * this attribute is set to. On getting, no serialization is performed,
  1175. * the returned string does not contain any markup. No whitespace
  1176. * normalization is performed, the returned string does not contain the
  1177. * element content whitespaces . Similarly, on setting, no parsing is
  1178. * performed either, the input string is taken as pure textual content.
  1179. * <br>The string returned is made of the text content of this node
  1180. * depending on its type, as defined below:
  1181. * <table border='1'>
  1182. * <tr>
  1183. * <th>Node type</th>
  1184. * <th>Content</th>
  1185. * </tr>
  1186. * <tr>
  1187. * <td valign='top' rowspan='1' colspan='1'>
  1188. * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
  1189. * DOCUMENT_FRAGMENT_NODE</td>
  1190. * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
  1191. * attribute value of every child node, excluding COMMENT_NODE and
  1192. * PROCESSING_INSTRUCTION_NODE nodes</td>
  1193. * </tr>
  1194. * <tr>
  1195. * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
  1196. * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
  1197. * <td valign='top' rowspan='1' colspan='1'>
  1198. * <code>nodeValue</code></td>
  1199. * </tr>
  1200. * <tr>
  1201. * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
  1202. * <td valign='top' rowspan='1' colspan='1'>
  1203. * null</td>
  1204. * </tr>
  1205. * </table>
  1206. * @exception DOMException
  1207. * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
  1208. * @exception DOMException
  1209. * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
  1210. * fit in a <code>DOMString</code> variable on the implementation
  1211. * platform.
  1212. * @since DOM Level 3
  1213. */
  1214. public String getTextContent() throws DOMException {
  1215. return getNodeValue(); // overriden in some subclasses
  1216. }
  1217. // internal method taking a StringBuffer in parameter
  1218. void getTextContent(StringBuffer buf) throws DOMException {
  1219. String content = getNodeValue();
  1220. if (content != null) {
  1221. buf.append(content);
  1222. }
  1223. }
  1224. /**
  1225. * This attribute returns the text content of this node and its
  1226. * descendants. When it is defined to be null, setting it has no effect.
  1227. * When set, any possible children this node may have are removed and
  1228. * replaced by a single <code>Text</code> node containing the string
  1229. * this attribute is set to. On getting, no serialization is performed,
  1230. * the returned string does not contain any markup. No whitespace
  1231. * normalization is performed, the returned string does not contain the
  1232. * element content whitespaces . Similarly, on setting, no parsing is
  1233. * performed either, the input string is taken as pure textual content.
  1234. * <br>The string returned is made of the text content of this node
  1235. * depending on its type, as defined below:
  1236. * <table border='1'>
  1237. * <tr>
  1238. * <th>Node type</th>
  1239. * <th>Content</th>
  1240. * </tr>
  1241. * <tr>
  1242. * <td valign='top' rowspan='1' colspan='1'>
  1243. * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
  1244. * DOCUMENT_FRAGMENT_NODE</td>
  1245. * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
  1246. * attribute value of every child node, excluding COMMENT_NODE and
  1247. * PROCESSING_INSTRUCTION_NODE nodes</td>
  1248. * </tr>
  1249. * <tr>
  1250. * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
  1251. * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
  1252. * <td valign='top' rowspan='1' colspan='1'>
  1253. * <code>nodeValue</code></td>
  1254. * </tr>
  1255. * <tr>
  1256. * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
  1257. * <td valign='top' rowspan='1' colspan='1'>
  1258. * null</td>
  1259. * </tr>
  1260. * </table>
  1261. * @exception DOMException
  1262. * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
  1263. * @exception DOMException
  1264. * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
  1265. * fit in a <code>DOMString</code> variable on the implementation
  1266. * platform.
  1267. * @since DOM Level 3
  1268. */
  1269. public void setTextContent(String textContent)
  1270. throws DOMException {
  1271. setNodeValue(textContent);
  1272. }
  1273. /**
  1274. * Returns whether this node is the same node as the given one.
  1275. * <br>This method provides a way to determine whether two
  1276. * <code>Node</code> references returned by the implementation reference
  1277. * the same object. When two <code>Node</code> references are references
  1278. * to the same object, even if through a proxy, the references may be
  1279. * used completely interchangably, such that all attributes have the
  1280. * same values and calling the same DOM method on either reference
  1281. * always has exactly the same effect.
  1282. * @param other The node to test against.
  1283. * @return Returns <code>true</code> if the nodes are the same,
  1284. * <code>false</code> otherwise.
  1285. * @since DOM Level 3
  1286. */
  1287. public boolean isSameNode(Node other) {
  1288. // we do not use any wrapper so the answer is obvious
  1289. return this == other;
  1290. }
  1291. /**
  1292. * DOM Level 3: Experimental
  1293. * This method checks if the specified <code>namespaceURI</code> is the
  1294. * default namespace or not.
  1295. * @param namespaceURI The namespace URI to look for.
  1296. * @return <code>true</code> if the specified <code>namespaceURI</code>
  1297. * is the default namespace, <code>false</code> otherwise.
  1298. * @since DOM Level 3
  1299. */
  1300. public boolean isDefaultNamespace(String namespaceURI){
  1301. // REVISIT: remove casts when DOM L3 becomes REC.
  1302. short type = this.getNodeType();
  1303. switch (type) {
  1304. case Node.ELEMENT_NODE: {
  1305. String namespace = this.getNamespaceURI();
  1306. String prefix = this.getPrefix();
  1307. // REVISIT: is it possible that prefix is empty string?
  1308. if (prefix == null || prefix.length() == 0) {
  1309. if (namespaceURI == null) {
  1310. return (namespace == namespaceURI);
  1311. }
  1312. return namespaceURI.equals(namespace);
  1313. }
  1314. if (this.hasAttributes()) {
  1315. ElementImpl elem = (ElementImpl)this;
  1316. NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
  1317. if (attr != null) {
  1318. String value = attr.getNodeValue();
  1319. if (namespaceURI == null) {
  1320. return (namespace == value);
  1321. }
  1322. return namespaceURI.equals(value);
  1323. }
  1324. }
  1325. NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
  1326. if (ancestor != null) {
  1327. return ancestor.isDefaultNamespace(namespaceURI);
  1328. }
  1329. return false;
  1330. }
  1331. case Node.DOCUMENT_NODE:{
  1332. return((NodeImpl)((Document)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
  1333. }
  1334. case Node.ENTITY_NODE :
  1335. case Node.NOTATION_NODE:
  1336. case Node.DOCUMENT_FRAGMENT_NODE:
  1337. case Node.DOCUMENT_TYPE_NODE:
  1338. // type is unknown
  1339. return false;
  1340. case Node.ATTRIBUTE_NODE:{
  1341. if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
  1342. return ownerNode.isDefaultNamespace(namespaceURI);
  1343. }
  1344. return false;
  1345. }
  1346. default:{
  1347. NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
  1348. if (ancestor != null) {
  1349. return ancestor.isDefaultNamespace(namespaceURI);
  1350. }
  1351. return false;
  1352. }
  1353. }
  1354. }
  1355. /**
  1356. *
  1357. * DOM Level 3 - Experimental:
  1358. * Look up the prefix associated to the given namespace URI, starting from this node.
  1359. *
  1360. * @param namespaceURI
  1361. * @return the prefix for the namespace
  1362. */
  1363. public String lookupPrefix(String namespaceURI){
  1364. // REVISIT: When Namespaces 1.1 comes out this may not be true
  1365. // Prefix can't be bound to null namespace
  1366. if (namespaceURI == null) {
  1367. return null;
  1368. }
  1369. short type = this.getNodeType();
  1370. switch (type) {
  1371. case Node.ELEMENT_NODE: {
  1372. String namespace = this.getNamespaceURI(); // to flip out children
  1373. return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
  1374. }
  1375. case Node.DOCUMENT_NODE:{
  1376. return((NodeImpl)((Document)this).getDocumentElement()).lookupPrefix(namespaceURI);
  1377. }
  1378. case Node.ENTITY_NODE :
  1379. case Node.NOTATION_NODE:
  1380. case Node.DOCUMENT_FRAGMENT_NODE:
  1381. case Node.DOCUMENT_TYPE_NODE:
  1382. // type is unknown
  1383. return null;
  1384. case Node.ATTRIBUTE_NODE:{
  1385. if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
  1386. return ownerNode.lookupPrefix(namespaceURI);
  1387. }
  1388. return null;
  1389. }
  1390. default:{
  1391. NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
  1392. if (ancestor != null) {
  1393. return ancestor.lookupPrefix(namespaceURI);
  1394. }
  1395. return null;
  1396. }
  1397. }
  1398. }
  1399. /**
  1400. * DOM Level 3 - Experimental:
  1401. * Look up the namespace URI associated to the given prefix, starting from this node.
  1402. * Use lookupNamespaceURI(null) to lookup the default namespace
  1403. *
  1404. * @param namespaceURI
  1405. * @return th URI for the namespace
  1406. * @since DOM Level 3
  1407. */
  1408. public String lookupNamespaceURI(String specifiedPrefix) {
  1409. short type = this.getNodeType();
  1410. switch (type) {
  1411. case Node.ELEMENT_NODE : {
  1412. String namespace = this.getNamespaceURI();
  1413. String prefix = this.getPrefix();
  1414. if (namespace !=null) {
  1415. // REVISIT: is it possible that prefix is empty string?
  1416. if (specifiedPrefix== null && prefix==specifiedPrefix) {
  1417. // looking for default namespace
  1418. return namespace;
  1419. } else if (prefix != null && prefix.equals(specifiedPrefix)) {
  1420. // non default namespace
  1421. return namespace;
  1422. }
  1423. }
  1424. if (this.hasAttributes()) {
  1425. NamedNodeMap map = this.getAttributes();
  1426. int length = map.getLength();
  1427. for (int i=0;i<length;i++) {
  1428. Node attr = map.item(i);
  1429. String attrPrefix = attr.getPrefix();
  1430. String value = attr.getNodeValue();
  1431. namespace = attr.getNamespaceURI();
  1432. if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
  1433. // at this point we are dealing with DOM Level 2 nodes only
  1434. if (specifiedPrefix == null &&
  1435. attr.getNodeName().equals("xmlns")) {
  1436. // default namespace
  1437. return value;
  1438. } else if (attrPrefix !=null &&
  1439. attrPrefix.equals("xmlns") &&
  1440. attr.getLocalName().equals(specifiedPrefix)) {
  1441. // non default namespace
  1442. return value;
  1443. }
  1444. }
  1445. }
  1446. }
  1447. NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
  1448. if (ancestor != null) {
  1449. return ancestor.lookupNamespaceURI(specifiedPrefix);
  1450. }
  1451. return null;
  1452. }
  1453. case Node.DOCUMENT_NODE : {
  1454. return((NodeImpl)((Document)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix);
  1455. }
  1456. case Node.ENTITY_NODE :
  1457. case Node.NOTATION_NODE:
  1458. case Node.DOCUMENT_FRAGMENT_NODE:
  1459. case Node.DOCUMENT_TYPE_NODE:
  1460. // type is unknown
  1461. return null;
  1462. case Node.ATTRIBUTE_NODE:{
  1463. if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
  1464. return ownerNode.lookupNamespaceURI(specifiedPrefix);
  1465. }
  1466. return null;
  1467. }
  1468. default:{
  1469. NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
  1470. if (ancestor != null) {
  1471. return ancestor.lookupNamespaceURI(specifiedPrefix);
  1472. }
  1473. return null;
  1474. }
  1475. }
  1476. }
  1477. Node getElementAncestor (Node currentNode){
  1478. Node parent = currentNode.getParentNode();
  1479. if (parent != null) {
  1480. short type = parent.getNodeType();
  1481. if (type == Node.ELEMENT_NODE) {
  1482. return parent;
  1483. }
  1484. return getElementAncestor(parent);
  1485. }
  1486. return null;
  1487. }
  1488. String lookupNamespacePrefix(String namespaceURI, ElementImpl el){
  1489. String namespace = this.getNamespaceURI();
  1490. // REVISIT: if no prefix is available is it null or empty string, or
  1491. // could be both?
  1492. String prefix = this.getPrefix();
  1493. if (namespace!=null && namespace.equals(namespaceURI)) {
  1494. if (prefix != null) {
  1495. String foundNamespace = el.lookupNamespaceURI(prefix);
  1496. if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
  1497. return prefix;
  1498. }
  1499. }
  1500. }
  1501. if (this.hasAttributes()) {
  1502. NamedNodeMap map = this.getAttributes();
  1503. int length = map.getLength();
  1504. for (int i=0;i<length;i++) {
  1505. Node attr = map.item(i);
  1506. String attrPrefix = attr.getPrefix();
  1507. String value = attr.getNodeValue();
  1508. namespace = attr.getNamespaceURI();
  1509. if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
  1510. // DOM Level 2 nodes
  1511. if (((attr.getNodeName().equals("xmlns")) ||
  1512. (attrPrefix !=null && attrPrefix.equals("xmlns")) &&
  1513. value.equals(namespaceURI))) {
  1514. String localname= attr.getLocalName();
  1515. String foundNamespace = el.lookupNamespaceURI(localname);
  1516. if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
  1517. return localname;
  1518. }
  1519. }
  1520. }
  1521. }
  1522. }
  1523. NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
  1524. if (ancestor != null) {
  1525. return ancestor.lookupNamespacePrefix(namespaceURI, el);
  1526. }
  1527. return null;
  1528. }
  1529. /**
  1530. * Tests whether two nodes are equal.
  1531. * <br>This method tests for equality of nodes, not sameness (i.e.,
  1532. * whether the two nodes are references to the same object) which can be
  1533. * tested with <code>Node.isSameNode</code>. All nodes that are the same
  1534. * will also be equal, though the reverse may not be true.
  1535. * <br>Two nodes are equal if and only if the following conditions are
  1536. * satisfied: The two nodes are of the same type.The following string
  1537. * attributes are equal: <code>nodeName</code>, <code>localName</code>,
  1538. * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code>
  1539. * , <code>baseURI</code>. This is: they are both <code>null</code>, or
  1540. * they have the same length and are character for character identical.
  1541. * The <code>attributes</code> <code>NamedNodeMaps</code> are equal.
  1542. * This is: they are both <code>null</code>, or they have the same
  1543. * length and for each node that exists in one map there is a node that
  1544. * exists in the other map and is equal, although not necessarily at the
  1545. * same index.The <code>childNodes</code> <code>NodeLists</code> are
  1546. * equal. This is: they are both <code>null</code>, or they have the
  1547. * same length and contain equal nodes at the same index. This is true
  1548. * for <code>Attr</code> nodes as for any other type of node. Note that
  1549. * normalization can affect equality; to avoid this, nodes should be
  1550. * normalized before being compared.
  1551. * <br>For two <code>DocumentType</code> nodes to be equal, the following
  1552. * conditions must also be satisfied: The following string attributes
  1553. * are equal: <code>publicId</code>, <code>systemId</code>,
  1554. * <code>internalSubset</code>.The <code>entities</code>
  1555. * <code>NamedNodeMaps</code> are equal.The <code>notations</code>
  1556. * <code>NamedNodeMaps</code> are equal.
  1557. * <br>On the other hand, the following do not affect equality: the
  1558. * <code>ownerDocument</code> attribute, the <code>specified</code>
  1559. * attribute for <code>Attr</code> nodes, the
  1560. * <code>isWhitespaceInElementContent</code> attribute for
  1561. * <code>Text</code> nodes, as well as any user data or event listeners
  1562. * registered on the nodes.
  1563. * @param arg The node to compare equality with.
  1564. * @param deep If <code>true</code>, recursively compare the subtrees; if
  1565. * <code>false</code>, compare only the nodes themselves (and its
  1566. * attributes, if it is an <code>Element</code>).
  1567. * @return If the nodes, and possibly subtrees are equal,
  1568. * <code>true</code> otherwise <code>false</code>.
  1569. * @since DOM Level 3
  1570. */
  1571. public boolean isEqualNode(Node arg) {
  1572. if (arg == this) {
  1573. return true;
  1574. }
  1575. if (arg.getNodeType() != getNodeType()) {
  1576. return false;
  1577. }
  1578. // in theory nodeName can't be null but better be careful
  1579. // who knows what other implementations may be doing?...
  1580. if (getNodeName() == null) {
  1581. if (arg.getNodeName() != null) {
  1582. return false;
  1583. }
  1584. }
  1585. else if (!getNodeName().equals(arg.getNodeName())) {
  1586. return false;
  1587. }
  1588. if (getLocalName() == null) {
  1589. if (arg.getLocalName() != null) {
  1590. return false;
  1591. }
  1592. }
  1593. else if (!getLocalName().equals(arg.getLocalName())) {
  1594. return false;
  1595. }
  1596. if (getNamespaceURI() == null) {
  1597. if (arg.getNamespaceURI() != null) {
  1598. return false;
  1599. }
  1600. }
  1601. else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
  1602. return false;
  1603. }
  1604. if (getPrefix() == null) {
  1605. if (arg.getPrefix() != null) {
  1606. return false;
  1607. }
  1608. }
  1609. else if (!getPrefix().equals(arg.getPrefix())) {
  1610. return false;
  1611. }
  1612. if (getNodeValue() == null) {
  1613. if (arg.getNodeValue() != null) {
  1614. return false;
  1615. }
  1616. }
  1617. else if (!getNodeValue().equals(arg.getNodeValue())) {
  1618. return false;
  1619. }
  1620. return true;
  1621. }
  1622. /**
  1623. * @since DOM Level 3
  1624. */
  1625. public Object getFeature(String feature, String version) {
  1626. // we don't have any alternate node, either this node does the job
  1627. // or we don't have anything that does
  1628. return isSupported(feature, version) ? this : null;
  1629. }
  1630. /**
  1631. * Associate an object to a key on this node. The object can later be
  1632. * retrieved from this node by calling <code>getUserData</code> with the
  1633. * same key.
  1634. * @param key The key to associate the object to.
  1635. * @param data The object to associate to the given key, or
  1636. * <code>null</code> to remove any existing association to that key.
  1637. * @param handler The handler to associate to that key, or
  1638. * <code>null</code>.
  1639. * @return Returns the <code>DOMObject</code> previously associated to
  1640. * the given key on this node, or <code>null</code> if there was none.
  1641. * @since DOM Level 3
  1642. */
  1643. public Object setUserData(String key,
  1644. Object data,
  1645. UserDataHandler handler) {
  1646. return ownerDocument().setUserData(this, key, data, handler);
  1647. }
  1648. /**
  1649. * Retrieves the object associated to a key on a this node. The object
  1650. * must first have been set to this node by calling
  1651. * <code>setUserData</code> with the same key.
  1652. * @param key The key the object is associated to.
  1653. * @return Returns the <code>DOMObject</code> associated to the given key
  1654. * on this node, or <code>null</code> if there was none.
  1655. * @since DOM Level 3
  1656. */
  1657. public Object getUserData(String key) {
  1658. return ownerDocument().getUserData(this, key);
  1659. }
  1660. /**
  1661. */
  1662. protected Hashtable getUserDataRecord(){
  1663. return ownerDocument().getUserDataRecord(this);
  1664. }
  1665. //
  1666. // Public methods
  1667. //
  1668. /**
  1669. * NON-DOM: PR-DOM-Level-1-19980818 mentions readonly nodes in conjunction
  1670. * with Entities, but provides no API to support this.
  1671. * <P>
  1672. * Most DOM users should not touch this method. Its anticpated use
  1673. * is during construction of EntityRefernces, where it will be used to
  1674. * lock the contents replicated from Entity so they can't be casually
  1675. * altered. It _could_ be published as a DOM extension, if desired.
  1676. * <P>
  1677. * Note: since we never have any children deep is meaningless here,
  1678. * ParentNode overrides this behavior.
  1679. * @see ParentNode
  1680. *
  1681. * @param readOnly True or false as desired.
  1682. * @param deep If true, children are also toggled. Note that this will
  1683. * not change the state of an EntityReference or its children,
  1684. * which are always read-only.
  1685. */
  1686. public void setReadOnly(boolean readOnly, boolean deep) {
  1687. if (needsSyncData()) {
  1688. synchronizeData();
  1689. }
  1690. isReadOnly(readOnly);
  1691. } // setReadOnly(boolean,boolean)
  1692. /**
  1693. * NON-DOM: Returns true if this node is read-only. This is a
  1694. * shallow check.
  1695. */
  1696. public boolean getReadOnly() {
  1697. if (needsSyncData()) {
  1698. synchronizeData();
  1699. }
  1700. return isReadOnly();
  1701. } // getReadOnly():boolean
  1702. /**
  1703. * NON-DOM: As an alternative to subclassing the DOM, this implementation
  1704. * has been extended with the ability to attach an object to each node.
  1705. * (If you need multiple objects, you can attach a collection such as a
  1706. * vector or hashtable, then attach your application information to that.)
  1707. * <p><b>Important Note:</b> You are responsible for removing references
  1708. * to your data on nodes that are no longer used. Failure to do so will
  1709. * prevent the nodes, your data is attached to, to be garbage collected
  1710. * until the whole document is.
  1711. *
  1712. * @param data the object to store or null to remove any existing reference
  1713. */
  1714. public void setUserData(Object data) {
  1715. ownerDocument().setUserData(this, data);
  1716. }
  1717. /**
  1718. * NON-DOM:
  1719. * Returns the user data associated to this node.
  1720. */
  1721. public Object getUserData() {
  1722. return ownerDocument().getUserData(this);
  1723. }
  1724. //
  1725. // Protected methods
  1726. //
  1727. /**
  1728. * Denotes that this node has changed.
  1729. */
  1730. protected void changed() {
  1731. // we do not actually store this information on every node, we only
  1732. // have a global indicator on the Document. Doing otherwise cost us too
  1733. // much for little gain.
  1734. ownerDocument().changed();
  1735. }
  1736. /**
  1737. * Returns the number of changes to this node.
  1738. */
  1739. protected int changes() {
  1740. // we do not actually store this information on every node, we only
  1741. // have a global indicator on the Document. Doing otherwise cost us too
  1742. // much for little gain.
  1743. return ownerDocument().changes();
  1744. }
  1745. /**
  1746. * Override this method in subclass to hook in efficient
  1747. * internal data structure.
  1748. */
  1749. protected void synchronizeData() {
  1750. // By default just change the flag to avoid calling this method again
  1751. needsSyncData(false);
  1752. }
  1753. /**
  1754. * For non-child nodes, the node which "points" to this node.
  1755. * For example, the owning element for an attribute
  1756. */
  1757. protected Node getContainer() {
  1758. return null;
  1759. }
  1760. /*
  1761. * Flags setters and getters
  1762. */
  1763. final boolean isReadOnly() {
  1764. return (flags & READONLY) != 0;
  1765. }
  1766. final void isReadOnly(boolean value) {
  1767. flags = (short) (value ? flags | READONLY : flags & ~READONLY);
  1768. }
  1769. final boolean needsSyncData() {
  1770. return (flags & SYNCDATA) != 0;
  1771. }
  1772. final void needsSyncData(boolean value) {
  1773. flags = (short) (value ? flags | SYNCDATA : flags & ~SYNCDATA);
  1774. }
  1775. final boolean needsSyncChildren() {
  1776. return (flags & SYNCCHILDREN) != 0;
  1777. }
  1778. public final void needsSyncChildren(boolean value) {
  1779. flags = (short) (value ? flags | SYNCCHILDREN : flags & ~SYNCCHILDREN);
  1780. }
  1781. final boolean isOwned() {
  1782. return (flags & OWNED) != 0;
  1783. }
  1784. final void isOwned(boolean value) {
  1785. flags = (short) (value ? flags | OWNED : flags & ~OWNED);
  1786. }
  1787. final boolean isFirstChild() {
  1788. return (flags & FIRSTCHILD) != 0;
  1789. }
  1790. final void isFirstChild(boolean value) {
  1791. flags = (short) (value ? flags | FIRSTCHILD : flags & ~FIRSTCHILD);
  1792. }
  1793. final boolean isSpecified() {
  1794. return (flags & SPECIFIED) != 0;
  1795. }
  1796. final void isSpecified(boolean value) {
  1797. flags = (short) (value ? flags | SPECIFIED : flags & ~SPECIFIED);
  1798. }
  1799. // inconsistent name to avoid clash with public method on TextImpl
  1800. final boolean internalIsIgnorableWhitespace() {
  1801. return (flags & IGNORABLEWS) != 0;
  1802. }
  1803. final void isIgnorableWhitespace(boolean value) {
  1804. flags = (short) (value ? flags | IGNORABLEWS : flags & ~IGNORABLEWS);
  1805. }
  1806. final boolean hasStringValue() {
  1807. return (flags & HASSTRING) != 0;
  1808. }
  1809. final void hasStringValue(boolean value) {
  1810. flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
  1811. }
  1812. final boolean isNormalized() {
  1813. return (flags & NORMALIZED) != 0;
  1814. }
  1815. final void isNormalized(boolean value) {
  1816. // See if flag should propagate to parent.
  1817. if (!value && isNormalized() && ownerNode != null) {
  1818. ownerNode.isNormalized(false);
  1819. }
  1820. flags = (short) (value ? flags | NORMALIZED : flags & ~NORMALIZED);
  1821. }
  1822. final boolean isIdAttribute() {
  1823. return (flags & ID) != 0;
  1824. }
  1825. final void isIdAttribute(boolean value) {
  1826. flags = (short) (value ? flags | ID : flags & ~ID);
  1827. }
  1828. //
  1829. // Object methods
  1830. //
  1831. /** NON-DOM method for debugging convenience. */
  1832. public String toString() {
  1833. return "["+getNodeName()+": "+getNodeValue()+"]";
  1834. }
  1835. //
  1836. // Serialization methods
  1837. //
  1838. /** Serialize object. */
  1839. private void writeObject(ObjectOutputStream out) throws IOException {
  1840. // synchronize data
  1841. if (needsSyncData()) {
  1842. synchronizeData();
  1843. }
  1844. // write object
  1845. out.defaultWriteObject();
  1846. } // writeObject(ObjectOutputStream)
  1847. } // class NodeImpl