1 11 package org.eclipse.core.internal.dtree; 12 13 import org.eclipse.core.internal.utils.Messages; 14 import org.eclipse.core.internal.utils.StringPool; 15 import org.eclipse.core.runtime.*; 16 17 37 38 public class DeltaDataTree extends AbstractDataTree { 39 private AbstractDataTreeNode rootNode; 40 private DeltaDataTree parent; 41 42 45 public DeltaDataTree() { 46 this.empty(); 47 } 48 49 54 public DeltaDataTree(AbstractDataTreeNode rootNode) { 55 this.rootNode = rootNode; 56 this.parent = null; 57 } 58 59 protected DeltaDataTree(AbstractDataTreeNode rootNode, DeltaDataTree parent) { 60 this.rootNode = rootNode; 61 this.parent = parent; 62 } 63 64 71 protected void addChild(IPath parentKey, String localName, AbstractDataTreeNode childNode) { 72 if (!includes(parentKey)) 73 handleNotFound(parentKey); 74 childNode.setName(localName); 75 this.assembleNode(parentKey, new NoDataDeltaNode(parentKey.lastSegment(), childNode)); 76 } 77 78 85 DeltaDataTree asBackwardDelta() { 86 if (getParent() == null) 87 return newEmptyDeltaTree(); 88 return new DeltaDataTree(getRootNode().asBackwardDelta(this, getParent(), rootKey()), this); 89 } 90 91 98 public DeltaDataTree asReverseComparisonTree(IComparator comparator) { 99 100 if (rootNode.getName() == null) { 101 AbstractDataTreeNode[] children = rootNode.getChildren(); 102 int nextChild = 0; 103 for (int i = 0; i < children.length; i++) { 104 AbstractDataTreeNode newChild = children[i].asReverseComparisonNode(comparator); 105 if (newChild != null) { 106 children[nextChild++] = newChild; 107 } 108 } 109 110 if (nextChild < children.length) { 111 AbstractDataTreeNode[] newChildren = new AbstractDataTreeNode[nextChild]; 112 System.arraycopy(children, 0, newChildren, 0, nextChild); 113 rootNode.setChildren(newChildren); 114 } 115 } else { 116 rootNode.asReverseComparisonNode(comparator); 117 } 118 return this; 119 } 120 121 129 protected void assembleNode(IPath key, AbstractDataTreeNode deltaNode) { 130 rootNode = rootNode.assembleWith(deltaNode, key, 0); 131 } 132 133 152 public DeltaDataTree assembleWithForwardDelta(DeltaDataTree deltaTree) { 153 return new DeltaDataTree(getRootNode().assembleWith(deltaTree.getRootNode()), this); 154 } 155 156 161 protected DeltaDataTree basicCompare(DeltaDataTree other, IComparator comparator, IPath path) { 162 DeltaDataTree newTree; 163 if (this == other) { 164 newTree = new DeltaDataTree(); 165 newTree.setData(Path.ROOT, new NodeComparison(null, null, 0, 0)); 166 } else if (other.hasAncestor(this)) { 167 AbstractDataTreeNode assembled = other.searchNodeAt(path); 168 DeltaDataTree tree = other; 169 170 171 while ((tree = tree.getParent()) != this) { 172 AbstractDataTreeNode treeNode = tree.searchNodeAt(path); 174 if (treeNode != null) { 175 assembled = treeNode.assembleWith(assembled); 176 } 177 } 178 AbstractDataTreeNode comparedRoot = assembled.compareWithParent(path, this, comparator); 179 newTree = new DeltaDataTree(comparedRoot); 180 } else if (this.hasAncestor(other)) { 181 AbstractDataTreeNode assembled = this.asBackwardDelta().searchNodeAt(path); 182 DeltaDataTree tree = this; 183 184 185 while ((tree = tree.getParent()) != other) { 186 assembled = assembled.assembleWith(tree.asBackwardDelta().searchNodeAt(path)); 187 } 188 AbstractDataTreeNode comparedRoot = assembled.compareWithParent(path, this, comparator); 189 newTree = new DeltaDataTree(comparedRoot); 190 } else { 191 DataTreeNode thisCompleteRoot = (DataTreeNode) this.copyCompleteSubtree(path); 193 DataTreeNode otherCompleteRoot = (DataTreeNode) other.copyCompleteSubtree(path); 194 AbstractDataTreeNode comparedRoot = thisCompleteRoot.compareWith(otherCompleteRoot, comparator); 195 newTree = new DeltaDataTree(comparedRoot); 196 } 197 newTree.immutable(); 198 return newTree; 199 } 200 201 214 public DeltaDataTree collapseTo(DeltaDataTree collapseTo, IComparator comparator) { 215 if (this == collapseTo || getParent() == collapseTo) { 216 return this; 218 } 219 DeltaDataTree c = collapseTo.forwardDeltaWith(this, comparator); 222 223 this.parent = collapseTo; 225 this.rootNode = c.rootNode; 226 return this; 227 } 228 229 235 public DeltaDataTree compareWith(DeltaDataTree other, IComparator comparator) { 236 237 DeltaDataTree newTree; 238 if (this == other) { 239 newTree = new DeltaDataTree(); 240 newTree.setData(Path.ROOT, new NodeComparison(null, null, 0, 0)); 241 } else if (other.hasAncestor(this)) { 242 243 AbstractDataTreeNode assembled = other.getRootNode(); 244 DeltaDataTree tree = other; 245 246 247 while ((tree = tree.getParent()) != this) { 248 assembled = tree.getRootNode().assembleWith(assembled); 249 } 250 AbstractDataTreeNode comparedRoot = assembled.compareWithParent(rootKey(), this, comparator); 251 newTree = new DeltaDataTree(comparedRoot); 252 } else if (this.hasAncestor(other)) { 253 AbstractDataTreeNode assembled = this.asBackwardDelta().getRootNode(); 254 DeltaDataTree tree = this; 255 256 257 while ((tree = tree.getParent()) != other) { 258 assembled = assembled.assembleWith(tree.asBackwardDelta().getRootNode()); 259 } 260 AbstractDataTreeNode comparedRoot = assembled.compareWithParent(rootKey(), this, comparator); 261 newTree = new DeltaDataTree(comparedRoot); 262 } else { 263 DataTreeNode thisCompleteRoot = (DataTreeNode) this.copyCompleteSubtree(rootKey()); 265 DataTreeNode otherCompleteRoot = (DataTreeNode) other.copyCompleteSubtree(rootKey()); 266 AbstractDataTreeNode comparedRoot = thisCompleteRoot.compareWith(otherCompleteRoot, comparator); 267 newTree = new DeltaDataTree(comparedRoot); 268 } 269 newTree.immutable(); 270 return newTree; 271 } 272 273 277 public DeltaDataTree compareWith(DeltaDataTree other, IComparator comparator, IPath path) { 278 279 if (this.includes(path)) { 280 if (other.includes(path)) 281 return basicCompare(other, comparator, path); 282 283 return new DeltaDataTree(AbstractDataTreeNode.convertToRemovedComparisonNode(this.copyCompleteSubtree(path), comparator.compare(this.getData(path), null))); 284 } 285 if (other.includes(path)) 286 287 return new DeltaDataTree(AbstractDataTreeNode.convertToAddedComparisonNode(other.copyCompleteSubtree(path), comparator.compare(null, other.getData(path)))); 288 289 return DeltaDataTree.createEmptyDelta(); 290 } 291 292 295 protected AbstractDataTree copy() { 296 return new DeltaDataTree(rootNode, parent); 297 } 298 299 305 public AbstractDataTreeNode copyCompleteSubtree(IPath key) { 306 AbstractDataTreeNode node = searchNodeAt(key); 307 if (node == null) { 308 handleNotFound(key); 309 return null; 310 } 311 if (node.isDelta()) 312 return naiveCopyCompleteSubtree(key); 313 return node.copy(); 315 } 316 317 320 public void createChild(IPath parentKey, String localName) { 321 createChild(parentKey, localName, null); 322 } 323 324 327 public void createChild(IPath parentKey, String localName, Object data) { 328 if (isImmutable()) 329 handleImmutableTree(); 330 addChild(parentKey, localName, new DataTreeNode(localName, data)); 331 } 332 333 338 static DeltaDataTree createEmptyDelta() { 339 340 DeltaDataTree newTree = new DeltaDataTree(); 341 newTree.emptyDelta(); 342 return newTree; 343 } 344 345 349 protected AbstractDataTree createInstance() { 350 return new DeltaDataTree(); 351 } 352 353 356 public void createSubtree(IPath key, AbstractDataTreeNode node) { 357 if (isImmutable()) 358 handleImmutableTree(); 359 if (key.isRoot()) { 360 setParent(null); 361 setRootNode(node); 362 } else { 363 addChild(key.removeLastSegments(1), key.lastSegment(), node); 364 } 365 } 366 367 370 public void deleteChild(IPath parentKey, String localName) { 371 if (isImmutable()) 372 handleImmutableTree(); 373 374 IPath childKey = parentKey.append(localName); 375 if (!includes(childKey)) 376 handleNotFound(childKey); 377 assembleNode(parentKey, new NoDataDeltaNode(parentKey.lastSegment(), new DeletedNode(localName))); 378 } 379 380 384 public void empty() { 385 rootNode = new DataTreeNode(null, null); 386 parent = null; 387 } 388 389 394 void emptyDelta() { 395 rootNode = new NoDataDeltaNode(null); 396 } 397 398 404 public AbstractDataTreeNode findNodeAt(IPath key) { 405 AbstractDataTreeNode node = rootNode; 406 int segmentCount = key.segmentCount(); 407 for (int i = 0; i < segmentCount; i++) { 408 node = node.childAtOrNull(key.segment(i)); 409 if (node == null) 410 return null; 411 } 412 return node; 413 } 414 415 437 public DeltaDataTree forwardDeltaWith(DeltaDataTree sourceTree, IComparator comparer) { 438 DeltaDataTree newTree; 439 if (this == sourceTree) { 440 newTree = this.newEmptyDeltaTree(); 441 } else if (sourceTree.hasAncestor(this)) { 442 AbstractDataTreeNode assembled = sourceTree.getRootNode(); 443 DeltaDataTree treeParent = sourceTree; 444 445 446 while ((treeParent = treeParent.getParent()) != this) { 447 assembled = treeParent.getRootNode().assembleWith(assembled); 448 } 449 newTree = new DeltaDataTree(assembled, this); 450 newTree.simplify(comparer); 451 } else if (this.hasAncestor(sourceTree)) { 452 newTree = sourceTree.forwardDeltaWith(this, comparer); 454 newTree = newTree.asBackwardDelta(); 455 } else { 456 DataTreeNode thisCompleteRoot = (DataTreeNode) this.copyCompleteSubtree(rootKey()); 457 DataTreeNode sourceTreeCompleteRoot = (DataTreeNode) sourceTree.copyCompleteSubtree(rootKey()); 458 AbstractDataTreeNode deltaRoot = thisCompleteRoot.forwardDeltaWith(sourceTreeCompleteRoot, comparer); 459 newTree = new DeltaDataTree(deltaRoot, this); 460 } 461 newTree.immutable(); 462 return newTree; 463 } 464 465 468 public int getChildCount(IPath parentKey) { 469 return getChildNodes(parentKey).length; 470 } 471 472 475 protected AbstractDataTreeNode[] getChildNodes(IPath parentKey) { 476 477 484 485 AbstractDataTreeNode[] childNodes = null; 486 int keyLength = parentKey.segmentCount(); 487 for (DeltaDataTree tree = this; tree != null; tree = tree.parent) { 488 AbstractDataTreeNode node = tree.rootNode; 489 boolean complete = !node.isDelta(); 490 for (int i = 0; i < keyLength; i++) { 491 node = node.childAtOrNull(parentKey.segment(i)); 492 if (node == null) { 493 break; 494 } 495 if (!node.isDelta()) { 496 complete = true; 497 } 498 } 499 if (node != null) { 500 if (node.isDeleted()) { 501 break; 502 } 503 if (childNodes == null) { 504 childNodes = node.children; 505 } else { 506 childNodes = AbstractDataTreeNode.assembleWith(node.children, childNodes, !complete); 509 } 510 } 511 if (complete) { 512 if (childNodes != null) { 513 return childNodes; 514 } 515 break; 517 } 518 } 519 if (childNodes != null) { 520 Assert.isTrue(false, Messages.dtree_malformedTree); 523 } 524 525 handleNotFound(parentKey); 527 return null; } 529 530 533 public IPath[] getChildren(IPath parentKey) { 534 AbstractDataTreeNode[] childNodes = getChildNodes(parentKey); 535 int len = childNodes.length; 536 if (len == 0) 537 return NO_CHILDREN; 538 IPath[] answer = new IPath[len]; 539 for (int i = 0; i < len; ++i) 540 answer[i] = parentKey.append(childNodes[i].name); 541 return answer; 542 } 543 544 550 public Object getData(IPath key) { 551 552 559 560 int keyLength = key.segmentCount(); 561 for (DeltaDataTree tree = this; tree != null; tree = tree.parent) { 562 AbstractDataTreeNode node = tree.rootNode; 563 boolean complete = !node.isDelta(); 564 for (int i = 0; i < keyLength; i++) { 565 node = node.childAtOrNull(key.segment(i)); 566 if (node == null) { 567 break; 568 } 569 if (!node.isDelta()) { 570 complete = true; 571 } 572 } 573 if (node != null) { 574 if (node.hasData()) { 575 return node.getData(); 576 } else if (node.isDeleted()) { 577 break; 578 } 579 } 580 if (complete) { 581 break; 583 } 584 } 585 handleNotFound(key); 586 return null; } 588 589 592 public String getNameOfChild(IPath parentKey, int index) { 593 AbstractDataTreeNode[] childNodes = getChildNodes(parentKey); 594 return childNodes[index].name; 595 } 596 597 602 public String [] getNamesOfChildren(IPath parentKey) { 603 AbstractDataTreeNode[] childNodes = getChildNodes(parentKey); 604 int len = childNodes.length; 605 String [] namesOfChildren = new String [len]; 606 for (int i = 0; i < len; ++i) 607 namesOfChildren[i] = childNodes[i].name; 608 return namesOfChildren; 609 } 610 611 614 public DeltaDataTree getParent() { 615 return parent; 616 } 617 618 621 protected AbstractDataTreeNode getRootNode() { 622 return rootNode; 623 } 624 625 630 protected boolean hasAncestor(DeltaDataTree ancestor) { 631 DeltaDataTree myParent = this; 632 while ((myParent = myParent.getParent()) != null) { 633 if (myParent == ancestor) { 634 return true; 635 } 636 } 637 return false; 638 } 639 640 644 public boolean includes(IPath key) { 645 return searchNodeAt(key) != null; 646 } 647 648 public boolean isEmptyDelta() { 649 return rootNode.getChildren().length == 0; 650 } 651 652 660 public DataTreeLookup lookup(IPath key) { 661 int keyLength = key.segmentCount(); 662 for (DeltaDataTree tree = this; tree != null; tree = tree.parent) { 663 AbstractDataTreeNode node = tree.rootNode; 664 boolean complete = !node.isDelta(); 665 for (int i = 0; i < keyLength; i++) { 666 node = node.childAtOrNull(key.segment(i)); 667 if (node == null) { 668 break; 669 } 670 complete |= !node.isDelta(); 671 } 672 if (node != null) { 673 if (node.hasData()) { 674 return DataTreeLookup.newLookup(key, true, node.getData(), tree == this); 675 } else if (node.isDeleted()) { 676 break; 677 } 678 } 679 if (complete) { 680 break; 682 } 683 } 684 return DataTreeLookup.newLookup(key, false, null); 685 } 686 687 698 public DataTreeLookup lookupIgnoreCase(IPath key) { 699 int keyLength = key.segmentCount(); 700 for (DeltaDataTree tree = this; tree != null; tree = tree.parent) { 701 AbstractDataTreeNode node = tree.rootNode; 702 boolean complete = !node.isDelta(); 703 for (int i = 0; i < keyLength; i++) { 704 node = node.childAtIgnoreCase(key.segment(i)); 705 if (node == null) { 706 break; 707 } 708 complete |= !node.isDelta(); 709 } 710 if (node != null) { 711 if (node.hasData()) { 712 return DataTreeLookup.newLookup(key, true, node.getData(), tree == this); 713 } else if (node.isDeleted()) { 714 break; 715 } 716 } 717 if (complete) { 718 break; 720 } 721 } 722 return DataTreeLookup.newLookup(key, false, null); 723 } 724 725 730 public void makeComplete() { 731 AbstractDataTreeNode assembled = getRootNode(); 732 DeltaDataTree myParent = getParent(); 733 while (myParent != null) { 734 assembled = myParent.getRootNode().assembleWith(assembled); 735 myParent = myParent.getParent(); 736 } 737 setRootNode(assembled); 738 setParent(null); 739 } 740 741 748 protected AbstractDataTreeNode naiveCopyCompleteSubtree(IPath key) { 749 String [] childNames = getNamesOfChildren(key); 750 int numChildren = childNames.length; 751 AbstractDataTreeNode[] childNodes; 752 if (numChildren == 0) { 753 childNodes = AbstractDataTreeNode.NO_CHILDREN; 754 } else { 755 childNodes = new AbstractDataTreeNode[numChildren]; 756 757 for (int i = numChildren; --i >= 0;) { 758 childNodes[i] = copyCompleteSubtree(key.append(childNames[i])); 759 } 760 } 761 return new DataTreeNode(key.lastSegment(), getData(key), childNodes); 762 } 763 764 770 public DeltaDataTree newEmptyDeltaTree() { 771 if (!isImmutable()) 772 throw new IllegalArgumentException (Messages.dtree_notImmutable); 773 DeltaDataTree newTree = (DeltaDataTree) this.copy(); 774 newTree.setParent(this); 775 newTree.emptyDelta(); 776 return newTree; 777 } 778 779 790 public DeltaDataTree reroot() { 791 792 reroot(this); 793 return this; 794 } 795 796 809 protected void reroot(DeltaDataTree sourceTree) { 810 if (!sourceTree.isImmutable()) 811 handleImmutableTree(); 812 DeltaDataTree sourceParent = sourceTree.getParent(); 813 if (sourceParent == null) 814 return; 815 this.reroot(sourceParent); 816 DeltaDataTree backwardDelta = sourceTree.asBackwardDelta(); 817 DeltaDataTree complete = sourceParent.assembleWithForwardDelta(sourceTree); 818 sourceTree.setRootNode(complete.getRootNode()); 819 sourceTree.setParent(null); 820 sourceParent.setRootNode(backwardDelta.getRootNode()); 821 sourceParent.setParent(sourceTree); 822 } 823 824 831 public AbstractDataTreeNode safeCopyCompleteSubtree(IPath key) { 832 AbstractDataTreeNode node = searchNodeAt(key); 833 if (node == null) 834 return null; 835 if (node.isDelta()) 836 return safeNaiveCopyCompleteSubtree(key); 837 return node.copy(); 839 } 840 841 849 protected AbstractDataTreeNode safeNaiveCopyCompleteSubtree(IPath key) { 850 try { 851 String [] childNames = getNamesOfChildren(key); 852 int numChildren = childNames.length; 853 AbstractDataTreeNode[] childNodes; 854 if (numChildren == 0) { 855 childNodes = AbstractDataTreeNode.NO_CHILDREN; 856 } else { 857 childNodes = new AbstractDataTreeNode[numChildren]; 858 859 int actualChildCount = 0; 860 for (int i = numChildren; --i >= 0;) { 861 childNodes[i] = safeCopyCompleteSubtree(key.append(childNames[i])); 862 if (childNodes[i] != null) 863 actualChildCount++; 864 } 865 if (actualChildCount < numChildren) { 867 AbstractDataTreeNode[] actualChildNodes = new AbstractDataTreeNode[actualChildCount]; 868 for (int iOld = 0, iNew = 0; iOld < numChildren; iOld++) 869 if (childNodes[iOld] != null) 870 actualChildNodes[iNew++] = childNodes[iOld]; 871 childNodes = actualChildNodes; 872 } 873 } 874 return new DataTreeNode(key.lastSegment(), getData(key), childNodes); 875 } catch (ObjectNotFoundException e) { 876 return null; 877 } 878 } 879 880 884 protected AbstractDataTreeNode searchNodeAt(IPath key) { 885 int keyLength = key.segmentCount(); 886 for (DeltaDataTree tree = this; tree != null; tree = tree.parent) { 887 AbstractDataTreeNode node = tree.rootNode; 888 boolean complete = !node.isDelta(); 889 for (int i = 0; i < keyLength; i++) { 890 node = node.childAtOrNull(key.segment(i)); 891 if (node == null) { 892 break; 893 } 894 if (!node.isDelta()) { 895 complete = true; 896 } 897 } 898 if (node != null) { 899 if (node.isDeleted()) 900 break; 901 return node; 902 } 903 if (complete) { 904 break; 906 } 907 } 908 return null; 909 } 910 911 914 public void setData(IPath key, Object data) { 915 if (isImmutable()) 916 handleImmutableTree(); 917 if (!includes(key)) 918 handleNotFound(key); 919 assembleNode(key, new DataDeltaNode(key.lastSegment(), data)); 920 } 921 922 925 protected void setParent(DeltaDataTree aTree) { 926 parent = aTree; 927 } 928 929 932 void setRootNode(AbstractDataTreeNode aNode) { 933 rootNode = aNode; 934 } 935 936 942 protected void simplify(IComparator comparer) { 943 if (parent == null) 944 return; 945 setRootNode(rootNode.simplifyWithParent(rootKey(), parent, comparer)); 946 } 947 948 951 public void storeStrings(StringPool set) { 952 AbstractDataTreeNode root = rootNode; 954 DeltaDataTree dad = parent; 955 if (root != null) 956 root.storeStrings(set); 957 if (dad != null) 958 dad.storeStrings(set); 959 } 960 } 961 | Popular Tags |