org.eclipse.core.internal.watson.ElementTreeIterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjtools Show documentation
Show all versions of aspectjtools Show documentation
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.
/*******************************************************************************
* Copyright (c) 2000, 2015 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.watson;
import org.eclipse.core.internal.dtree.AbstractDataTreeNode;
import org.eclipse.core.internal.dtree.DataTreeNode;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/**
* A class for performing operations on each element in an element tree.
* For example, this can be used to print the contents of a tree.
*
* When creating an ElementTree iterator, an element tree and root path must be
* supplied. When the iterate()
method is called, a visitor object
* must be provided. The visitor is called once for each node of the tree. For
* each node, the visitor is passed the entire tree, the object in the tree at
* that node, and a callback for requesting the full path of that node.
*
* Example:
*
* // printing a crude representation of the poster child
* IElementContentVisitor visitor=
* new IElementContentVisitor() {
* public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) {
* System.out.println(requestor.requestPath() + " -> " + elementContents);
* return true;
* }
* });
* ElementTreeIterator iterator = new ElementTreeIterator(tree, Path.ROOT);
* iterator.iterate(visitor);
*
*/
public class ElementTreeIterator implements IPathRequestor {
//for path requestor
private String[] segments = new String[10];
private int nextFreeSegment;
/* the tree being visited */
private ElementTree tree;
/* the root of the subtree to visit */
private IPath path;
/* the immutable data tree being visited */
private DataTreeNode treeRoot;
/**
* Creates a new element tree iterator for visiting the given tree starting
* at the given path.
*/
public ElementTreeIterator(ElementTree tree, IPath path) {
this.tree = tree;
this.path = path;
//treeRoot can be null if deleted concurrently
//must copy the tree while owning the tree's monitor to prevent concurrent deletion while creating visitor's copy
synchronized (tree) {
treeRoot = (DataTreeNode) tree.getDataTree().safeCopyCompleteSubtree(path);
}
}
/**
* Iterates through the given element tree and visit each element (node)
* passing in the element's ID and element object.
*/
private void doIteration(DataTreeNode node, IElementContentVisitor visitor) {
//push the name of this node to the requestor stack
if (nextFreeSegment >= segments.length) {
grow();
}
segments[nextFreeSegment++] = node.getName();
//do the visit
if (visitor.visitElement(tree, this, node.getData())) {
//recurse
AbstractDataTreeNode[] children = node.getChildren();
int len = children.length;
for (int i = 0; i < len; i++) {
doIteration((DataTreeNode) children[i], visitor);
}
}
//pop the segment from the requestor stack
nextFreeSegment--;
if (nextFreeSegment < 0)
nextFreeSegment = 0;
}
/**
* Method grow.
*/
private void grow() {
//grow the segments array
int oldLen = segments.length;
String[] newPaths = new String[oldLen * 2];
System.arraycopy(segments, 0, newPaths, 0, oldLen);
segments = newPaths;
}
/**
* Iterates through this iterator's tree and visits each element in the
* subtree rooted at the given path. The visitor is passed each element's
* data and a request callback for obtaining the path.
*/
public void iterate(IElementContentVisitor visitor) {
if (path.isRoot()) {
//special visit for root element to use special treeData
if (visitor.visitElement(tree, this, tree.getTreeData())) {
if (treeRoot == null)
return;
AbstractDataTreeNode[] children = treeRoot.getChildren();
int len = children.length;
for (int i = 0; i < len; i++) {
AbstractDataTreeNode node = children[i];
if (node instanceof DataTreeNode) {
doIteration((DataTreeNode) node, visitor);
}
}
}
} else {
if (treeRoot == null)
return;
push(path, path.segmentCount() - 1);
doIteration(treeRoot, visitor);
}
}
/**
* Push the first "toPush" segments of this path.
*/
private void push(IPath pathToPush, int toPush) {
if (toPush <= 0)
return;
for (int i = 0; i < toPush; i++) {
if (nextFreeSegment >= segments.length) {
grow();
}
segments[nextFreeSegment++] = pathToPush.segment(i);
}
}
@Override
public String requestName() {
if (nextFreeSegment == 0)
return ""; //$NON-NLS-1$
return segments[nextFreeSegment - 1];
}
@Override
public IPath requestPath() {
if (nextFreeSegment == 0) {
return IPath.ROOT;
}
int length = nextFreeSegment;
for (int i = 0; i < nextFreeSegment; i++) {
length += segments[i].length();
}
StringBuilder pathBuf = new StringBuilder(length);
for (int i = 0; i < nextFreeSegment; i++) {
pathBuf.append('/');
pathBuf.append(segments[i]);
}
return new Path(null, pathBuf.toString());
}
}