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