package org.eclipse.core.internal.dtree;
import org.eclipse.core.internal.utils.*;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
public class DataTreeNode extends AbstractDataTreeNode {
protected Object data;
public DataTreeNode(String name, Object data) {
super(name, AbstractDataTreeNode.NO_CHILDREN);
this.data = data;
}
public DataTreeNode(String name, Object data, AbstractDataTreeNode[] children) {
super(name, children);
this.data = data;
}
@Override
AbstractDataTreeNode asBackwardDelta(DeltaDataTree myTree, DeltaDataTree parentTree, IPath key) {
if (parentTree.includes(key))
return parentTree.copyCompleteSubtree(key);
return new DeletedNode(name);
}
@Override
AbstractDataTreeNode asReverseComparisonNode(IComparator comparator) {
NodeComparison comparison = null;
try {
comparison = ((NodeComparison) data).asReverseComparison(comparator);
} catch (ClassCastException e) {
Assert.isTrue(false, Messages.dtree_reverse);
}
int nextChild = 0;
for (AbstractDataTreeNode c : children) {
AbstractDataTreeNode child = c.asReverseComparisonNode(comparator);
if (child != null) {
children[nextChild++] = child;
}
}
if (nextChild == 0 && comparison.getUserComparison() == 0) {
return null;
}
data = comparison;
if (nextChild < children.length) {
AbstractDataTreeNode[] newChildren = new AbstractDataTreeNode[nextChild];
System.arraycopy(children, 0, newChildren, 0, nextChild);
children = newChildren;
}
return this;
}
AbstractDataTreeNode compareWith(DataTreeNode other, IComparator comparator) {
AbstractDataTreeNode[] comparedChildren = compareWith(children, other.children, comparator);
Object oldData = data;
Object newData = other.data;
int userComparison = 0;
if (name != null) {
userComparison = comparator.compare(oldData, newData);
}
return new DataTreeNode(name, new NodeComparison(oldData, newData, NodeComparison.K_CHANGED, userComparison), comparedChildren);
}
@Override
AbstractDataTreeNode compareWithParent(IPath key, DeltaDataTree parent, IComparator comparator) {
if (!parent.includes(key))
return convertToAddedComparisonNode(this, NodeComparison.K_ADDED);
DataTreeNode inParent = (DataTreeNode) parent.copyCompleteSubtree(key);
return inParent.compareWith(this, comparator);
}
@Override
AbstractDataTreeNode copy() {
if (children.length > 0) {
AbstractDataTreeNode[] childrenCopy = new AbstractDataTreeNode[children.length];
System.arraycopy(children, 0, childrenCopy, 0, children.length);
return new DataTreeNode(name, data, childrenCopy);
}
return new DataTreeNode(name, data, children);
}
DataTreeNode copyWithNewChild(String localName, DataTreeNode childNode) {
AbstractDataTreeNode[] children = this.children;
int left = 0;
int right = children.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
int compare = localName.compareTo(children[mid].name);
if (compare < 0) {
right = mid - 1;
} else if (compare > 0) {
left = mid + 1;
} else {
throw new Error();
}
}
AbstractDataTreeNode[] newChildren = new AbstractDataTreeNode[children.length + 1];
System.arraycopy(children, 0, newChildren, 0, left);
childNode.setName(localName);
newChildren[left] = childNode;
System.arraycopy(children, left, newChildren, left + 1, children.length - left);
return new DataTreeNode(this.getName(), this.getData(), newChildren);
}
DataTreeNode copyWithoutChild(String localName) {
int index, newSize;
DataTreeNode newNode;
AbstractDataTreeNode children[];
index = this.indexOfChild(localName);
if (index == -1) {
newNode = (DataTreeNode) this.copy();
} else {
newSize = this.size() - 1;
children = new AbstractDataTreeNode[newSize];
newNode = new DataTreeNode(this.getName(), this.getData(), children);
newNode.copyChildren(0, index - 1, this, 0);
newNode.copyChildren(index, newSize - 1, this, index + 1);
}
return newNode;
}
protected static AbstractDataTreeNode[] forwardDeltaWith(AbstractDataTreeNode[] oldNodes, AbstractDataTreeNode[] newNodes, IComparator comparer) {
if (oldNodes.length == 0 && newNodes.length == 0) {
return NO_CHILDREN;
}
AbstractDataTreeNode[] childDeltas = null;
int numChildDeltas = 0;
int childDeltaMax = 0;
int oldIndex = 0;
int newIndex = 0;
while (oldIndex < oldNodes.length && newIndex < newNodes.length) {
String oldName = oldNodes[oldIndex].name;
String newName = newNodes[newIndex].name;
int compare = oldName.compareTo(newName);
if (compare == 0) {
AbstractDataTreeNode deltaNode = forwardDeltaWithOrNullIfEqual(oldNodes[oldIndex++], newNodes[newIndex++], comparer);
if (deltaNode != null) {
if (numChildDeltas >= childDeltaMax) {
if (childDeltas == null)
childDeltas = new AbstractDataTreeNode[childDeltaMax = 5];
else
System.arraycopy(childDeltas, 0, childDeltas = new AbstractDataTreeNode[childDeltaMax = childDeltaMax * 2 + 1], 0, numChildDeltas);
}
childDeltas[numChildDeltas++] = deltaNode;
}
} else if (compare < 0) {
if (numChildDeltas >= childDeltaMax) {
if (childDeltas == null)
childDeltas = new AbstractDataTreeNode[childDeltaMax = 5];
else
System.arraycopy(childDeltas, 0, childDeltas = new AbstractDataTreeNode[childDeltaMax = childDeltaMax * 2 + 1], 0, numChildDeltas);
}
childDeltas[numChildDeltas++] = new DeletedNode(oldName);
oldIndex++;
} else {
if (numChildDeltas >= childDeltaMax) {
if (childDeltas == null)
childDeltas = new AbstractDataTreeNode[childDeltaMax = 5];
else
System.arraycopy(childDeltas, 0, childDeltas = new AbstractDataTreeNode[childDeltaMax = childDeltaMax * 2 + 1], 0, numChildDeltas);
}
childDeltas[numChildDeltas++] = newNodes[newIndex++];
}
}
while (oldIndex < oldNodes.length) {
if (numChildDeltas >= childDeltaMax) {
if (childDeltas == null)
childDeltas = new AbstractDataTreeNode[childDeltaMax = 5];
else
System.arraycopy(childDeltas, 0, childDeltas = new AbstractDataTreeNode[childDeltaMax = childDeltaMax * 2 + 1], 0, numChildDeltas);
}
childDeltas[numChildDeltas++] = new DeletedNode(oldNodes[oldIndex++].name);
}
while (newIndex < newNodes.length) {
if (numChildDeltas >= childDeltaMax) {
if (childDeltas == null)
childDeltas = new AbstractDataTreeNode[childDeltaMax = 5];
else
System.arraycopy(childDeltas, 0, childDeltas = new AbstractDataTreeNode[childDeltaMax = childDeltaMax * 2 + 1], 0, numChildDeltas);
}
childDeltas[numChildDeltas++] = newNodes[newIndex++];
}
if (numChildDeltas == 0) {
return NO_CHILDREN;
}
if (numChildDeltas < childDeltaMax) {
System.arraycopy(childDeltas, 0, childDeltas = new AbstractDataTreeNode[numChildDeltas], 0, numChildDeltas);
}
return childDeltas;
}
protected AbstractDataTreeNode forwardDeltaWith(DataTreeNode other, IComparator comparer) {
AbstractDataTreeNode deltaNode = forwardDeltaWithOrNullIfEqual(this, other, comparer);
if (deltaNode == null) {
return new NoDataDeltaNode(name, NO_CHILDREN);
}
return deltaNode;
}
protected static AbstractDataTreeNode forwardDeltaWithOrNullIfEqual(AbstractDataTreeNode oldNode, AbstractDataTreeNode newNode, IComparator comparer) {
AbstractDataTreeNode[] childDeltas = forwardDeltaWith(oldNode.children, newNode.children, comparer);
Object newData = newNode.getData();
if (comparer.compare(oldNode.getData(), newData) == 0) {
if (childDeltas.length == 0) {
return null;
}
return new NoDataDeltaNode(newNode.name, childDeltas);
}
return new DataDeltaNode(newNode.name, newData, childDeltas);
}
@Override
public Object getData() {
return data;
}
@Override
boolean hasData() {
return true;
}
void setData(Object o) {
data = o;
}
@Override
AbstractDataTreeNode simplifyWithParent(IPath key, DeltaDataTree parent, IComparator comparer) {
if (!parent.includes(key)) {
return this;
}
DataTreeNode parentsNode = (DataTreeNode) parent.copyCompleteSubtree(key);
return parentsNode.forwardDeltaWith(this, comparer);
}
@Override
public void storeStrings(StringPool set) {
super.storeStrings(set);
Object o = data;
if (o instanceof IStringPoolParticipant)
((IStringPoolParticipant) o).shareStrings(set);
}
@Override
public String toString() {
return "a DataTreeNode(" + this.getName() + ") with " + getChildren().length + " children.";
}
@Override
int type() {
return T_COMPLETE_NODE;
}
}