1 55 56 package org.xquark.xpath.datamodel.xerces.dom; 57 58 import java.util.Vector ; 59 60 import org.w3c.dom.*; 61 import org.w3c.dom.ranges.Range; 62 import org.w3c.dom.ranges.RangeException; 63 64 68 public class RangeImpl implements Range { 69 70 74 75 79 DocumentImpl fDocument; 80 Node fStartContainer; 81 Node fEndContainer; 82 int fStartOffset; 83 int fEndOffset; 84 boolean fIsCollapsed; 85 boolean fDetach = false; 86 Node fInsertNode = null; 87 Node fDeleteNode = null; 88 Node fSplitNode = null; 89 90 91 95 public RangeImpl(DocumentImpl document) { 96 fDocument = document; 97 fStartContainer = document; 98 fEndContainer = document; 99 fStartOffset = 0; 100 fEndOffset = 0; 101 fDetach = false; 102 } 103 104 public Node getStartContainer() { 105 return fStartContainer; 106 } 107 108 public int getStartOffset() { 109 return fStartOffset; 110 } 111 112 public Node getEndContainer() { 113 return fEndContainer; 114 } 115 public int getEndOffset() { 116 return fEndOffset; 117 } 118 119 public boolean getCollapsed() { 120 return (fStartContainer == fEndContainer 121 && fStartOffset == fEndOffset); 122 } 123 124 public Node getCommonAncestorContainer(){ 125 Vector startV = new Vector (); 126 Node node; 127 for (node=fStartContainer; node != null; 128 node=node.getParentNode()) 129 { 130 startV.addElement(node); 131 } 132 Vector endV = new Vector (); 133 for (node=fEndContainer; node != null; 134 node=node.getParentNode()) 135 { 136 endV.addElement(node); 137 } 138 int s = startV.size()-1; 139 int e = endV.size()-1; 140 Object result = null; 141 while (s>=0 && e>=0) { 142 if (startV.elementAt(s) == endV.elementAt(e)) { 143 result = startV.elementAt(s); 144 } else { 145 break; 146 } 147 --s; 148 --e; 149 } 150 return (Node)result; 151 } 152 153 154 public void setStart(Node refNode, int offset) 155 throws RangeException, DOMException 156 { 157 if( fDetach) { 158 throw new DOMException( 159 DOMException.INVALID_STATE_ERR, 160 "DOM011 Invalid state"); 161 } 162 if ( !isLegalContainer(refNode)) { 163 throw new RangeExceptionImpl( 164 RangeException.INVALID_NODE_TYPE_ERR, 165 "DOM012 Invalid node type"); 166 } 167 168 checkIndex(refNode, offset); 169 170 fStartContainer = refNode; 171 fStartOffset = offset; 172 } 173 174 public void setEnd(Node refNode, int offset) 175 throws RangeException, DOMException 176 { 177 if( fDetach) { 178 throw new DOMException( 179 DOMException.INVALID_STATE_ERR, 180 "DOM011 Invalid state"); 181 } 182 if ( !isLegalContainer(refNode)) { 183 throw new RangeExceptionImpl( 184 RangeException.INVALID_NODE_TYPE_ERR, 185 "DOM012 Invalid node type"); 186 } 187 188 checkIndex(refNode, offset); 189 190 fEndContainer = refNode; 191 fEndOffset = offset; 192 } 193 public void setStartBefore(Node refNode) 194 throws RangeException 195 { 196 if( fDetach) { 197 throw new DOMException( 198 DOMException.INVALID_STATE_ERR, 199 "DOM011 Invalid state"); 200 } 201 if ( !hasLegalRootContainer(refNode) || 202 !isLegalContainedNode(refNode) ) 203 { 204 throw new RangeExceptionImpl( 205 RangeException.INVALID_NODE_TYPE_ERR, 206 "DOM012 Invalid node type"); 207 } 208 fStartContainer = refNode.getParentNode(); 209 int i = 0; 210 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 211 i++; 212 } 213 fStartOffset = i-1; 214 } 215 public void setStartAfter(Node refNode) 216 throws RangeException 217 { 218 if( fDetach) { 219 throw new DOMException( 220 DOMException.INVALID_STATE_ERR, 221 "DOM011 Invalid state"); 222 } 223 if ( !hasLegalRootContainer(refNode) || 224 !isLegalContainedNode(refNode)) { 225 throw new RangeExceptionImpl( 226 RangeException.INVALID_NODE_TYPE_ERR, 227 "DOM012 Invalid node type"); 228 } 229 fStartContainer = refNode.getParentNode(); 230 int i = 0; 231 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 232 i++; 233 } 234 fStartOffset = i; 235 } 236 public void setEndBefore(Node refNode) 237 throws RangeException 238 { 239 if( fDetach) { 240 throw new DOMException( 241 DOMException.INVALID_STATE_ERR, 242 "DOM011 Invalid state"); 243 } 244 if ( !hasLegalRootContainer(refNode) || 245 !isLegalContainedNode(refNode)) { 246 throw new RangeExceptionImpl( 247 RangeException.INVALID_NODE_TYPE_ERR, 248 "DOM012 Invalid node type"); 249 } 250 fEndContainer = refNode.getParentNode(); 251 int i = 0; 252 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 253 i++; 254 } 255 fEndOffset = i-1; 256 } 257 258 public void setEndAfter(Node refNode) 259 throws RangeException 260 { 261 if( fDetach) { 262 throw new DOMException( 263 DOMException.INVALID_STATE_ERR, 264 "DOM011 Invalid state"); 265 } 266 if ( !hasLegalRootContainer(refNode) || 267 !isLegalContainedNode(refNode)) { 268 throw new RangeExceptionImpl( 269 RangeException.INVALID_NODE_TYPE_ERR, 270 "DOM012 Invalid node type"); 271 } 272 fEndContainer = refNode.getParentNode(); 273 int i = 0; 274 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 275 i++; 276 } 277 fEndOffset = i; 278 } 279 public void collapse(boolean toStart) { 280 281 if( fDetach) { 282 throw new DOMException( 283 DOMException.INVALID_STATE_ERR, 284 "DOM011 Invalid state"); 285 } 286 287 if (toStart) { 288 fEndContainer = fStartContainer; 289 fEndOffset = fStartOffset; 290 } else { 291 fStartContainer = fEndContainer; 292 fStartOffset = fEndOffset; 293 } 294 } 295 296 public void selectNode(Node refNode) 297 throws RangeException 298 { 299 if( fDetach) { 300 throw new DOMException( 301 DOMException.INVALID_STATE_ERR, 302 "DOM011 Invalid state"); 303 } 304 if ( !isLegalContainer( refNode.getParentNode() ) || 305 !isLegalContainedNode( refNode ) ) { 306 throw new RangeExceptionImpl( 307 RangeException.INVALID_NODE_TYPE_ERR, 308 "DOM012 Invalid node type"); 309 } 310 Node parent = refNode.getParentNode(); 311 if (parent != null ) { 313 fStartContainer = parent; 314 fEndContainer = parent; 315 int i = 0; 316 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 317 i++; 318 } 319 fStartOffset = i-1; 320 fEndOffset = fStartOffset+1; 321 } 322 } 323 324 public void selectNodeContents(Node refNode) 325 throws RangeException 326 { 327 if( fDetach) { 328 throw new DOMException( 329 DOMException.INVALID_STATE_ERR, 330 "DOM011 Invalid state"); 331 } 332 if ( !isLegalContainer(refNode)) { 333 throw new RangeExceptionImpl( 334 RangeException.INVALID_NODE_TYPE_ERR, 335 "DOM012 Invalid node type"); 336 } 337 fStartContainer = refNode; 338 fEndContainer = refNode; 339 Node first = refNode.getFirstChild(); 340 fStartOffset = 0; 341 if (first == null) { 342 fEndOffset = 0; 343 } else { 344 int i = 0; 345 for (Node n = first; n!=null; n = n.getNextSibling()) { 346 i++; 347 } 348 fEndOffset = i; 349 } 350 351 } 352 353 public short compareBoundaryPoints(short how, Range sourceRange) 354 throws DOMException 355 { 356 if( fDetach) { 357 throw new DOMException( 358 DOMException.INVALID_STATE_ERR, 359 "DOM011 Invalid state"); 360 } 361 362 Node endPointA; 363 Node endPointB; 364 int offsetA; 365 int offsetB; 366 367 if (how == START_TO_START) { 368 endPointA = sourceRange.getStartContainer(); 369 endPointB = fStartContainer; 370 offsetA = sourceRange.getStartOffset(); 371 offsetB = fStartOffset; 372 } else 373 if (how == START_TO_END) { 374 endPointA = sourceRange.getStartContainer(); 375 endPointB = fEndContainer; 376 offsetA = sourceRange.getStartOffset(); 377 offsetB = fEndOffset; 378 } else 379 if (how == END_TO_START) { 380 endPointA = sourceRange.getEndContainer(); 381 endPointB = fStartContainer; 382 offsetA = sourceRange.getEndOffset(); 383 offsetB = fStartOffset; 384 } else { 385 endPointA = sourceRange.getEndContainer(); 386 endPointB = fEndContainer; 387 offsetA = sourceRange.getEndOffset(); 388 offsetB = fEndOffset; 389 } 390 391 398 if (endPointA == endPointB) { 400 if (offsetA < offsetB) return 1; 401 if (offsetA == offsetB) return 0; 402 return -1; 403 } 404 for ( Node c = endPointB, p = c.getParentNode(); 407 p != null; 408 c = p, p = p.getParentNode()) 409 { 410 if (p == endPointA) { 411 int index = indexOf(c, endPointA); 412 if (offsetA <= index) return 1; 413 return -1; 414 } 415 } 416 417 for ( Node c = endPointA, p = c.getParentNode(); 420 p != null; 421 c = p, p = p.getParentNode()) 422 { 423 if (p == endPointB) { 424 int index = indexOf(c, endPointB); 425 if (index < offsetB) return 1; 426 return -1; 427 } 428 } 429 430 434 int depthDiff = 0; 435 for ( Node n = endPointA; n != null; n = n.getParentNode() ) 436 depthDiff++; 437 for ( Node n = endPointB; n != null; n = n.getParentNode() ) 438 depthDiff--; 439 while (depthDiff > 0) { 440 endPointA = endPointA.getParentNode(); 441 depthDiff--; 442 } 443 while (depthDiff < 0) { 444 endPointB = endPointB.getParentNode(); 445 depthDiff++; 446 } 447 for (Node pA = endPointA.getParentNode(), 448 pB = endPointB.getParentNode(); 449 pA != pB; 450 pA = pA.getParentNode(), pB = pB.getParentNode() ) 451 { 452 endPointA = pA; 453 endPointB = pB; 454 } 455 for ( Node n = endPointA.getNextSibling(); 456 n != null; 457 n = n.getNextSibling() ) 458 { 459 if (n == endPointB) { 460 return 1; 461 } 462 } 463 return -1; 464 } 465 466 public void deleteContents() 467 throws DOMException 468 { 469 traverseContents(DELETE_CONTENTS); 470 } 471 472 public DocumentFragment extractContents() 473 throws DOMException 474 { 475 return traverseContents(EXTRACT_CONTENTS); 476 } 477 478 public DocumentFragment cloneContents() 479 throws DOMException 480 { 481 return traverseContents(CLONE_CONTENTS); 482 } 483 484 public void insertNode(Node newNode) 485 throws DOMException, RangeException 486 { 487 if ( newNode == null ) return; 489 if( fDetach) { 490 throw new DOMException( 491 DOMException.INVALID_STATE_ERR, 492 "DOM011 Invalid state"); 493 } 494 if ( fDocument != newNode.getOwnerDocument() ) { 495 throw new DOMException(DOMException.WRONG_DOCUMENT_ERR,"DOM004 Wrong document"); 496 } 497 498 int type = newNode.getNodeType(); 499 if (type == Node.ATTRIBUTE_NODE 500 || type == Node.ENTITY_NODE 501 || type == Node.NOTATION_NODE 502 || type == Node.DOCUMENT_NODE) 503 { 504 throw new RangeExceptionImpl( 505 RangeException.INVALID_NODE_TYPE_ERR, 506 "DOM012 Invalid node type"); 507 } 508 Node cloneCurrent; 509 Node current; 510 int currentChildren = 0; 511 512 if (fStartContainer.getNodeType() == Node.TEXT_NODE) { 514 515 Node parent = fStartContainer.getParentNode(); 516 currentChildren = parent.getChildNodes().getLength(); cloneCurrent = fStartContainer.cloneNode(false); 519 ((TextImpl)cloneCurrent).setNodeValueInternal( 520 (cloneCurrent.getNodeValue()).substring(fStartOffset)); 521 ((TextImpl)fStartContainer).setNodeValueInternal( 522 (fStartContainer.getNodeValue()).substring(0,fStartOffset)); 523 Node next = fStartContainer.getNextSibling(); 524 if (next != null) { 525 if (parent != null) { 526 parent.insertBefore(newNode, next); 527 parent.insertBefore(cloneCurrent, next); 528 } 529 } else { 530 if (parent != null) { 531 parent.appendChild(newNode); 532 parent.appendChild(cloneCurrent); 533 } 534 } 535 if ( fEndContainer == fStartContainer) { 537 fEndContainer = cloneCurrent; fEndOffset -= fStartOffset; 539 } 540 else if ( fEndContainer == parent ) { fEndOffset += (parent.getChildNodes().getLength() - currentChildren); 543 } 544 545 signalSplitData(fStartContainer, cloneCurrent, fStartOffset); 547 548 549 } else { if ( fEndContainer == fStartContainer ) currentChildren= fEndContainer.getChildNodes().getLength(); 552 553 current = fStartContainer.getFirstChild(); 554 int i = 0; 555 for(i = 0; i < fStartOffset && current != null; i++) { 556 current=current.getNextSibling(); 557 } 558 if (current != null) { 559 fStartContainer.insertBefore(newNode, current); 560 } else { 561 fStartContainer.appendChild(newNode); 562 } 563 if ( fEndContainer == fStartContainer ) { fEndOffset += (fEndContainer.getChildNodes().getLength() - currentChildren); 567 } 568 569 } 570 } 571 572 public void surroundContents(Node newParent) 573 throws DOMException, RangeException 574 { 575 if (newParent==null) return; 576 577 if( fDetach) { 578 throw new DOMException( 579 DOMException.INVALID_STATE_ERR, 580 "DOM011 Invalid state"); 581 } 582 int type = newParent.getNodeType(); 583 if (type == Node.ATTRIBUTE_NODE 584 || type == Node.ENTITY_NODE 585 || type == Node.NOTATION_NODE 586 || type == Node.DOCUMENT_TYPE_NODE 587 || type == Node.DOCUMENT_NODE 588 || type == Node.DOCUMENT_FRAGMENT_NODE) 589 { 590 throw new RangeExceptionImpl( 591 RangeException.INVALID_NODE_TYPE_ERR, 592 "DOM012 Invalid node type"); 593 } 594 595 598 Node realStart = fStartContainer; 599 Node realEnd = fEndContainer; 600 if (fStartContainer.getNodeType() == Node.TEXT_NODE) { 601 realStart = fStartContainer.getParentNode(); 602 } 603 if (fEndContainer.getNodeType() == Node.TEXT_NODE) { 604 realEnd = fEndContainer.getParentNode(); 605 } 606 607 if (realStart != realEnd) { 608 throw new RangeExceptionImpl( 609 RangeException.BAD_BOUNDARYPOINTS_ERR, 610 "DOM013 Bad boundary points"); 611 } 612 613 DocumentFragment frag = extractContents(); 614 insertNode(newParent); 615 newParent.appendChild(frag); 616 selectNode(newParent); 617 } 618 619 public Range cloneRange(){ 620 if( fDetach) { 621 throw new DOMException( 622 DOMException.INVALID_STATE_ERR, 623 "DOM011 Invalid state"); 624 } 625 626 Range range = fDocument.createRange(); 627 range.setStart(fStartContainer, fStartOffset); 628 range.setEnd(fEndContainer, fEndOffset); 629 return range; 630 } 631 632 public String toString(){ 633 if( fDetach) { 634 throw new DOMException( 635 DOMException.INVALID_STATE_ERR, 636 "DOM011 Invalid state"); 637 } 638 639 Node node = fStartContainer; 640 Node stopNode = fEndContainer; 641 StringBuffer sb = new StringBuffer (); 642 if (fStartContainer.getNodeType() == Node.TEXT_NODE 643 || fStartContainer.getNodeType() == Node.CDATA_SECTION_NODE 644 ) { 645 if (fStartContainer == fEndContainer) { 646 sb.append(fStartContainer.getNodeValue().substring(fStartOffset, fEndOffset)); 647 return sb.toString(); 648 } 649 sb.append(fStartContainer.getNodeValue().substring(fStartOffset)); 650 node=nextNode (node,true); 652 } 653 else { node=node.getFirstChild(); 655 if (fStartOffset>0) { int counter=0; 657 while (counter<fStartOffset && node!=null) { 658 node=node.getNextSibling(); 659 counter++; 660 } 661 } 662 if (node == null) { 663 node = nextNode(fStartContainer,false); 664 } 665 } 666 if ( fEndContainer.getNodeType()!= Node.TEXT_NODE && 667 fEndContainer.getNodeType()!= Node.CDATA_SECTION_NODE ){ 668 int i=fEndOffset; 669 stopNode = fEndContainer.getFirstChild(); 670 while( i>0 && stopNode!=null ){ 671 --i; 672 stopNode = stopNode.getNextSibling(); 673 } 674 if ( stopNode == null ) 675 stopNode = nextNode( fEndContainer, false ); 676 } 677 while (node != stopNode) { if (node == null) break; 679 if (node.getNodeType() == Node.TEXT_NODE 680 || node.getNodeType() == Node.CDATA_SECTION_NODE) { 681 sb.append(node.getNodeValue()); 682 } 683 684 node = nextNode(node, true); 685 } 686 687 if (fEndContainer.getNodeType() == Node.TEXT_NODE 688 || fEndContainer.getNodeType() == Node.CDATA_SECTION_NODE) { 689 sb.append(fEndContainer.getNodeValue().substring(0,fEndOffset)); 690 } 691 return sb.toString(); 692 } 693 694 public void detach() { 695 fDetach = true; 696 fDocument.removeRange(this); 697 } 698 699 703 707 void signalSplitData(Node node, Node newNode, int offset) { 708 fSplitNode = node; 709 fDocument.splitData(node, newNode, offset); 711 fSplitNode = null; 712 } 713 714 717 void receiveSplitData(Node node, Node newNode, int offset) { 718 if (node == null || newNode == null) return; 719 if (fSplitNode == node) return; 720 721 if (node == fStartContainer 722 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 723 if (fStartOffset > offset) { 724 fStartOffset = fStartOffset - offset; 725 fStartContainer = newNode; 726 } 727 } 728 if (node == fEndContainer 729 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 730 if (fEndOffset > offset) { 731 fEndOffset = fEndOffset-offset; 732 fEndContainer = newNode; 733 } 734 } 735 736 } 737 738 741 void deleteData(CharacterData node, int offset, int count) { 742 fDeleteNode = node; 743 node.deleteData( offset, count); 744 fDeleteNode = null; 745 } 746 747 748 752 void receiveDeletedText(Node node, int offset, int count) { 753 if (node == null) return; 754 if (fDeleteNode == node) return; 755 if (node == fStartContainer 756 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 757 if (fStartOffset > offset+count) { 758 fStartOffset = offset+(fStartOffset-(offset+count)); 759 } else 760 if (fStartOffset > offset) { 761 fStartOffset = offset; 762 } 763 } 764 if (node == fEndContainer 765 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 766 if (fEndOffset > offset+count) { 767 fEndOffset = offset+(fEndOffset-(offset+count)); 768 } else 769 if (fEndOffset > offset) { 770 fEndOffset = offset; 771 } 772 } 773 774 } 775 776 779 void insertData(CharacterData node, int index, String insert) { 780 fInsertNode = node; 781 node.insertData( index, insert); 782 fInsertNode = null; 783 } 784 785 786 790 void receiveInsertedText(Node node, int index, int len) { 791 if (node == null) return; 792 if (fInsertNode == node) return; 793 if (node == fStartContainer 794 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 795 if (index < fStartOffset) { 796 fStartOffset = fStartOffset+len; 797 } 798 } 799 if (node == fEndContainer 800 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 801 if (index < fEndOffset) { 802 fEndOffset = fEndOffset+len; 803 } 804 } 805 806 } 807 808 812 void receiveReplacedText(Node node) { 813 if (node == null) return; 814 if (node == fStartContainer 815 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 816 fStartOffset = 0; 817 } 818 if (node == fEndContainer 819 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 820 fEndOffset = 0; 821 } 822 823 } 824 825 829 public void insertedNodeFromDOM(Node node) { 830 if (node == null) return; 831 if (fInsertNode == node) return; 832 833 Node parent = node.getParentNode(); 834 835 if (parent == fStartContainer) { 836 int index = indexOf(node, fStartContainer); 837 if (index < fStartOffset) { 838 fStartOffset++; 839 } 840 } 841 842 if (parent == fEndContainer) { 843 int index = indexOf(node, fEndContainer); 844 if (index < fEndOffset) { 845 fEndOffset++; 846 } 847 } 848 849 } 850 851 856 857 Node fRemoveChild = null; 858 Node removeChild(Node parent, Node child) { 859 fRemoveChild = child; 860 Node n = parent.removeChild(child); 861 fRemoveChild = null; 862 return n; 863 } 864 865 869 void removeNode(Node node) { 870 if (node == null) return; 871 if (fRemoveChild == node) return; 872 873 Node parent = node.getParentNode(); 874 875 if (parent == fStartContainer) { 876 int index = indexOf(node, fStartContainer); 877 if (index < fStartOffset) { 878 fStartOffset--; 879 } 880 } 881 882 if (parent == fEndContainer) { 883 int index = indexOf(node, fEndContainer); 884 if (index < fEndOffset) { 885 fEndOffset--; 886 } 887 } 888 if (parent != fStartContainer 890 || parent != fEndContainer) { 891 if (isAncestorOf(node, fStartContainer)) { 892 fStartContainer = parent; 893 fStartOffset = indexOf( node, parent); 894 } 895 if (isAncestorOf(node, fEndContainer)) { 896 fEndContainer = parent; 897 fEndOffset = indexOf( node, parent); 898 } 899 } 900 901 } 902 903 907 static final int EXTRACT_CONTENTS = 1; 910 static final int CLONE_CONTENTS = 2; 911 static final int DELETE_CONTENTS = 3; 912 913 943 private DocumentFragment traverseContents( int how ) 944 throws DOMException 945 { 946 if (fStartContainer == null || fEndContainer == null) { 947 return null; } 949 950 if( fDetach) { 952 throw new DOMException( 953 DOMException.INVALID_STATE_ERR, 954 "DOM011 Invalid state"); 955 } 956 957 964 965 if ( fStartContainer == fEndContainer ) 967 return traverseSameContainer( how ); 968 969 970 int endContainerDepth = 0; 974 for ( Node c = fEndContainer, p = c.getParentNode(); 975 p != null; 976 c = p, p = p.getParentNode()) 977 { 978 if (p == fStartContainer) 979 return traverseCommonStartContainer( c, how ); 980 ++endContainerDepth; 981 } 982 983 int startContainerDepth = 0; 986 for ( Node c = fStartContainer, p = c.getParentNode(); 987 p != null; 988 c = p, p = p.getParentNode()) 989 { 990 if (p == fEndContainer) 991 return traverseCommonEndContainer( c, how ); 992 ++startContainerDepth; 993 } 994 995 int depthDiff = startContainerDepth - endContainerDepth; 998 999 Node startNode = fStartContainer; 1000 while (depthDiff > 0) { 1001 startNode = startNode.getParentNode(); 1002 depthDiff--; 1003 } 1004 1005 Node endNode = fEndContainer; 1006 while (depthDiff < 0) { 1007 endNode = endNode.getParentNode(); 1008 depthDiff++; 1009 } 1010 1011 for( Node sp = startNode.getParentNode(), ep = endNode.getParentNode(); 1013 sp!=ep; 1014 sp = sp.getParentNode(), ep = ep.getParentNode() ) 1015 { 1016 startNode = sp; 1017 endNode = ep; 1018 } 1019 return traverseCommonAncestors( startNode, endNode, how ); 1020 } 1021 1022 1052 private DocumentFragment traverseSameContainer( int how ) 1053 { 1054 DocumentFragment frag = null; 1055 if ( how!=DELETE_CONTENTS) 1056 frag = fDocument.createDocumentFragment(); 1057 1058 if ( fStartOffset==fEndOffset ) 1060 return frag; 1061 1062 if ( fStartContainer.getNodeType()==Node.TEXT_NODE ) 1064 { 1065 String s = fStartContainer.getNodeValue(); 1067 String sub = s.substring( fStartOffset, fEndOffset ); 1068 1069 if ( how != CLONE_CONTENTS ) 1071 { 1072 fStartContainer.setNodeValue( 1073 s.substring(0, fStartOffset ) + 1074 s.substring(fEndOffset) 1075 ); 1076 1077 collapse( true ); 1079 } 1080 if ( how==DELETE_CONTENTS) 1081 return null; 1082 frag.appendChild( fDocument.createTextNode(sub) ); 1083 return frag; 1084 } 1085 1086 Node n = getSelectedNode( fStartContainer, fStartOffset ); 1088 int cnt = fEndOffset - fStartOffset; 1089 while( cnt > 0 ) 1090 { 1091 Node sibling = n.getNextSibling(); 1092 Node xferNode = traverseFullySelected( n, how ); 1093 if ( frag!=null ) 1094 frag.appendChild( xferNode ); 1095 --cnt; 1096 n = sibling; 1097 } 1098 1099 if ( how != CLONE_CONTENTS ) 1101 collapse( true ); 1102 return frag; 1103 } 1104 1105 1140 private DocumentFragment 1141 traverseCommonStartContainer( Node endAncestor, int how ) 1142 { 1143 DocumentFragment frag = null; 1144 if ( how!=DELETE_CONTENTS) 1145 frag = fDocument.createDocumentFragment(); 1146 Node n = traverseRightBoundary( endAncestor, how ); 1147 if ( frag!=null ) 1148 frag.appendChild( n ); 1149 1150 int endIdx = indexOf( endAncestor, fStartContainer ); 1151 int cnt = endIdx - fStartOffset; 1152 if ( cnt <=0 ) 1153 { 1154 if ( how != CLONE_CONTENTS ) 1157 { 1158 setEndBefore( endAncestor ); 1159 collapse( false ); 1160 } 1161 return frag; 1162 } 1163 1164 n = endAncestor.getPreviousSibling(); 1165 while( cnt > 0 ) 1166 { 1167 Node sibling = n.getPreviousSibling(); 1168 Node xferNode = traverseFullySelected( n, how ); 1169 if ( frag!=null ) 1170 frag.insertBefore( xferNode, frag.getFirstChild() ); 1171 --cnt; 1172 n = sibling; 1173 } 1174 if ( how != CLONE_CONTENTS ) 1177 { 1178 setEndBefore( endAncestor ); 1179 collapse( false ); 1180 } 1181 return frag; 1182 } 1183 1184 1219 private DocumentFragment 1220 traverseCommonEndContainer( Node startAncestor, int how ) 1221 { 1222 DocumentFragment frag = null; 1223 if ( how!=DELETE_CONTENTS) 1224 frag = fDocument.createDocumentFragment(); 1225 Node n = traverseLeftBoundary( startAncestor, how ); 1226 if ( frag!=null ) 1227 frag.appendChild( n ); 1228 int startIdx = indexOf( startAncestor, fEndContainer ); 1229 ++startIdx; 1231 int cnt = fEndOffset - startIdx; 1232 n = startAncestor.getNextSibling(); 1233 while( cnt > 0 ) 1234 { 1235 Node sibling = n.getNextSibling(); 1236 Node xferNode = traverseFullySelected( n, how ); 1237 if ( frag!=null ) 1238 frag.appendChild( xferNode ); 1239 --cnt; 1240 n = sibling; 1241 } 1242 1243 if ( how != CLONE_CONTENTS ) 1244 { 1245 setStartAfter( startAncestor ); 1246 collapse( true ); 1247 } 1248 1249 return frag; 1250 } 1251 1252 1294 private DocumentFragment 1295 traverseCommonAncestors( Node startAncestor, Node endAncestor, int how ) 1296 { 1297 DocumentFragment frag = null; 1298 if ( how!=DELETE_CONTENTS) 1299 frag = fDocument.createDocumentFragment(); 1300 1301 Node n = traverseLeftBoundary( startAncestor, how ); 1302 if ( frag!=null ) 1303 frag.appendChild( n ); 1304 1305 Node commonParent = startAncestor.getParentNode(); 1306 int startOffset = indexOf( startAncestor, commonParent ); 1307 int endOffset = indexOf( endAncestor, commonParent ); 1308 ++startOffset; 1309 1310 int cnt = endOffset - startOffset; 1311 Node sibling = startAncestor.getNextSibling(); 1312 1313 while( cnt > 0 ) 1314 { 1315 Node nextSibling = sibling.getNextSibling(); 1316 n = traverseFullySelected( sibling, how ); 1317 if ( frag!=null ) 1318 frag.appendChild( n ); 1319 sibling = nextSibling; 1320 --cnt; 1321 } 1322 1323 n = traverseRightBoundary( endAncestor, how ); 1324 if ( frag!=null ) 1325 frag.appendChild( n ); 1326 1327 if ( how != CLONE_CONTENTS ) 1328 { 1329 setStartAfter( startAncestor ); 1330 collapse( true ); 1331 } 1332 return frag; 1333 } 1334 1335 1393 private Node traverseRightBoundary( Node root, int how ) 1394 { 1395 Node next = getSelectedNode( fEndContainer, fEndOffset-1 ); 1396 boolean isFullySelected = ( next!=fEndContainer ); 1397 1398 if ( next==root ) 1399 return traverseNode( next, isFullySelected, false, how ); 1400 1401 Node parent = next.getParentNode(); 1402 Node clonedParent = traverseNode( parent, false, false, how ); 1403 1404 while( parent!=null ) 1405 { 1406 while( next!=null ) 1407 { 1408 Node prevSibling = next.getPreviousSibling(); 1409 Node clonedChild = 1410 traverseNode( next, isFullySelected, false, how ); 1411 if ( how!=DELETE_CONTENTS ) 1412 { 1413 clonedParent.insertBefore( 1414 clonedChild, 1415 clonedParent.getFirstChild() 1416 ); 1417 } 1418 isFullySelected = true; 1419 next = prevSibling; 1420 } 1421 if ( parent==root ) 1422 return clonedParent; 1423 1424 next = parent.getPreviousSibling(); 1425 parent = parent.getParentNode(); 1426 Node clonedGrandParent = traverseNode( parent, false, false, how ); 1427 if ( how!=DELETE_CONTENTS ) 1428 clonedGrandParent.appendChild( clonedParent ); 1429 clonedParent = clonedGrandParent; 1430 1431 } 1432 1433 return null; 1435 } 1436 1437 1496 private Node traverseLeftBoundary( Node root, int how ) 1497 { 1498 Node next = getSelectedNode( getStartContainer(), getStartOffset() ); 1499 boolean isFullySelected = ( next!=getStartContainer() ); 1500 1501 if ( next==root ) 1502 return traverseNode( next, isFullySelected, true, how ); 1503 1504 Node parent = next.getParentNode(); 1505 Node clonedParent = traverseNode( parent, false, true, how ); 1506 1507 while( parent!=null ) 1508 { 1509 while( next!=null ) 1510 { 1511 Node nextSibling = next.getNextSibling(); 1512 Node clonedChild = 1513 traverseNode( next, isFullySelected, true, how ); 1514 if ( how!=DELETE_CONTENTS ) 1515 clonedParent.appendChild(clonedChild); 1516 isFullySelected = true; 1517 next = nextSibling; 1518 } 1519 if ( parent==root ) 1520 return clonedParent; 1521 1522 next = parent.getNextSibling(); 1523 parent = parent.getParentNode(); 1524 Node clonedGrandParent = traverseNode( parent, false, true, how ); 1525 if ( how!=DELETE_CONTENTS ) 1526 clonedGrandParent.appendChild( clonedParent ); 1527 clonedParent = clonedGrandParent; 1528 1529 } 1530 1531 return null; 1533 1534 } 1535 1536 1577 private Node traverseNode( Node n, boolean isFullySelected, boolean isLeft, int how ) 1578 { 1579 if ( isFullySelected ) 1580 return traverseFullySelected( n, how ); 1581 if ( n.getNodeType()==Node.TEXT_NODE ) 1582 return traverseTextNode( n, isLeft, how ); 1583 return traversePartiallySelected( n, how ); 1584 } 1585 1586 1613 private Node traverseFullySelected( Node n, int how ) 1614 { 1615 switch( how ) 1616 { 1617 case CLONE_CONTENTS: 1618 return n.cloneNode( true ); 1619 case EXTRACT_CONTENTS: 1620 if ( n.getNodeType()==Node.DOCUMENT_TYPE_NODE ) 1621 { 1622 throw new RangeExceptionImpl( 1624 RangeException.INVALID_NODE_TYPE_ERR, 1625 "DOM012 Invalid node type"); 1626 } 1627 return n; 1628 case DELETE_CONTENTS: 1629 n.getParentNode().removeChild(n); 1630 return null; 1631 } 1632 return null; 1633 } 1634 1635 1662 private Node traversePartiallySelected( Node n, int how ) 1663 { 1664 switch( how ) 1665 { 1666 case DELETE_CONTENTS: 1667 return null; 1668 case CLONE_CONTENTS: 1669 case EXTRACT_CONTENTS: 1670 return n.cloneNode( false ); 1671 } 1672 return null; 1673 } 1674 1675 1708 private Node traverseTextNode( Node n, boolean isLeft, int how ) 1709 { 1710 String txtValue = n.getNodeValue(); 1711 String newNodeValue; 1712 String oldNodeValue; 1713 1714 if ( isLeft ) 1715 { 1716 int offset = getStartOffset(); 1717 newNodeValue = txtValue.substring( offset ); 1718 oldNodeValue = txtValue.substring( 0, offset ); 1719 } 1720 else 1721 { 1722 int offset = getEndOffset(); 1723 newNodeValue = txtValue.substring( 0, offset ); 1724 oldNodeValue = txtValue.substring( offset ); 1725 } 1726 1727 if ( how != CLONE_CONTENTS ) 1728 n.setNodeValue( oldNodeValue ); 1729 if ( how==DELETE_CONTENTS ) 1730 return null; 1731 Node newNode = n.cloneNode( false ); 1732 newNode.setNodeValue( newNodeValue ); 1733 return newNode; 1734 } 1735 1736 void checkIndex(Node refNode, int offset) throws DOMException 1737 { 1738 if (offset < 0) { 1739 throw new DOMException( 1740 DOMException.INDEX_SIZE_ERR, 1741 "DOM004 Index out of bounds"); 1742 } 1743 1744 int type = refNode.getNodeType(); 1745 1746 if (type == Node.TEXT_NODE 1749 || type == Node.CDATA_SECTION_NODE 1750 || type == Node.COMMENT_NODE 1751 || type == Node.PROCESSING_INSTRUCTION_NODE) { 1752 if (offset > refNode.getNodeValue().length()) { 1753 throw new DOMException(DOMException.INDEX_SIZE_ERR, 1754 "DOM004 Index out of bounds"); 1755 } 1756 } 1757 else { 1758 if (offset > refNode.getChildNodes().getLength()) { 1761 throw new DOMException(DOMException.INDEX_SIZE_ERR, 1762 "DOM004 Index out of bounds"); 1763 } 1764 } 1765 } 1766 1767 1771 private Node getRootContainer( Node node ) 1772 { 1773 if ( node==null ) 1774 return null; 1775 1776 while( node.getParentNode()!=null ) 1777 node = node.getParentNode(); 1778 return node; 1779 } 1780 1781 1785 private boolean isLegalContainer( Node node ) 1786 { 1787 if ( node==null ) 1788 return false; 1789 1790 while( node!=null ) 1791 { 1792 switch( node.getNodeType() ) 1793 { 1794 case Node.ENTITY_NODE: 1795 case Node.NOTATION_NODE: 1796 case Node.DOCUMENT_TYPE_NODE: 1797 return false; 1798 } 1799 node = node.getParentNode(); 1800 } 1801 1802 return true; 1803 } 1804 1805 1806 1813 private boolean hasLegalRootContainer( Node node ) 1814 { 1815 if ( node==null ) 1816 return false; 1817 1818 Node rootContainer = getRootContainer( node ); 1819 switch( rootContainer.getNodeType() ) 1820 { 1821 case Node.ATTRIBUTE_NODE: 1822 case Node.DOCUMENT_NODE: 1823 case Node.DOCUMENT_FRAGMENT_NODE: 1824 return true; 1825 } 1826 return false; 1827 } 1828 1829 1833 private boolean isLegalContainedNode( Node node ) 1834 { 1835 if ( node==null ) 1836 return false; 1837 switch( node.getNodeType() ) 1838 { 1839 case Node.DOCUMENT_NODE: 1840 case Node.DOCUMENT_FRAGMENT_NODE: 1841 case Node.ATTRIBUTE_NODE: 1842 case Node.ENTITY_NODE: 1843 case Node.NOTATION_NODE: 1844 return false; 1845 } 1846 return true; 1847 } 1848 1849 Node nextNode(Node node, boolean visitChildren) { 1850 1851 if (node == null) return null; 1852 1853 Node result; 1854 if (visitChildren) { 1855 result = node.getFirstChild(); 1856 if (result != null) { 1857 return result; 1858 } 1859 } 1860 1861 result = node.getNextSibling(); 1863 if (result != null) { 1864 return result; 1865 } 1866 1867 1868 Node parent = node.getParentNode(); 1870 while (parent != null 1871 && parent != fDocument 1872 ) { 1873 result = parent.getNextSibling(); 1874 if (result != null) { 1875 return result; 1876 } else { 1877 parent = parent.getParentNode(); 1878 } 1879 1880 } 1882 return null; 1884 } 1885 1886 1887 boolean isAncestorOf(Node a, Node b) { 1888 for (Node node=b; node != null; node=node.getParentNode()) { 1889 if (node == a) return true; 1890 } 1891 return false; 1892 } 1893 1894 1895 int indexOf(Node child, Node parent) { 1896 if (child.getParentNode() != parent) return -1; 1897 int i = 0; 1898 for(Node node = parent.getFirstChild(); node!= child; node=node.getNextSibling()) { 1899 i++; 1900 } 1901 return i; 1902 } 1903 1904 1920 private Node getSelectedNode( Node container, int offset ) 1921 { 1922 if ( container.getNodeType() == Node.TEXT_NODE ) 1923 return container; 1924 1925 if ( offset<0 ) 1928 return container; 1929 1930 Node child = container.getFirstChild(); 1931 while( child!=null && offset > 0 ) 1932 { 1933 --offset; 1934 child = child.getNextSibling(); 1935 } 1936 if ( child!=null ) 1937 return child; 1938 return container; 1939 } 1940 1941} 1942 | Popular Tags |