1 57 58 package com.sun.org.apache.xerces.internal.dom; 59 60 import java.util.Vector ; 61 62 import org.w3c.dom.CharacterData ; 63 import org.w3c.dom.DOMException ; 64 import org.w3c.dom.DocumentFragment ; 65 import org.w3c.dom.Node ; 66 import org.w3c.dom.ranges.Range; 67 import org.w3c.dom.ranges.RangeException; 68 69 70 76 public class RangeImpl implements Range { 77 78 82 83 87 DocumentImpl fDocument; 88 Node fStartContainer; 89 Node fEndContainer; 90 int fStartOffset; 91 int fEndOffset; 92 boolean fIsCollapsed; 93 boolean fDetach = false; 94 Node fInsertNode = null; 95 Node fDeleteNode = null; 96 Node fSplitNode = null; 97 98 99 103 public RangeImpl(DocumentImpl document) { 104 fDocument = document; 105 fStartContainer = document; 106 fEndContainer = document; 107 fStartOffset = 0; 108 fEndOffset = 0; 109 fDetach = false; 110 } 111 112 public Node getStartContainer() { 113 if ( fDetach ) { 114 throw new DOMException ( 115 DOMException.INVALID_STATE_ERR, 116 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 117 } 118 return fStartContainer; 119 } 120 121 public int getStartOffset() { 122 if ( fDetach ) { 123 throw new DOMException ( 124 DOMException.INVALID_STATE_ERR, 125 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 126 } 127 return fStartOffset; 128 } 129 130 public Node getEndContainer() { 131 if ( fDetach ) { 132 throw new DOMException ( 133 DOMException.INVALID_STATE_ERR, 134 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 135 } 136 return fEndContainer; 137 } 138 139 public int getEndOffset() { 140 if ( fDetach ) { 141 throw new DOMException ( 142 DOMException.INVALID_STATE_ERR, 143 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 144 } 145 return fEndOffset; 146 } 147 148 public boolean getCollapsed() { 149 if ( fDetach ) { 150 throw new DOMException ( 151 DOMException.INVALID_STATE_ERR, 152 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 153 } 154 return (fStartContainer == fEndContainer 155 && fStartOffset == fEndOffset); 156 } 157 158 public Node getCommonAncestorContainer() { 159 if ( fDetach ) { 160 throw new DOMException ( 161 DOMException.INVALID_STATE_ERR, 162 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 163 } 164 Vector startV = new Vector (); 165 Node node; 166 for (node=fStartContainer; node != null; 167 node=node.getParentNode()) 168 { 169 startV.addElement(node); 170 } 171 Vector endV = new Vector (); 172 for (node=fEndContainer; node != null; 173 node=node.getParentNode()) 174 { 175 endV.addElement(node); 176 } 177 int s = startV.size()-1; 178 int e = endV.size()-1; 179 Object result = null; 180 while (s>=0 && e>=0) { 181 if (startV.elementAt(s) == endV.elementAt(e)) { 182 result = startV.elementAt(s); 183 } else { 184 break; 185 } 186 --s; 187 --e; 188 } 189 return (Node )result; 190 } 191 192 193 public void setStart(Node refNode, int offset) 194 throws RangeException, DOMException 195 { 196 if( fDetach) { 197 throw new DOMException ( 198 DOMException.INVALID_STATE_ERR, 199 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 200 } 201 if ( !isLegalContainer(refNode)) { 202 throw new RangeExceptionImpl( 203 RangeException.INVALID_NODE_TYPE_ERR, 204 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 205 } 206 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 207 throw new DOMException ( 208 DOMException.WRONG_DOCUMENT_ERR, 209 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 210 } 211 212 213 checkIndex(refNode, offset); 214 215 fStartContainer = refNode; 216 fStartOffset = offset; 217 } 218 219 public void setEnd(Node refNode, int offset) 220 throws RangeException, DOMException 221 { 222 if( fDetach) { 223 throw new DOMException ( 224 DOMException.INVALID_STATE_ERR, 225 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 226 } 227 if ( !isLegalContainer(refNode)) { 228 throw new RangeExceptionImpl( 229 RangeException.INVALID_NODE_TYPE_ERR, 230 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 231 } 232 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 233 throw new DOMException ( 234 DOMException.WRONG_DOCUMENT_ERR, 235 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 236 } 237 238 checkIndex(refNode, offset); 239 240 fEndContainer = refNode; 241 fEndOffset = offset; 242 } 243 244 public void setStartBefore(Node refNode) 245 throws RangeException 246 { 247 if( fDetach) { 248 throw new DOMException ( 249 DOMException.INVALID_STATE_ERR, 250 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 251 } 252 if ( !hasLegalRootContainer(refNode) || 253 !isLegalContainedNode(refNode) ) 254 { 255 throw new RangeExceptionImpl( 256 RangeException.INVALID_NODE_TYPE_ERR, 257 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 258 } 259 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 260 throw new DOMException ( 261 DOMException.WRONG_DOCUMENT_ERR, 262 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 263 } 264 fStartContainer = refNode.getParentNode(); 265 int i = 0; 266 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 267 i++; 268 } 269 fStartOffset = i-1; 270 } 271 272 public void setStartAfter(Node refNode) 273 throws RangeException 274 { 275 if( fDetach) { 276 throw new DOMException ( 277 DOMException.INVALID_STATE_ERR, 278 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 279 } 280 if ( !hasLegalRootContainer(refNode) || 281 !isLegalContainedNode(refNode)) { 282 throw new RangeExceptionImpl( 283 RangeException.INVALID_NODE_TYPE_ERR, 284 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 285 } 286 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 287 throw new DOMException ( 288 DOMException.WRONG_DOCUMENT_ERR, 289 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 290 } 291 fStartContainer = refNode.getParentNode(); 292 int i = 0; 293 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 294 i++; 295 } 296 fStartOffset = i; 297 } 298 299 public void setEndBefore(Node refNode) 300 throws RangeException 301 { 302 if( fDetach) { 303 throw new DOMException ( 304 DOMException.INVALID_STATE_ERR, 305 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 306 } 307 if ( !hasLegalRootContainer(refNode) || 308 !isLegalContainedNode(refNode)) { 309 throw new RangeExceptionImpl( 310 RangeException.INVALID_NODE_TYPE_ERR, 311 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 312 } 313 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 314 throw new DOMException ( 315 DOMException.WRONG_DOCUMENT_ERR, 316 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 317 } 318 fEndContainer = refNode.getParentNode(); 319 int i = 0; 320 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 321 i++; 322 } 323 fEndOffset = i-1; 324 } 325 326 public void setEndAfter(Node refNode) 327 throws RangeException 328 { 329 if( fDetach) { 330 throw new DOMException ( 331 DOMException.INVALID_STATE_ERR, 332 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 333 } 334 if ( !hasLegalRootContainer(refNode) || 335 !isLegalContainedNode(refNode)) { 336 throw new RangeExceptionImpl( 337 RangeException.INVALID_NODE_TYPE_ERR, 338 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 339 } 340 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 341 throw new DOMException ( 342 DOMException.WRONG_DOCUMENT_ERR, 343 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 344 } 345 fEndContainer = refNode.getParentNode(); 346 int i = 0; 347 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 348 i++; 349 } 350 fEndOffset = i; 351 } 352 353 public void collapse(boolean toStart) { 354 355 if( fDetach) { 356 throw new DOMException ( 357 DOMException.INVALID_STATE_ERR, 358 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 359 } 360 361 if (toStart) { 362 fEndContainer = fStartContainer; 363 fEndOffset = fStartOffset; 364 } else { 365 fStartContainer = fEndContainer; 366 fStartOffset = fEndOffset; 367 } 368 } 369 370 public void selectNode(Node refNode) 371 throws RangeException 372 { 373 if( fDetach) { 374 throw new DOMException ( 375 DOMException.INVALID_STATE_ERR, 376 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 377 } 378 if ( !isLegalContainer( refNode.getParentNode() ) || 379 !isLegalContainedNode( refNode ) ) { 380 throw new RangeExceptionImpl( 381 RangeException.INVALID_NODE_TYPE_ERR, 382 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 383 } 384 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 385 throw new DOMException ( 386 DOMException.WRONG_DOCUMENT_ERR, 387 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 388 } 389 Node parent = refNode.getParentNode(); 390 if (parent != null ) { 392 fStartContainer = parent; 393 fEndContainer = parent; 394 int i = 0; 395 for (Node n = refNode; n!=null; n = n.getPreviousSibling()) { 396 i++; 397 } 398 fStartOffset = i-1; 399 fEndOffset = fStartOffset+1; 400 } 401 } 402 403 public void selectNodeContents(Node refNode) 404 throws RangeException 405 { 406 if( fDetach) { 407 throw new DOMException ( 408 DOMException.INVALID_STATE_ERR, 409 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 410 } 411 if ( !isLegalContainer(refNode)) { 412 throw new RangeExceptionImpl( 413 RangeException.INVALID_NODE_TYPE_ERR, 414 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 415 } 416 if ( fDocument != refNode.getOwnerDocument() && fDocument != refNode) { 417 throw new DOMException ( 418 DOMException.WRONG_DOCUMENT_ERR, 419 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 420 } 421 fStartContainer = refNode; 422 fEndContainer = refNode; 423 Node first = refNode.getFirstChild(); 424 fStartOffset = 0; 425 if (first == null) { 426 fEndOffset = 0; 427 } else { 428 int i = 0; 429 for (Node n = first; n!=null; n = n.getNextSibling()) { 430 i++; 431 } 432 fEndOffset = i; 433 } 434 435 } 436 437 public short compareBoundaryPoints(short how, Range sourceRange) 438 throws DOMException 439 { 440 if( fDetach) { 441 throw new DOMException ( 442 DOMException.INVALID_STATE_ERR, 443 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 444 } 445 446 Node endPointA; 447 Node endPointB; 448 int offsetA; 449 int offsetB; 450 451 if (how == START_TO_START) { 452 endPointA = sourceRange.getStartContainer(); 453 endPointB = fStartContainer; 454 offsetA = sourceRange.getStartOffset(); 455 offsetB = fStartOffset; 456 } else 457 if (how == START_TO_END) { 458 endPointA = sourceRange.getStartContainer(); 459 endPointB = fEndContainer; 460 offsetA = sourceRange.getStartOffset(); 461 offsetB = fEndOffset; 462 } else 463 if (how == END_TO_START) { 464 endPointA = sourceRange.getEndContainer(); 465 endPointB = fStartContainer; 466 offsetA = sourceRange.getEndOffset(); 467 offsetB = fStartOffset; 468 } else { 469 endPointA = sourceRange.getEndContainer(); 470 endPointB = fEndContainer; 471 offsetA = sourceRange.getEndOffset(); 472 offsetB = fEndOffset; 473 } 474 475 482 if (endPointA == endPointB) { 484 if (offsetA < offsetB) return 1; 485 if (offsetA == offsetB) return 0; 486 return -1; 487 } 488 for ( Node c = endPointB, p = c.getParentNode(); 491 p != null; 492 c = p, p = p.getParentNode()) 493 { 494 if (p == endPointA) { 495 int index = indexOf(c, endPointA); 496 if (offsetA <= index) return 1; 497 return -1; 498 } 499 } 500 501 for ( Node c = endPointA, p = c.getParentNode(); 504 p != null; 505 c = p, p = p.getParentNode()) 506 { 507 if (p == endPointB) { 508 int index = indexOf(c, endPointB); 509 if (index < offsetB) return 1; 510 return -1; 511 } 512 } 513 514 518 int depthDiff = 0; 519 for ( Node n = endPointA; n != null; n = n.getParentNode() ) 520 depthDiff++; 521 for ( Node n = endPointB; n != null; n = n.getParentNode() ) 522 depthDiff--; 523 while (depthDiff > 0) { 524 endPointA = endPointA.getParentNode(); 525 depthDiff--; 526 } 527 while (depthDiff < 0) { 528 endPointB = endPointB.getParentNode(); 529 depthDiff++; 530 } 531 for (Node pA = endPointA.getParentNode(), 532 pB = endPointB.getParentNode(); 533 pA != pB; 534 pA = pA.getParentNode(), pB = pB.getParentNode() ) 535 { 536 endPointA = pA; 537 endPointB = pB; 538 } 539 for ( Node n = endPointA.getNextSibling(); 540 n != null; 541 n = n.getNextSibling() ) 542 { 543 if (n == endPointB) { 544 return 1; 545 } 546 } 547 return -1; 548 } 549 550 public void deleteContents() 551 throws DOMException 552 { 553 traverseContents(DELETE_CONTENTS); 554 } 555 556 public DocumentFragment extractContents() 557 throws DOMException 558 { 559 return traverseContents(EXTRACT_CONTENTS); 560 } 561 562 public DocumentFragment cloneContents() 563 throws DOMException 564 { 565 return traverseContents(CLONE_CONTENTS); 566 } 567 568 public void insertNode(Node newNode) 569 throws DOMException , RangeException 570 { 571 if ( newNode == null ) return; 573 if( fDetach) { 574 throw new DOMException ( 575 DOMException.INVALID_STATE_ERR, 576 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 577 } 578 if ( fDocument != newNode.getOwnerDocument() ) { 579 throw new DOMException (DOMException.WRONG_DOCUMENT_ERR, 580 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null)); 581 } 582 583 int type = newNode.getNodeType(); 584 if (type == Node.ATTRIBUTE_NODE 585 || type == Node.ENTITY_NODE 586 || type == Node.NOTATION_NODE 587 || type == Node.DOCUMENT_NODE) 588 { 589 throw new RangeExceptionImpl( 590 RangeException.INVALID_NODE_TYPE_ERR, 591 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 592 } 593 Node cloneCurrent; 594 Node current; 595 int currentChildren = 0; 596 597 if (fStartContainer.getNodeType() == Node.TEXT_NODE) { 599 600 Node parent = fStartContainer.getParentNode(); 601 currentChildren = parent.getChildNodes().getLength(); cloneCurrent = fStartContainer.cloneNode(false); 604 ((TextImpl)cloneCurrent).setNodeValueInternal( 605 (cloneCurrent.getNodeValue()).substring(fStartOffset)); 606 ((TextImpl)fStartContainer).setNodeValueInternal( 607 (fStartContainer.getNodeValue()).substring(0,fStartOffset)); 608 Node next = fStartContainer.getNextSibling(); 609 if (next != null) { 610 if (parent != null) { 611 parent.insertBefore(newNode, next); 612 parent.insertBefore(cloneCurrent, next); 613 } 614 } else { 615 if (parent != null) { 616 parent.appendChild(newNode); 617 parent.appendChild(cloneCurrent); 618 } 619 } 620 if ( fEndContainer == fStartContainer) { 622 fEndContainer = cloneCurrent; fEndOffset -= fStartOffset; 624 } 625 else if ( fEndContainer == parent ) { fEndOffset += (parent.getChildNodes().getLength() - currentChildren); 628 } 629 630 signalSplitData(fStartContainer, cloneCurrent, fStartOffset); 632 633 634 } else { if ( fEndContainer == fStartContainer ) currentChildren= fEndContainer.getChildNodes().getLength(); 637 638 current = fStartContainer.getFirstChild(); 639 int i = 0; 640 for(i = 0; i < fStartOffset && current != null; i++) { 641 current=current.getNextSibling(); 642 } 643 if (current != null) { 644 fStartContainer.insertBefore(newNode, current); 645 } else { 646 fStartContainer.appendChild(newNode); 647 } 648 if ( fEndContainer == fStartContainer ) { fEndOffset += (fEndContainer.getChildNodes().getLength() - currentChildren); 652 } 653 654 } 655 } 656 657 public void surroundContents(Node newParent) 658 throws DOMException , RangeException 659 { 660 if (newParent==null) return; 661 662 if( fDetach) { 663 throw new DOMException ( 664 DOMException.INVALID_STATE_ERR, 665 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 666 } 667 int type = newParent.getNodeType(); 668 if (type == Node.ATTRIBUTE_NODE 669 || type == Node.ENTITY_NODE 670 || type == Node.NOTATION_NODE 671 || type == Node.DOCUMENT_TYPE_NODE 672 || type == Node.DOCUMENT_NODE 673 || type == Node.DOCUMENT_FRAGMENT_NODE) 674 { 675 throw new RangeExceptionImpl( 676 RangeException.INVALID_NODE_TYPE_ERR, 677 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 678 } 679 680 Node root = getCommonAncestorContainer(); 681 682 Node realStart = fStartContainer; 683 Node realEnd = fEndContainer; 684 if (fStartContainer.getNodeType() == Node.TEXT_NODE) { 685 realStart = fStartContainer.getParentNode(); 686 } 687 if (fEndContainer.getNodeType() == Node.TEXT_NODE) { 688 realEnd = fEndContainer.getParentNode(); 689 } 690 691 if (realStart != realEnd) { 692 throw new RangeExceptionImpl( 693 RangeException.BAD_BOUNDARYPOINTS_ERR, 694 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "BAD_BOUNDARYPOINTS_ERR", null)); 695 } 696 697 DocumentFragment frag = extractContents(); 698 insertNode(newParent); 699 newParent.appendChild(frag); 700 selectNode(newParent); 701 } 702 703 public Range cloneRange(){ 704 if( fDetach) { 705 throw new DOMException ( 706 DOMException.INVALID_STATE_ERR, 707 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 708 } 709 710 Range range = fDocument.createRange(); 711 range.setStart(fStartContainer, fStartOffset); 712 range.setEnd(fEndContainer, fEndOffset); 713 return range; 714 } 715 716 public String toString(){ 717 if( fDetach) { 718 throw new DOMException ( 719 DOMException.INVALID_STATE_ERR, 720 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 721 } 722 723 Node node = fStartContainer; 724 Node stopNode = fEndContainer; 725 StringBuffer sb = new StringBuffer (); 726 if (fStartContainer.getNodeType() == Node.TEXT_NODE 727 || fStartContainer.getNodeType() == Node.CDATA_SECTION_NODE 728 ) { 729 if (fStartContainer == fEndContainer) { 730 sb.append(fStartContainer.getNodeValue().substring(fStartOffset, fEndOffset)); 731 return sb.toString(); 732 } 733 sb.append(fStartContainer.getNodeValue().substring(fStartOffset)); 734 node=nextNode (node,true); 736 } 737 else { node=node.getFirstChild(); 739 if (fStartOffset>0) { int counter=0; 741 while (counter<fStartOffset && node!=null) { 742 node=node.getNextSibling(); 743 counter++; 744 } 745 } 746 if (node == null) { 747 node = nextNode(fStartContainer,false); 748 } 749 } 750 if ( fEndContainer.getNodeType()!= Node.TEXT_NODE && 751 fEndContainer.getNodeType()!= Node.CDATA_SECTION_NODE ){ 752 int i=fEndOffset; 753 stopNode = fEndContainer.getFirstChild(); 754 while( i>0 && stopNode!=null ){ 755 --i; 756 stopNode = stopNode.getNextSibling(); 757 } 758 if ( stopNode == null ) 759 stopNode = nextNode( fEndContainer, false ); 760 } 761 while (node != stopNode) { if (node == null) break; 763 if (node.getNodeType() == Node.TEXT_NODE 764 || node.getNodeType() == Node.CDATA_SECTION_NODE) { 765 sb.append(node.getNodeValue()); 766 } 767 768 node = nextNode(node, true); 769 } 770 771 if (fEndContainer.getNodeType() == Node.TEXT_NODE 772 || fEndContainer.getNodeType() == Node.CDATA_SECTION_NODE) { 773 sb.append(fEndContainer.getNodeValue().substring(0,fEndOffset)); 774 } 775 return sb.toString(); 776 } 777 778 public void detach() { 779 fDetach = true; 780 fDocument.removeRange(this); 781 } 782 783 787 791 void signalSplitData(Node node, Node newNode, int offset) { 792 fSplitNode = node; 793 fDocument.splitData(node, newNode, offset); 795 fSplitNode = null; 796 } 797 798 801 void receiveSplitData(Node node, Node newNode, int offset) { 802 if (node == null || newNode == null) return; 803 if (fSplitNode == node) return; 804 805 if (node == fStartContainer 806 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 807 if (fStartOffset > offset) { 808 fStartOffset = fStartOffset - offset; 809 fStartContainer = newNode; 810 } 811 } 812 if (node == fEndContainer 813 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 814 if (fEndOffset > offset) { 815 fEndOffset = fEndOffset-offset; 816 fEndContainer = newNode; 817 } 818 } 819 820 } 821 822 825 void deleteData(CharacterData node, int offset, int count) { 826 fDeleteNode = node; 827 node.deleteData( offset, count); 828 fDeleteNode = null; 829 } 830 831 832 836 void receiveDeletedText(Node node, int offset, int count) { 837 if (node == null) return; 838 if (fDeleteNode == node) return; 839 if (node == fStartContainer 840 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 841 if (fStartOffset > offset+count) { 842 fStartOffset = offset+(fStartOffset-(offset+count)); 843 } else 844 if (fStartOffset > offset) { 845 fStartOffset = offset; 846 } 847 } 848 if (node == fEndContainer 849 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 850 if (fEndOffset > offset+count) { 851 fEndOffset = offset+(fEndOffset-(offset+count)); 852 } else 853 if (fEndOffset > offset) { 854 fEndOffset = offset; 855 } 856 } 857 858 } 859 860 863 void insertData(CharacterData node, int index, String insert) { 864 fInsertNode = node; 865 node.insertData( index, insert); 866 fInsertNode = null; 867 } 868 869 870 874 void receiveInsertedText(Node node, int index, int len) { 875 if (node == null) return; 876 if (fInsertNode == node) return; 877 if (node == fStartContainer 878 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 879 if (index < fStartOffset) { 880 fStartOffset = fStartOffset+len; 881 } 882 } 883 if (node == fEndContainer 884 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 885 if (index < fEndOffset) { 886 fEndOffset = fEndOffset+len; 887 } 888 } 889 890 } 891 892 896 void receiveReplacedText(Node node) { 897 if (node == null) return; 898 if (node == fStartContainer 899 && fStartContainer.getNodeType() == Node.TEXT_NODE) { 900 fStartOffset = 0; 901 } 902 if (node == fEndContainer 903 && fEndContainer.getNodeType() == Node.TEXT_NODE) { 904 fEndOffset = 0; 905 } 906 907 } 908 909 913 public void insertedNodeFromDOM(Node node) { 914 if (node == null) return; 915 if (fInsertNode == node) return; 916 917 Node parent = node.getParentNode(); 918 919 if (parent == fStartContainer) { 920 int index = indexOf(node, fStartContainer); 921 if (index < fStartOffset) { 922 fStartOffset++; 923 } 924 } 925 926 if (parent == fEndContainer) { 927 int index = indexOf(node, fEndContainer); 928 if (index < fEndOffset) { 929 fEndOffset++; 930 } 931 } 932 933 } 934 935 940 941 Node fRemoveChild = null; 942 Node removeChild(Node parent, Node child) { 943 fRemoveChild = child; 944 Node n = parent.removeChild(child); 945 fRemoveChild = null; 946 return n; 947 } 948 949 953 void removeNode(Node node) { 954 if (node == null) return; 955 if (fRemoveChild == node) return; 956 957 Node parent = node.getParentNode(); 958 959 if (parent == fStartContainer) { 960 int index = indexOf(node, fStartContainer); 961 if (index < fStartOffset) { 962 fStartOffset--; 963 } 964 } 965 966 if (parent == fEndContainer) { 967 int index = indexOf(node, fEndContainer); 968 if (index < fEndOffset) { 969 fEndOffset--; 970 } 971 } 972 if (parent != fStartContainer 974 || parent != fEndContainer) { 975 if (isAncestorOf(node, fStartContainer)) { 976 fStartContainer = parent; 977 fStartOffset = indexOf( node, parent); 978 } 979 if (isAncestorOf(node, fEndContainer)) { 980 fEndContainer = parent; 981 fEndOffset = indexOf( node, parent); 982 } 983 } 984 985 } 986 987 991 static final int EXTRACT_CONTENTS = 1; 994 static final int CLONE_CONTENTS = 2; 995 static final int DELETE_CONTENTS = 3; 996 997 1027 private DocumentFragment traverseContents( int how ) 1028 throws DOMException 1029 { 1030 if (fStartContainer == null || fEndContainer == null) { 1031 return null; } 1033 1034 if( fDetach) { 1036 throw new DOMException ( 1037 DOMException.INVALID_STATE_ERR, 1038 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); 1039 } 1040 1041 1048 1049 if ( fStartContainer == fEndContainer ) 1051 return traverseSameContainer( how ); 1052 1053 1054 int endContainerDepth = 0; 1058 for ( Node c = fEndContainer, p = c.getParentNode(); 1059 p != null; 1060 c = p, p = p.getParentNode()) 1061 { 1062 if (p == fStartContainer) 1063 return traverseCommonStartContainer( c, how ); 1064 ++endContainerDepth; 1065 } 1066 1067 int startContainerDepth = 0; 1070 for ( Node c = fStartContainer, p = c.getParentNode(); 1071 p != null; 1072 c = p, p = p.getParentNode()) 1073 { 1074 if (p == fEndContainer) 1075 return traverseCommonEndContainer( c, how ); 1076 ++startContainerDepth; 1077 } 1078 1079 int depthDiff = startContainerDepth - endContainerDepth; 1082 1083 Node startNode = fStartContainer; 1084 while (depthDiff > 0) { 1085 startNode = startNode.getParentNode(); 1086 depthDiff--; 1087 } 1088 1089 Node endNode = fEndContainer; 1090 while (depthDiff < 0) { 1091 endNode = endNode.getParentNode(); 1092 depthDiff++; 1093 } 1094 1095 for( Node sp = startNode.getParentNode(), ep = endNode.getParentNode(); 1097 sp!=ep; 1098 sp = sp.getParentNode(), ep = ep.getParentNode() ) 1099 { 1100 startNode = sp; 1101 endNode = ep; 1102 } 1103 return traverseCommonAncestors( startNode, endNode, how ); 1104 } 1105 1106 1136 private DocumentFragment traverseSameContainer( int how ) 1137 { 1138 DocumentFragment frag = null; 1139 if ( how!=DELETE_CONTENTS) 1140 frag = fDocument.createDocumentFragment(); 1141 1142 if ( fStartOffset==fEndOffset ) 1144 return frag; 1145 1146 if ( fStartContainer.getNodeType()==Node.TEXT_NODE ) 1148 { 1149 String s = fStartContainer.getNodeValue(); 1151 String sub = s.substring( fStartOffset, fEndOffset ); 1152 1153 if ( how != CLONE_CONTENTS ) 1155 { 1156 ((TextImpl)fStartContainer).deleteData(fStartOffset, 1157 fEndOffset-fStartOffset) ; 1158 collapse( true ); 1160 } 1161 if ( how==DELETE_CONTENTS) 1162 return null; 1163 frag.appendChild( fDocument.createTextNode(sub) ); 1164 return frag; 1165 } 1166 1167 Node n = getSelectedNode( fStartContainer, fStartOffset ); 1169 int cnt = fEndOffset - fStartOffset; 1170 while( cnt > 0 ) 1171 { 1172 Node sibling = n.getNextSibling(); 1173 Node xferNode = traverseFullySelected( n, how ); 1174 if ( frag!=null ) 1175 frag.appendChild( xferNode ); 1176 --cnt; 1177 n = sibling; 1178 } 1179 1180 if ( how != CLONE_CONTENTS ) 1182 collapse( true ); 1183 return frag; 1184 } 1185 1186 1221 private DocumentFragment 1222 traverseCommonStartContainer( Node endAncestor, int how ) 1223 { 1224 DocumentFragment frag = null; 1225 if ( how!=DELETE_CONTENTS) 1226 frag = fDocument.createDocumentFragment(); 1227 Node n = traverseRightBoundary( endAncestor, how ); 1228 if ( frag!=null ) 1229 frag.appendChild( n ); 1230 1231 int endIdx = indexOf( endAncestor, fStartContainer ); 1232 int cnt = endIdx - fStartOffset; 1233 if ( cnt <=0 ) 1234 { 1235 if ( how != CLONE_CONTENTS ) 1238 { 1239 setEndBefore( endAncestor ); 1240 collapse( false ); 1241 } 1242 return frag; 1243 } 1244 1245 n = endAncestor.getPreviousSibling(); 1246 while( cnt > 0 ) 1247 { 1248 Node sibling = n.getPreviousSibling(); 1249 Node xferNode = traverseFullySelected( n, how ); 1250 if ( frag!=null ) 1251 frag.insertBefore( xferNode, frag.getFirstChild() ); 1252 --cnt; 1253 n = sibling; 1254 } 1255 if ( how != CLONE_CONTENTS ) 1258 { 1259 setEndBefore( endAncestor ); 1260 collapse( false ); 1261 } 1262 return frag; 1263 } 1264 1265 1300 private DocumentFragment 1301 traverseCommonEndContainer( Node startAncestor, int how ) 1302 { 1303 DocumentFragment frag = null; 1304 if ( how!=DELETE_CONTENTS) 1305 frag = fDocument.createDocumentFragment(); 1306 Node n = traverseLeftBoundary( startAncestor, how ); 1307 if ( frag!=null ) 1308 frag.appendChild( n ); 1309 int startIdx = indexOf( startAncestor, fEndContainer ); 1310 ++startIdx; 1312 int cnt = fEndOffset - startIdx; 1313 n = startAncestor.getNextSibling(); 1314 while( cnt > 0 ) 1315 { 1316 Node sibling = n.getNextSibling(); 1317 Node xferNode = traverseFullySelected( n, how ); 1318 if ( frag!=null ) 1319 frag.appendChild( xferNode ); 1320 --cnt; 1321 n = sibling; 1322 } 1323 1324 if ( how != CLONE_CONTENTS ) 1325 { 1326 setStartAfter( startAncestor ); 1327 collapse( true ); 1328 } 1329 1330 return frag; 1331 } 1332 1333 1375 private DocumentFragment 1376 traverseCommonAncestors( Node startAncestor, Node endAncestor, int how ) 1377 { 1378 DocumentFragment frag = null; 1379 if ( how!=DELETE_CONTENTS) 1380 frag = fDocument.createDocumentFragment(); 1381 1382 Node n = traverseLeftBoundary( startAncestor, how ); 1383 if ( frag!=null ) 1384 frag.appendChild( n ); 1385 1386 Node commonParent = startAncestor.getParentNode(); 1387 int startOffset = indexOf( startAncestor, commonParent ); 1388 int endOffset = indexOf( endAncestor, commonParent ); 1389 ++startOffset; 1390 1391 int cnt = endOffset - startOffset; 1392 Node sibling = startAncestor.getNextSibling(); 1393 1394 while( cnt > 0 ) 1395 { 1396 Node nextSibling = sibling.getNextSibling(); 1397 n = traverseFullySelected( sibling, how ); 1398 if ( frag!=null ) 1399 frag.appendChild( n ); 1400 sibling = nextSibling; 1401 --cnt; 1402 } 1403 1404 n = traverseRightBoundary( endAncestor, how ); 1405 if ( frag!=null ) 1406 frag.appendChild( n ); 1407 1408 if ( how != CLONE_CONTENTS ) 1409 { 1410 setStartAfter( startAncestor ); 1411 collapse( true ); 1412 } 1413 return frag; 1414 } 1415 1416 1474 private Node traverseRightBoundary( Node root, int how ) 1475 { 1476 Node next = getSelectedNode( fEndContainer, fEndOffset-1 ); 1477 boolean isFullySelected = ( next!=fEndContainer ); 1478 1479 if ( next==root ) 1480 return traverseNode( next, isFullySelected, false, how ); 1481 1482 Node parent = next.getParentNode(); 1483 Node clonedParent = traverseNode( parent, false, false, how ); 1484 1485 while( parent!=null ) 1486 { 1487 while( next!=null ) 1488 { 1489 Node prevSibling = next.getPreviousSibling(); 1490 Node clonedChild = 1491 traverseNode( next, isFullySelected, false, how ); 1492 if ( how!=DELETE_CONTENTS ) 1493 { 1494 clonedParent.insertBefore( 1495 clonedChild, 1496 clonedParent.getFirstChild() 1497 ); 1498 } 1499 isFullySelected = true; 1500 next = prevSibling; 1501 } 1502 if ( parent==root ) 1503 return clonedParent; 1504 1505 next = parent.getPreviousSibling(); 1506 parent = parent.getParentNode(); 1507 Node clonedGrandParent = traverseNode( parent, false, false, how ); 1508 if ( how!=DELETE_CONTENTS ) 1509 clonedGrandParent.appendChild( clonedParent ); 1510 clonedParent = clonedGrandParent; 1511 1512 } 1513 1514 return null; 1516 } 1517 1518 1577 private Node traverseLeftBoundary( Node root, int how ) 1578 { 1579 Node next = getSelectedNode( getStartContainer(), getStartOffset() ); 1580 boolean isFullySelected = ( next!=getStartContainer() ); 1581 1582 if ( next==root ) 1583 return traverseNode( next, isFullySelected, true, how ); 1584 1585 Node parent = next.getParentNode(); 1586 Node clonedParent = traverseNode( parent, false, true, how ); 1587 1588 while( parent!=null ) 1589 { 1590 while( next!=null ) 1591 { 1592 Node nextSibling = next.getNextSibling(); 1593 Node clonedChild = 1594 traverseNode( next, isFullySelected, true, how ); 1595 if ( how!=DELETE_CONTENTS ) 1596 clonedParent.appendChild(clonedChild); 1597 isFullySelected = true; 1598 next = nextSibling; 1599 } 1600 if ( parent==root ) 1601 return clonedParent; 1602 1603 next = parent.getNextSibling(); 1604 parent = parent.getParentNode(); 1605 Node clonedGrandParent = traverseNode( parent, false, true, how ); 1606 if ( how!=DELETE_CONTENTS ) 1607 clonedGrandParent.appendChild( clonedParent ); 1608 clonedParent = clonedGrandParent; 1609 1610 } 1611 1612 return null; 1614 1615 } 1616 1617 1658 private Node traverseNode( Node n, boolean isFullySelected, boolean isLeft, int how ) 1659 { 1660 if ( isFullySelected ) 1661 return traverseFullySelected( n, how ); 1662 if ( n.getNodeType()==Node.TEXT_NODE ) 1663 return traverseTextNode( n, isLeft, how ); 1664 return traversePartiallySelected( n, how ); 1665 } 1666 1667 1694 private Node traverseFullySelected( Node n, int how ) 1695 { 1696 switch( how ) 1697 { 1698 case CLONE_CONTENTS: 1699 return n.cloneNode( true ); 1700 case EXTRACT_CONTENTS: 1701 if ( n.getNodeType()==Node.DOCUMENT_TYPE_NODE ) 1702 { 1703 throw new RangeExceptionImpl( 1705 RangeException.INVALID_NODE_TYPE_ERR, 1706 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); 1707 } 1708 return n; 1709 case DELETE_CONTENTS: 1710 n.getParentNode().removeChild(n); 1711 return null; 1712 } 1713 return null; 1714 } 1715 1716 1743 private Node traversePartiallySelected( Node n, int how ) 1744 { 1745 switch( how ) 1746 { 1747 case DELETE_CONTENTS: 1748 return null; 1749 case CLONE_CONTENTS: 1750 case EXTRACT_CONTENTS: 1751 return n.cloneNode( false ); 1752 } 1753 return null; 1754 } 1755 1756 1789 private Node traverseTextNode( Node n, boolean isLeft, int how ) 1790 { 1791 String txtValue = n.getNodeValue(); 1792 String newNodeValue; 1793 String oldNodeValue; 1794 1795 if ( isLeft ) 1796 { 1797 int offset = getStartOffset(); 1798 newNodeValue = txtValue.substring( offset ); 1799 oldNodeValue = txtValue.substring( 0, offset ); 1800 } 1801 else 1802 { 1803 int offset = getEndOffset(); 1804 newNodeValue = txtValue.substring( 0, offset ); 1805 oldNodeValue = txtValue.substring( offset ); 1806 } 1807 1808 if ( how != CLONE_CONTENTS ) 1809 n.setNodeValue( oldNodeValue ); 1810 if ( how==DELETE_CONTENTS ) 1811 return null; 1812 Node newNode = n.cloneNode( false ); 1813 newNode.setNodeValue( newNodeValue ); 1814 return newNode; 1815 } 1816 1817 void checkIndex(Node refNode, int offset) throws DOMException 1818 { 1819 if (offset < 0) { 1820 throw new DOMException ( 1821 DOMException.INDEX_SIZE_ERR, 1822 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null)); 1823 } 1824 1825 int type = refNode.getNodeType(); 1826 1827 if (type == Node.TEXT_NODE 1830 || type == Node.CDATA_SECTION_NODE 1831 || type == Node.COMMENT_NODE 1832 || type == Node.PROCESSING_INSTRUCTION_NODE) { 1833 if (offset > refNode.getNodeValue().length()) { 1834 throw new DOMException (DOMException.INDEX_SIZE_ERR, 1835 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null)); 1836 } 1837 } 1838 else { 1839 if (offset > refNode.getChildNodes().getLength()) { 1842 throw new DOMException (DOMException.INDEX_SIZE_ERR, 1843 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", null)); 1844 } 1845 } 1846 } 1847 1848 1852 private Node getRootContainer( Node node ) 1853 { 1854 if ( node==null ) 1855 return null; 1856 1857 while( node.getParentNode()!=null ) 1858 node = node.getParentNode(); 1859 return node; 1860 } 1861 1862 1866 private boolean isLegalContainer( Node node ) 1867 { 1868 if ( node==null ) 1869 return false; 1870 1871 while( node!=null ) 1872 { 1873 switch( node.getNodeType() ) 1874 { 1875 case Node.ENTITY_NODE: 1876 case Node.NOTATION_NODE: 1877 case Node.DOCUMENT_TYPE_NODE: 1878 return false; 1879 } 1880 node = node.getParentNode(); 1881 } 1882 1883 return true; 1884 } 1885 1886 1887 1894 private boolean hasLegalRootContainer( Node node ) 1895 { 1896 if ( node==null ) 1897 return false; 1898 1899 Node rootContainer = getRootContainer( node ); 1900 switch( rootContainer.getNodeType() ) 1901 { 1902 case Node.ATTRIBUTE_NODE: 1903 case Node.DOCUMENT_NODE: 1904 case Node.DOCUMENT_FRAGMENT_NODE: 1905 return true; 1906 } 1907 return false; 1908 } 1909 1910 1914 private boolean isLegalContainedNode( Node node ) 1915 { 1916 if ( node==null ) 1917 return false; 1918 switch( node.getNodeType() ) 1919 { 1920 case Node.DOCUMENT_NODE: 1921 case Node.DOCUMENT_FRAGMENT_NODE: 1922 case Node.ATTRIBUTE_NODE: 1923 case Node.ENTITY_NODE: 1924 case Node.NOTATION_NODE: 1925 return false; 1926 } 1927 return true; 1928 } 1929 1930 Node nextNode(Node node, boolean visitChildren) { 1931 1932 if (node == null) return null; 1933 1934 Node result; 1935 if (visitChildren) { 1936 result = node.getFirstChild(); 1937 if (result != null) { 1938 return result; 1939 } 1940 } 1941 1942 result = node.getNextSibling(); 1944 if (result != null) { 1945 return result; 1946 } 1947 1948 1949 Node parent = node.getParentNode(); 1951 while (parent != null 1952 && parent != fDocument 1953 ) { 1954 result = parent.getNextSibling(); 1955 if (result != null) { 1956 return result; 1957 } else { 1958 parent = parent.getParentNode(); 1959 } 1960 1961 } 1963 return null; 1965 } 1966 1967 1968 boolean isAncestorOf(Node a, Node b) { 1969 for (Node node=b; node != null; node=node.getParentNode()) { 1970 if (node == a) return true; 1971 } 1972 return false; 1973 } 1974 1975 1976 int indexOf(Node child, Node parent) { 1977 if (child.getParentNode() != parent) return -1; 1978 int i = 0; 1979 for(Node node = parent.getFirstChild(); node!= child; node=node.getNextSibling()) { 1980 i++; 1981 } 1982 return i; 1983 } 1984 1985 2001 private Node getSelectedNode( Node container, int offset ) 2002 { 2003 if ( container.getNodeType() == Node.TEXT_NODE ) 2004 return container; 2005 2006 if ( offset<0 ) 2009 return container; 2010 2011 Node child = container.getFirstChild(); 2012 while( child!=null && offset > 0 ) 2013 { 2014 --offset; 2015 child = child.getNextSibling(); 2016 } 2017 if ( child!=null ) 2018 return child; 2019 return container; 2020 } 2021 2022} 2023 | Popular Tags |