All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.core.internal.dtree.DataTreeNode Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2000, 2014 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.internal.dtree;

import org.eclipse.core.internal.utils.*;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;

/**
 * DataTreeNodes are the nodes of a DataTree.  Their
 * information and their subtrees are complete, and do not represent deltas on
 * another node or subtree.
 */
public class DataTreeNode extends AbstractDataTreeNode {
	protected Object data;

	/**
	 * Creates a new node
	 *
	 * @param name name of node
	 * @param data data for node
	 */
	public DataTreeNode(String name, Object data) {
		super(name, AbstractDataTreeNode.NO_CHILDREN);
		this.data = data;
	}

	/**
	 * Creates a new node
	 *
	 * @param name name of node
	 * @param data data for node
	 * @param children children for new node
	 */
	public DataTreeNode(String name, Object data, AbstractDataTreeNode[] children) {
		super(name, children);
		this.data = data;
	}

	/**
	 * @see AbstractDataTreeNode#asBackwardDelta(DeltaDataTree, DeltaDataTree, IPath)
	 */
	@Override
	AbstractDataTreeNode asBackwardDelta(DeltaDataTree myTree, DeltaDataTree parentTree, IPath key) {
		if (parentTree.includes(key))
			return parentTree.copyCompleteSubtree(key);
		return new DeletedNode(name);
	}

	/**
	 * If this node is a node in a comparison tree, this method reverses
	 * the comparison for this node and all children.  Returns null
	 * if this node should no longer be included in the comparison tree.
	 */
	@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) {
			/* no children and no change */
			return null;
		}

		/* set the new data */
		data = comparison;

		/* shrink child array as necessary */
		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;

		/* don't allow comparison of implicit root node */
		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);
	}

	/**
	 * Creates and returns a new copy of the receiver.
	 */
	@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);
	}

	/**
	 * Returns a new node containing a child with the given local name in
	 * addition to the receiver's current children and data.
	 *
	 * @param localName
	 *	name of new child
	 * @param childNode
	 *	new child node
	 */
	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(); // it shouldn't have been here yet
			}
		}

		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);
	}

	/**
	 * Returns a new node without the specified child, but with the rest
	 * of the receiver's current children and its data.
	 *
	 * @param localName
	 *	name of child to exclude
	 */
	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); //#from:to:with:startingAt:
			newNode.copyChildren(index, newSize - 1, this, index + 1);
		}
		return newNode;
	}

	/**
	 * Returns an array of delta nodes representing the forward delta between
	 * the given two lists of nodes.
	 * The given nodes must all be complete nodes.
	 */
	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;

		// do a merge
		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++];
		}

		// trim size of result
		if (numChildDeltas == 0) {
			return NO_CHILDREN;
		}
		if (numChildDeltas < childDeltaMax) {
			System.arraycopy(childDeltas, 0, childDeltas = new AbstractDataTreeNode[numChildDeltas], 0, numChildDeltas);
		}
		return childDeltas;
	}

	/**
	 * Returns a node representing the forward delta between
	 * the given two (complete) nodes.
	 */
	protected AbstractDataTreeNode forwardDeltaWith(DataTreeNode other, IComparator comparer) {
		AbstractDataTreeNode deltaNode = forwardDeltaWithOrNullIfEqual(this, other, comparer);
		if (deltaNode == null) {
			return new NoDataDeltaNode(name, NO_CHILDREN);
		}
		return deltaNode;
	}

	/**
	 * Returns a node representing the forward delta between
	 * the given two (complete) nodes, or null if the two nodes are equal.
	 * Although typed as abstract nodes, the given nodes must be complete.
	 */
	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);
	}

	/**
	 * Returns the data for the node
	 */
	@Override
	public Object getData() {
		return data;
	}

	/**
	 * Returns true if the receiver can carry data, false otherwise.
	 */
	@Override
	boolean hasData() {
		return true;
	}

	/**
	 * Sets the data for the node
	 */
	void setData(Object o) {
		data = o;
	}

	/**
	 * Simplifies the given node, and answers its replacement.
	 */
	@Override
	AbstractDataTreeNode simplifyWithParent(IPath key, DeltaDataTree parent, IComparator comparer) {
		/* If not in parent, can't be simplified */
		if (!parent.includes(key)) {
			return this;
		}
		/* Can't just call simplify on children since this will miss the case
		 where a child exists in the parent but does not in this.
		 See PR 1FH5RYA. */
		DataTreeNode parentsNode = (DataTreeNode) parent.copyCompleteSubtree(key);
		return parentsNode.forwardDeltaWith(this, comparer);
	}

	@Override
	public void storeStrings(StringPool set) {
		super.storeStrings(set);
		//copy data for thread safety
		Object o = data;
		if (o instanceof IStringPoolParticipant)
			((IStringPoolParticipant) o).shareStrings(set);
	}

	@Override
	int type() {
		return T_COMPLETE_NODE;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy