Jul 17
This is my implementation of an Iterator interface which scans a TreeModel in a postfix manner.
So, let’s go!
public final class TreeModelIterator implements Iterator
{
private final TreeModel model;
private final Stack childLocations = new Stack ();
private final Position.Bias bias;
private TreePath current;
public TreeModelIterator(TreeModel model, Position.Bias bias) {
this.model = model;
this.bias = bias;
Object root = model.getRoot();
current = root != null ? new TreePath(root) : null;
}
public boolean hasNext() {
return current != null;
}
public TreePath next() {
TreePath result = current;
current = null;
if (model.getChildCount(result.getLastPathComponent()) > 0) {
pushElementChildren(result);
Object nextChild = model.getChild(result.getLastPathComponent(),
childLocations.peek());
current = result.pathByAddingChild(nextChild);
} else {
TreePath parent = result.getParentPath();
while (current == null && childLocations.size() > 0) {
int nextLocation = childLocations.pop() + getIncrement();
if (nextLocation == getChildIterationStopper(parent)) {
parent = parent.getParentPath();
} else {
Object nextChild = model.getChild(parent.getLastPathComponent(),
nextLocation);
current = parent.pathByAddingChild(nextChild);
childLocations.push(nextLocation);
}
}
}
return result;
}
private int getChildIterationStopper(TreePath path) {
return bias == Position.Bias.Forward
? model.getChildCount(path.getLastPathComponent()) : -1;
}
private void pushElementChildren(TreePath path) {
int iterationStart = bias == Position.Bias.Forward
? 0 : model.getChildCount(path.getLastPathComponent()) - 1;
childLocations.push(iterationStart);
}
private int getIncrement() {
return bias == Position.Bias.Forward ? 1 : -1;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
To use it in a foreach statement you will need to create an Iterable wrapper, too. Hope this is useful to any of you…
Anyway, with the new Yielder option it looks like this:
public final class TreeModelYielder extends Yielder
implements Iterable
{
private TreeModel model;
private TreePath path;
private Position.Bias bias;
public TreeModelYielder(TreeModel model, Position.Bias bias) {
this(model, model.getRoot() != null ? new TreePath(model.getRoot()) : null, bias);
private TreeModelYielder(TreeModel model, TreePath path, Position.Bias bias) {
this.curPath = path;
this.bias = bias;
}
protected void yieldNextCore() {
for (int i = getFirstChildIndex();
i != getChildIterationStopper(path);
i += getIncrement()) {
Object curChild = model.getChild(path.getLastPathComponent(), i);
for (TreePath res : new TreeModelYielder(model, curChild, bias)) {
yieldReturn(res);
}
}
yieldReturn(path.getLastPathComponent());
}
private int getFirstChildIndex() {
return bias == Position.Bias.Forward
? 0 : model.getChildCount(path.getLastPathComponent()) - 1;
}
// getChildIterationStopper and getIncrement are the same.
}
What do you think?