1 11 package org.eclipse.jdt.internal.core.jdom; 12 13 import java.util.Enumeration ; 14 15 import org.eclipse.jdt.core.jdom.*; 16 import org.eclipse.jdt.internal.core.util.CharArrayBuffer; 17 import org.eclipse.jdt.internal.core.util.Messages; 18 19 55 public abstract class DOMNode implements IDOMNode { 56 57 62 protected DOMNode fFirstChild= null; 63 64 70 protected DOMNode fLastChild= null; 71 72 76 protected DOMNode fNextNode= null; 77 78 83 protected DOMNode fParent= null; 84 85 89 protected DOMNode fPreviousNode= null; 90 91 100 protected boolean fIsFragmented= false; 101 102 108 protected String fName= null; 109 110 115 protected int[] fNameRange; 116 117 122 protected char[] fDocument= null; 123 124 129 protected int[] fSourceRange; 130 131 140 protected int fStateMask= 0; 141 142 146 protected int fInsertionPosition; 147 148 152 protected static final int MASK_FIELD_HAS_INITIALIZER= 0x00000001; 153 154 158 protected static final int MASK_FIELD_IS_VARIABLE_DECLARATOR= 0x00000002; 159 160 164 protected static final int MASK_FIELD_TYPE_ALTERED= 0x00000004; 165 166 170 protected static final int MASK_NAME_ALTERED= 0x00000008; 171 172 176 protected static final int MASK_HAS_BODY= 0x00000010; 177 178 182 protected static final int MASK_HAS_COMMENT= 0x00000020; 183 184 187 protected static final int MASK_IS_CONSTRUCTOR= 0x00000040; 188 189 192 protected static final int MASK_TYPE_IS_CLASS= 0x00000080; 193 194 198 protected static final int MASK_TYPE_HAS_SUPERCLASS= 0x00000100; 199 200 204 protected static final int MASK_TYPE_HAS_INTERFACES= 0x00000200; 205 206 210 protected static final int MASK_RETURN_TYPE_ALTERED= 0x00000400; 211 212 215 protected static final int MASK_DETAILED_SOURCE_INDEXES = 0x00000800; 216 217 220 DOMNode() { 221 fName= null; 222 fDocument= null; 223 fSourceRange= new int[]{-1, -1}; 224 fNameRange= new int[]{-1, -1}; 225 fragment(); 226 } 227 244 DOMNode(char[] document, int[] sourceRange, String name, int[] nameRange) { 245 super(); 246 fDocument= document; 247 fSourceRange= sourceRange; 248 fName= name; 249 fNameRange= nameRange; 250 251 } 252 261 public void addChild(IDOMNode child) throws IllegalArgumentException , DOMException { 262 basicAddChild(child); 263 264 if (child.getNodeType() == IDOMNode.METHOD && ((IDOMMethod)child).isConstructor()) { 266 ((DOMNode)child).fragment(); 267 } else { 268 fragment(); 269 } 270 } 271 281 protected void appendContents(CharArrayBuffer buffer) { 282 if (isFragmented()) { 283 appendFragmentedContents(buffer); 284 } else { 285 buffer.append(fDocument, fSourceRange[0], fSourceRange[1] + 1 - fSourceRange[0]); 286 } 287 } 288 296 protected void appendContentsOfChildren(CharArrayBuffer buffer) { 297 DOMNode child= fFirstChild; 298 DOMNode sibling; 299 300 int start= 0, end= 0; 301 if (child != null) { 302 start= child.getStartPosition(); 303 end= child.getEndPosition(); 304 } 305 while (child != null) { 306 sibling= child.fNextNode; 307 if (sibling != null) { 308 if (sibling.isContentMergableWith(child)) { 309 end= sibling.getEndPosition(); 310 } else { 311 if (child.isFragmented()) { 312 child.appendContents(buffer); 313 } else { 314 buffer.append(child.getDocument(), start, end + 1 - start); 315 } 316 start= sibling.getStartPosition(); 317 end= sibling.getEndPosition(); 318 } 319 } else { 320 if (child.isFragmented()) { 321 child.appendContents(buffer); 322 } else { 323 buffer.append(child.getDocument(), start, end + 1 - start); 324 } 325 } 326 child= sibling; 327 } 328 } 329 334 protected abstract void appendFragmentedContents(CharArrayBuffer buffer); 335 341 void basicAddChild(IDOMNode child) throws IllegalArgumentException , DOMException { 342 if (!canHaveChildren()) { 344 throw new DOMException(Messages.dom_unableAddChild); 345 } 346 if (child == null) { 347 throw new IllegalArgumentException (Messages.dom_addNullChild); 348 } 349 if (!isAllowableChild(child)) { 350 throw new DOMException(Messages.dom_addIncompatibleChild); 351 } 352 if (child.getParent() != null) { 353 throw new DOMException(Messages.dom_addChildWithParent); 354 } 355 359 if (child == getRoot()) { 360 throw new DOMException(Messages.dom_addAncestorAsChild); 361 } 362 363 DOMNode node= (DOMNode)child; 364 365 if (node.getDocument() != getDocument()) { 368 node.localizeContents(); 369 } 370 371 if (fFirstChild == null) { 373 fFirstChild= node; 375 } else { 376 fLastChild.fNextNode= node; 377 node.fPreviousNode= fLastChild; 378 } 379 fLastChild= node; 380 node.fParent= this; 381 } 382 388 protected void becomeDetailed() throws DOMException { 389 if (!isDetailed()) { 390 DOMNode detailed= getDetailedNode(); 391 if (detailed == null) { 392 throw new DOMException(Messages.dom_cannotDetail); 393 } 394 if (detailed != this) { 395 shareContents(detailed); 396 } 397 } 398 } 399 408 public boolean canHaveChildren() { 409 return false; 410 } 411 414 public Object clone() { 415 416 int length= 0; 418 char[] buffer= null; 419 int offset= fSourceRange[0]; 420 421 if (offset >= 0) { 422 length= fSourceRange[1] - offset + 1; 423 buffer= new char[length]; 424 System.arraycopy(fDocument, offset, buffer, 0, length); 425 } 426 DOMNode clone= newDOMNode(); 427 clone.shareContents(this); 428 clone.fDocument = buffer; 429 430 if (offset > 0) { 431 clone.offset(0 - offset); 432 } 433 434 if (canHaveChildren()) { 436 Enumeration children= getChildren(); 437 while (children.hasMoreElements()) { 438 DOMNode child= (DOMNode)children.nextElement(); 439 if (child.fDocument == fDocument) { 440 DOMNode childClone= child.cloneSharingDocument(buffer, offset); 441 clone.basicAddChild(childClone); 442 } else { 443 DOMNode childClone= (DOMNode)child.clone(); 444 clone.addChild(childClone); 445 } 446 447 } 448 } 449 450 return clone; 451 } 452 private DOMNode cloneSharingDocument(char[] document, int rootOffset) { 453 454 DOMNode clone = newDOMNode(); 455 clone.shareContents(this); 456 clone.fDocument = document; 457 if (rootOffset > 0) { 458 clone.offset(0 - rootOffset); 459 } 460 461 if (canHaveChildren()) { 462 Enumeration children = getChildren(); 463 while (children.hasMoreElements()) { 464 DOMNode child = (DOMNode) children.nextElement(); 465 if (child.fDocument == fDocument) { 466 DOMNode childClone= child.cloneSharingDocument(document, rootOffset); 467 clone.basicAddChild(childClone); 468 } else { 469 DOMNode childClone= (DOMNode)child.clone(); 470 clone.addChild(childClone); 471 } 472 } 473 } 474 return clone; 475 } 476 483 protected void fragment() { 484 if (!isFragmented()) { 485 fIsFragmented= true; 486 if (fParent != null) { 487 fParent.fragment(); 488 } 489 } 490 } 491 494 public char[] getCharacters() { 495 CharArrayBuffer buffer= new CharArrayBuffer(); 496 appendContents(buffer); 497 return buffer.getContents(); 498 } 499 502 public IDOMNode getChild(String name) { 503 DOMNode child = fFirstChild; 504 while (child != null) { 505 String n = child.getName(); 506 if (name == null) { 507 if (n == null) { 508 return child; 509 } 510 } else { 511 if (name.equals(n)) { 512 return child; 513 } 514 } 515 child = child.fNextNode; 516 } 517 return null; 518 } 519 522 public Enumeration getChildren() { 523 return new SiblingEnumeration(fFirstChild); 524 } 525 536 public String getContents() { 537 CharArrayBuffer buffer= new CharArrayBuffer(); 538 appendContents(buffer); 539 return buffer.toString(); 540 } 541 546 protected DOMNode getDetailedNode() { 547 return this; 548 } 549 553 protected char[] getDocument() { 554 return fDocument; 555 } 556 560 public int getEndPosition() { 561 return fSourceRange[1]; 562 } 563 566 protected IDOMFactory getFactory() { 567 return new DOMFactory(); 568 } 569 572 public IDOMNode getFirstChild() { 573 return fFirstChild; 574 } 575 578 public int getInsertionPosition() { 579 return fInsertionPosition; 580 } 581 585 protected boolean getMask(int mask) { 586 return (fStateMask & mask) > 0; 587 } 588 591 public String getName() { 592 return fName; 593 } 594 597 protected char[] getNameContents() { 598 if (isNameAltered()) { 599 return fName.toCharArray(); 600 } else { 601 if (fName == null || fNameRange[0] < 0) { 602 return null; 603 } else { 604 int length = fNameRange[1] + 1 - fNameRange[0]; 605 char[] result = new char[length]; 606 System.arraycopy(fDocument, fNameRange[0], result, 0, length); 607 return result; 608 } 609 } 610 } 611 614 public IDOMNode getNextNode() { 615 return fNextNode; 616 } 617 620 public IDOMNode getParent() { 621 return fParent; 622 } 623 627 protected int getParentEndDeclaration() { 628 IDOMNode parent = getParent(); 629 if (parent == null) { 630 return 0; 631 } else { 632 if (parent instanceof IDOMCompilationUnit) { 633 return 0; 634 } else { 635 return ((DOMType)parent).getOpenBodyEnd(); 636 } 637 } 638 } 639 642 public IDOMNode getPreviousNode() { 643 return fPreviousNode; 644 } 645 648 protected IDOMNode getRoot() { 649 if (fParent == null) { 650 return this; 651 } else { 652 return fParent.getRoot(); 653 } 654 } 655 659 public int getStartPosition() { 660 return fSourceRange[0]; 661 } 662 665 public void insertSibling(IDOMNode sibling) throws IllegalArgumentException , DOMException { 666 if (sibling == null) { 668 throw new IllegalArgumentException (Messages.dom_addNullSibling); 669 } 670 if (fParent == null) { 671 throw new DOMException(Messages.dom_addSiblingBeforeRoot); 672 } 673 if (!fParent.isAllowableChild(sibling)) { 674 throw new DOMException(Messages.dom_addIncompatibleSibling); 675 } 676 if (sibling.getParent() != null) { 677 throw new DOMException(Messages.dom_addSiblingWithParent); 678 } 679 683 if (sibling == getRoot()) { 684 throw new DOMException(Messages.dom_addAncestorAsSibling); 685 } 686 687 DOMNode node= (DOMNode)sibling; 688 689 if (node.getDocument() != getDocument()) { 692 node.localizeContents(); 693 } 694 695 if (fPreviousNode == null) { 697 fParent.fFirstChild= node; 698 } else { 699 fPreviousNode.fNextNode= node; 700 } 701 node.fParent= fParent; 702 node.fPreviousNode= fPreviousNode; 703 node.fNextNode= this; 704 fPreviousNode= node; 705 706 if (node.getNodeType() == IDOMNode.METHOD && ((IDOMMethod)node).isConstructor()) { 708 node.fragment(); 709 } else { 710 fParent.fragment(); 711 } 712 } 713 716 public boolean isAllowableChild(IDOMNode node) { 717 return false; 718 } 719 725 protected boolean isContentMergableWith(DOMNode node) { 726 return !node.isFragmented() && !isFragmented() && node.getDocument() == getDocument() && 727 node.getEndPosition() + 1 == getStartPosition(); 728 } 729 734 protected boolean isDetailed() { 735 return getMask(MASK_DETAILED_SOURCE_INDEXES); 736 } 737 743 protected boolean isFragmented() { 744 return fIsFragmented; 745 } 746 750 protected boolean isNameAltered() { 751 return getMask(MASK_NAME_ALTERED); 752 } 753 760 public boolean isSignatureEqual(IDOMNode node) { 761 return getNodeType() == node.getNodeType() && getName().equals(node.getName()); 762 } 763 770 protected void localizeContents() { 771 772 DOMNode clone= (DOMNode)clone(); 773 shareContents(clone); 774 775 } 776 779 protected abstract DOMNode newDOMNode(); 780 785 void normalize(ILineStartFinder finder) { 786 if (getPreviousNode() == null) 787 normalizeStartPosition(getParentEndDeclaration(), finder); 788 789 if (canHaveChildren()) { 791 Enumeration children = getChildren(); 792 while(children.hasMoreElements()) 793 ((DOMNode)children.nextElement()).normalize(finder); 794 } 795 796 normalizeEndPosition(finder, (DOMNode)getNextNode()); 797 } 798 801 void normalizeEndPosition(ILineStartFinder finder, DOMNode next) { 802 if (next == null) { 803 DOMNode parent = (DOMNode) getParent(); 806 if (parent == null || parent instanceof DOMCompilationUnit) { 807 setSourceRangeEnd(fDocument.length - 1); 808 } else { 809 int temp = ((DOMType)parent).getCloseBodyPosition() - 1; 811 setSourceRangeEnd(temp); 812 fInsertionPosition = Math.max(finder.getLineStart(temp + 1), getEndPosition()); 813 } 814 } else { 815 int temp = next.getStartPosition() - 1; 817 fInsertionPosition = Math.max(finder.getLineStart(temp + 1), getEndPosition()); 818 next.normalizeStartPosition(getEndPosition(), finder); 819 setSourceRangeEnd(next.getStartPosition() - 1); 820 } 821 } 822 825 void normalizeStartPosition(int previousEnd, ILineStartFinder finder) { 826 int nodeStart = getStartPosition(); 827 int lineStart = finder.getLineStart(nodeStart); 828 if (nodeStart > lineStart && (lineStart > previousEnd || (previousEnd == 0 && lineStart == 0))) 829 setStartPosition(lineStart); 830 } 831 834 protected void offset(int offset) { 835 offsetRange(fNameRange, offset); 836 offsetRange(fSourceRange, offset); 837 } 838 841 protected void offsetRange(int[] range, int offset) { 842 for (int i= 0; i < range.length; i++) { 843 range[i]+=offset; 844 if (range[i] < 0) { 845 range[i]= -1; 846 } 847 } 848 } 849 852 protected int[] rangeCopy(int[] range) { 853 int[] copy= new int[range.length]; 854 for (int i= 0; i < range.length; i++) { 855 copy[i]= range[i]; 856 } 857 return copy; 858 } 859 868 public void remove() { 869 870 if (fParent != null) { 871 fParent.fragment(); 872 } 873 874 if (fNextNode != null) { 876 fNextNode.fPreviousNode= fPreviousNode; 877 } 878 if (fPreviousNode != null) { 879 fPreviousNode.fNextNode= fNextNode; 880 } 881 if (fParent != null) { 883 if (fParent.fFirstChild == this) { 884 fParent.fFirstChild= fNextNode; 885 } 886 if (fParent.fLastChild == this) { 887 fParent.fLastChild= fPreviousNode; 888 } 889 } 890 fParent= null; 892 fNextNode= null; 893 fPreviousNode= null; 894 } 895 899 protected void setMask(int mask, boolean on) { 900 if (on) { 901 fStateMask |= mask; 902 } else { 903 fStateMask &= ~mask; 904 } 905 } 906 909 public void setName(String name) { 910 fName= name; 911 setNameAltered(true); 912 fragment(); 913 } 914 919 protected void setNameAltered(boolean altered) { 920 setMask(MASK_NAME_ALTERED, altered); 921 } 922 927 protected void setSourceRangeEnd(int end) { 928 fSourceRange[1]= end; 929 } 930 935 protected void setStartPosition(int start) { 936 fSourceRange[0]= start; 937 } 938 945 protected void shareContents(DOMNode node) { 946 fDocument= node.fDocument; 947 fIsFragmented= node.fIsFragmented; 948 fName= node.fName; 949 fNameRange= rangeCopy(node.fNameRange); 950 fSourceRange= rangeCopy(node.fSourceRange); 951 fStateMask= node.fStateMask; 952 953 954 if (canHaveChildren()) { 955 Enumeration myChildren= getChildren(); 956 Enumeration otherChildren= node.getChildren(); 957 DOMNode myChild, otherChild; 958 while (myChildren.hasMoreElements()) { 959 myChild= (DOMNode)myChildren.nextElement(); 960 otherChild= (DOMNode)otherChildren.nextElement(); 961 myChild.shareContents(otherChild); 962 } 963 } 964 } 965 968 public abstract String toString(); 969 } 970 | Popular Tags |