1 16 17 package org.apache.xerces.dom; 18 19 import java.io.Serializable ; 20 import java.io.IOException ; 21 import java.io.ObjectInputStream ; 22 import java.io.ObjectOutputStream ; 23 24 import org.w3c.dom.DOMException ; 25 import org.w3c.dom.Document ; 26 import org.w3c.dom.Node ; 27 import org.w3c.dom.NodeList ; 28 import org.w3c.dom.UserDataHandler ; 29 30 69 public abstract class ParentNode 70 extends ChildNode { 71 72 73 static final long serialVersionUID = 2815829867152120872L; 74 75 76 protected CoreDocumentImpl ownerDocument; 77 78 79 protected ChildNode firstChild = null; 80 81 83 84 protected transient NodeListCache fNodeListCache = null; 85 86 90 94 protected ParentNode(CoreDocumentImpl ownerDocument) { 95 super(ownerDocument); 96 this.ownerDocument = ownerDocument; 97 } 98 99 100 public ParentNode() {} 101 102 106 124 public Node cloneNode(boolean deep) { 125 126 if (needsSyncChildren()) { 127 synchronizeChildren(); 128 } 129 ParentNode newnode = (ParentNode) super.cloneNode(deep); 130 131 newnode.ownerDocument = ownerDocument; 133 134 newnode.firstChild = null; 136 137 newnode.fNodeListCache = null; 139 140 if (deep) { 142 for (ChildNode child = firstChild; 143 child != null; 144 child = child.nextSibling) { 145 newnode.appendChild(child.cloneNode(true)); 146 } 147 } 148 149 return newnode; 150 151 } 153 158 public Document getOwnerDocument() { 159 return ownerDocument; 160 } 161 162 166 CoreDocumentImpl ownerDocument() { 167 return ownerDocument; 168 } 169 170 174 void setOwnerDocument(CoreDocumentImpl doc) { 175 if (needsSyncChildren()) { 176 synchronizeChildren(); 177 } 178 super.setOwnerDocument(doc); 179 ownerDocument = doc; 180 for (ChildNode child = firstChild; 181 child != null; child = child.nextSibling) { 182 child.setOwnerDocument(doc); 183 } 184 } 185 186 190 public boolean hasChildNodes() { 191 if (needsSyncChildren()) { 192 synchronizeChildren(); 193 } 194 return firstChild != null; 195 } 196 197 210 public NodeList getChildNodes() { 211 212 if (needsSyncChildren()) { 213 synchronizeChildren(); 214 } 215 return this; 216 217 } 219 220 public Node getFirstChild() { 221 222 if (needsSyncChildren()) { 223 synchronizeChildren(); 224 } 225 return firstChild; 226 227 } 229 230 public Node getLastChild() { 231 232 if (needsSyncChildren()) { 233 synchronizeChildren(); 234 } 235 return lastChild(); 236 237 } 239 final ChildNode lastChild() { 240 return firstChild != null ? firstChild.previousSibling : null; 242 } 243 244 final void lastChild(ChildNode node) { 245 if (firstChild != null) { 247 firstChild.previousSibling = node; 248 } 249 } 250 251 279 public Node insertBefore(Node newChild, Node refChild) 280 throws DOMException { 281 return internalInsertBefore(newChild, refChild, false); 283 } 285 290 Node internalInsertBefore(Node newChild, Node refChild, boolean replace) 291 throws DOMException { 292 293 boolean errorChecking = ownerDocument.errorChecking; 294 295 if (newChild.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) { 296 303 311 if (errorChecking) { 314 for (Node kid = newChild.getFirstChild(); kid != null; kid = kid.getNextSibling()) { 316 317 if (!ownerDocument.isKidOK(this, kid)) { 318 throw new DOMException ( 319 DOMException.HIERARCHY_REQUEST_ERR, 320 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null)); 321 } 322 } 323 } 324 325 while (newChild.hasChildNodes()) { 326 insertBefore(newChild.getFirstChild(), refChild); 327 } 328 return newChild; 329 } 330 331 if (newChild == refChild) { 332 refChild = refChild.getNextSibling(); 334 removeChild(newChild); 335 insertBefore(newChild, refChild); 336 return newChild; 337 } 338 339 if (needsSyncChildren()) { 340 synchronizeChildren(); 341 } 342 343 if (errorChecking) { 344 if (isReadOnly()) { 345 throw new DOMException ( 346 DOMException.NO_MODIFICATION_ALLOWED_ERR, 347 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null)); 348 } 349 if (newChild.getOwnerDocument() != ownerDocument && newChild != ownerDocument) { 350 throw new DOMException (DOMException.WRONG_DOCUMENT_ERR, 351 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 352 } 353 if (!ownerDocument.isKidOK(this, newChild)) { 354 throw new DOMException (DOMException.HIERARCHY_REQUEST_ERR, 355 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null)); 356 } 357 if (refChild != null && refChild.getParentNode() != this) { 359 throw new DOMException (DOMException.NOT_FOUND_ERR, 360 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null)); 361 } 362 363 boolean treeSafe = true; 367 for (NodeImpl a = this; treeSafe && a != null; a = a.parentNode()) 368 { 369 treeSafe = newChild != a; 370 } 371 if(!treeSafe) { 372 throw new DOMException (DOMException.HIERARCHY_REQUEST_ERR, 373 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null)); 374 } 375 } 376 377 ownerDocument.insertingNode(this, replace); 379 380 ChildNode newInternal = (ChildNode)newChild; 382 383 Node oldparent = newInternal.parentNode(); 384 if (oldparent != null) { 385 oldparent.removeChild(newInternal); 386 } 387 388 ChildNode refInternal = (ChildNode)refChild; 390 391 newInternal.ownerNode = this; 393 newInternal.isOwned(true); 394 395 if (firstChild == null) { 398 firstChild = newInternal; 400 newInternal.isFirstChild(true); 401 newInternal.previousSibling = newInternal; 402 } 403 else { 404 if (refInternal == null) { 405 ChildNode lastChild = firstChild.previousSibling; 407 lastChild.nextSibling = newInternal; 408 newInternal.previousSibling = lastChild; 409 firstChild.previousSibling = newInternal; 410 } 411 else { 412 if (refChild == firstChild) { 414 firstChild.isFirstChild(false); 416 newInternal.nextSibling = firstChild; 417 newInternal.previousSibling = firstChild.previousSibling; 418 firstChild.previousSibling = newInternal; 419 firstChild = newInternal; 420 newInternal.isFirstChild(true); 421 } 422 else { 423 ChildNode prev = refInternal.previousSibling; 425 newInternal.nextSibling = refInternal; 426 prev.nextSibling = newInternal; 427 refInternal.previousSibling = newInternal; 428 newInternal.previousSibling = prev; 429 } 430 } 431 } 432 433 changed(); 434 435 if (fNodeListCache != null) { 437 if (fNodeListCache.fLength != -1) { 438 fNodeListCache.fLength++; 439 } 440 if (fNodeListCache.fChildIndex != -1) { 441 if (fNodeListCache.fChild == refInternal) { 444 fNodeListCache.fChild = newInternal; 445 } else { 446 fNodeListCache.fChildIndex = -1; 448 } 449 } 450 } 451 452 ownerDocument.insertedNode(this, newInternal, replace); 454 455 checkNormalizationAfterInsert(newInternal); 456 457 return newChild; 458 459 } 461 473 public Node removeChild(Node oldChild) 474 throws DOMException { 475 return internalRemoveChild(oldChild, false); 477 } 479 484 Node internalRemoveChild(Node oldChild, boolean replace) 485 throws DOMException { 486 487 CoreDocumentImpl ownerDocument = ownerDocument(); 488 if (ownerDocument.errorChecking) { 489 if (isReadOnly()) { 490 throw new DOMException ( 491 DOMException.NO_MODIFICATION_ALLOWED_ERR, 492 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null)); 493 } 494 if (oldChild != null && oldChild.getParentNode() != this) { 495 throw new DOMException (DOMException.NOT_FOUND_ERR, 496 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null)); 497 } 498 } 499 500 ChildNode oldInternal = (ChildNode) oldChild; 501 502 ownerDocument.removingNode(this, oldInternal, replace); 504 505 if (fNodeListCache != null) { 507 if (fNodeListCache.fLength != -1) { 508 fNodeListCache.fLength--; 509 } 510 if (fNodeListCache.fChildIndex != -1) { 511 if (fNodeListCache.fChild == oldInternal) { 514 fNodeListCache.fChildIndex--; 515 fNodeListCache.fChild = oldInternal.previousSibling(); 516 } else { 517 fNodeListCache.fChildIndex = -1; 519 } 520 } 521 } 522 523 if (oldInternal == firstChild) { 526 oldInternal.isFirstChild(false); 528 firstChild = oldInternal.nextSibling; 529 if (firstChild != null) { 530 firstChild.isFirstChild(true); 531 firstChild.previousSibling = oldInternal.previousSibling; 532 } 533 } else { 534 ChildNode prev = oldInternal.previousSibling; 535 ChildNode next = oldInternal.nextSibling; 536 prev.nextSibling = next; 537 if (next == null) { 538 firstChild.previousSibling = prev; 540 } else { 541 next.previousSibling = prev; 543 } 544 } 545 546 ChildNode oldPreviousSibling = oldInternal.previousSibling(); 548 549 oldInternal.ownerNode = ownerDocument; 551 oldInternal.isOwned(false); 552 oldInternal.nextSibling = null; 553 oldInternal.previousSibling = null; 554 555 changed(); 556 557 ownerDocument.removedNode(this, replace); 559 560 checkNormalizationAfterRemove(oldPreviousSibling); 561 562 return oldInternal; 563 564 } 566 587 public Node replaceChild(Node newChild, Node oldChild) 588 throws DOMException { 589 595 ownerDocument.replacingNode(this); 597 598 internalInsertBefore(newChild, oldChild, true); 599 if (newChild != oldChild) { 600 internalRemoveChild(oldChild, true); 601 } 602 603 ownerDocument.replacedNode(this); 605 606 return oldChild; 607 } 608 609 613 public String getTextContent() throws DOMException { 614 Node child = getFirstChild(); 615 if (child != null) { 616 Node next = child.getNextSibling(); 617 if (next == null) { 618 return hasTextContent(child) ? ((NodeImpl) child).getTextContent() : ""; 619 } 620 if (fBufferStr == null){ 621 fBufferStr = new StringBuffer (); 622 } 623 else { 624 fBufferStr.setLength(0); 625 } 626 getTextContent(fBufferStr); 627 return fBufferStr.toString(); 628 } 629 return ""; 630 } 631 632 void getTextContent(StringBuffer buf) throws DOMException { 634 Node child = getFirstChild(); 635 while (child != null) { 636 if (hasTextContent(child)) { 637 ((NodeImpl) child).getTextContent(buf); 638 } 639 child = child.getNextSibling(); 640 } 641 } 642 643 final boolean hasTextContent(Node child) { 645 return child.getNodeType() != Node.COMMENT_NODE && 646 child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE && 647 (child.getNodeType() != Node.TEXT_NODE || 648 ((TextImpl) child).isIgnorableWhitespace() == false); 649 } 650 651 655 public void setTextContent(String textContent) 656 throws DOMException { 657 Node child; 659 while ((child = getFirstChild()) != null) { 660 removeChild(child); 661 } 662 if (textContent != null && textContent.length() != 0){ 664 appendChild(ownerDocument().createTextNode(textContent)); 665 } 666 } 667 668 672 677 private int nodeListGetLength() { 678 679 if (fNodeListCache == null) { 680 if (firstChild == null) { 682 return 0; 683 } 684 if (firstChild == lastChild()) { 685 return 1; 686 } 687 fNodeListCache = ownerDocument.getNodeListCache(this); 689 } 690 if (fNodeListCache.fLength == -1) { int l; 692 ChildNode n; 693 if (fNodeListCache.fChildIndex != -1 && 695 fNodeListCache.fChild != null) { 696 l = fNodeListCache.fChildIndex; 697 n = fNodeListCache.fChild; 698 } else { 699 n = firstChild; 700 l = 0; 701 } 702 while (n != null) { 703 l++; 704 n = n.nextSibling; 705 } 706 fNodeListCache.fLength = l; 707 } 708 709 return fNodeListCache.fLength; 710 711 } 713 717 public int getLength() { 718 return nodeListGetLength(); 719 } 720 721 726 private Node nodeListItem(int index) { 727 728 if (fNodeListCache == null) { 729 if (firstChild == lastChild()) { 731 return index == 0 ? firstChild : null; 732 } 733 fNodeListCache = ownerDocument.getNodeListCache(this); 735 } 736 int i = fNodeListCache.fChildIndex; 737 ChildNode n = fNodeListCache.fChild; 738 boolean firstAccess = true; 739 if (i != -1 && n != null) { 741 firstAccess = false; 742 if (i < index) { 743 while (i < index && n != null) { 744 i++; 745 n = n.nextSibling; 746 } 747 } 748 else if (i > index) { 749 while (i > index && n != null) { 750 i--; 751 n = n.previousSibling(); 752 } 753 } 754 } 755 else { 756 if (index < 0) { 758 return null; 759 } 760 n = firstChild; 761 for (i = 0; i < index && n != null; i++) { 762 n = n.nextSibling; 763 } 764 } 765 766 if (!firstAccess && (n == firstChild || n == lastChild())) { 768 fNodeListCache.fChildIndex = -1; 769 fNodeListCache.fChild = null; 770 ownerDocument.freeNodeListCache(fNodeListCache); 771 } 776 else { 777 fNodeListCache.fChildIndex = i; 779 fNodeListCache.fChild = n; 780 } 781 return n; 782 783 } 785 791 public Node item(int index) { 792 return nodeListItem(index); 793 } 795 807 protected final NodeList getChildNodesUnoptimized() { 808 if (needsSyncChildren()) { 809 synchronizeChildren(); 810 } 811 return new NodeList () { 812 815 public int getLength() { 816 return nodeListGetLength(); 817 } 819 822 public Node item(int index) { 823 return nodeListItem(index); 824 } }; 826 } 828 832 837 public void normalize() { 838 if (isNormalized()) { 840 return; 841 } 842 if (needsSyncChildren()) { 843 synchronizeChildren(); 844 } 845 ChildNode kid; 846 for (kid = firstChild; kid != null; kid = kid.nextSibling) { 847 kid.normalize(); 848 } 849 isNormalized(true); 850 } 851 852 856 public boolean isEqualNode(Node arg) { 857 if (!super.isEqualNode(arg)) { 858 return false; 859 } 860 Node child1 = getFirstChild(); 864 Node child2 = arg.getFirstChild(); 865 while (child1 != null && child2 != null) { 866 if (!((NodeImpl) child1).isEqualNode(child2)) { 867 return false; 868 } 869 child1 = child1.getNextSibling(); 870 child2 = child2.getNextSibling(); 871 } 872 if (child1 != child2) { 873 return false; 874 } 875 return true; 876 } 877 878 882 890 public void setReadOnly(boolean readOnly, boolean deep) { 891 892 super.setReadOnly(readOnly, deep); 893 894 if (deep) { 895 896 if (needsSyncChildren()) { 897 synchronizeChildren(); 898 } 899 900 for (ChildNode mykid = firstChild; 902 mykid != null; 903 mykid = mykid.nextSibling) { 904 if (mykid.getNodeType() != Node.ENTITY_REFERENCE_NODE) { 905 mykid.setReadOnly(readOnly,true); 906 } 907 } 908 } 909 } 911 915 919 protected void synchronizeChildren() { 920 needsSyncChildren(false); 922 } 923 924 939 void checkNormalizationAfterInsert(ChildNode insertedChild) { 940 if (insertedChild.getNodeType() == Node.TEXT_NODE) { 942 ChildNode prev = insertedChild.previousSibling(); 943 ChildNode next = insertedChild.nextSibling; 944 if ((prev != null && prev.getNodeType() == Node.TEXT_NODE) || 947 (next != null && next.getNodeType() == Node.TEXT_NODE)) { 948 isNormalized(false); 949 } 950 } 951 else { 952 if (!insertedChild.isNormalized()) { 955 isNormalized(false); 956 } 957 } 958 } 960 972 void checkNormalizationAfterRemove(ChildNode previousSibling) { 973 if (previousSibling != null && 977 previousSibling.getNodeType() == Node.TEXT_NODE) { 978 979 ChildNode next = previousSibling.nextSibling; 980 if (next != null && next.getNodeType() == Node.TEXT_NODE) { 981 isNormalized(false); 982 } 983 } 984 } 986 990 991 private void writeObject(ObjectOutputStream out) throws IOException { 992 993 if (needsSyncChildren()) { 995 synchronizeChildren(); 996 } 997 out.defaultWriteObject(); 999 1000 } 1002 1003 private void readObject(ObjectInputStream ois) 1004 throws ClassNotFoundException , IOException { 1005 1006 ois.defaultReadObject(); 1008 1009 needsSyncChildren(false); 1012 1013 } 1015 1018 class UserDataRecord implements Serializable { 1019 1020 private static final long serialVersionUID = 3258126977134310455L; 1021 1022 Object fData; 1023 UserDataHandler fHandler; 1024 UserDataRecord(Object data, UserDataHandler handler) { 1025 fData = data; 1026 fHandler = handler; 1027 } 1028 } 1029} | Popular Tags |