My TreeModelIterator

· JavaFrameworks

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?