Implementation details for Java Yielder Jakarta’s BCEL vs. ObjectWeb’s ASM
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?

  • Share/Bookmark

Leave a Reply

Chaotic Java is Digg proof thanks to caching by WP Super Cache