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