/* Copyright (c) 1996-2007 Ariba, Inc. All rights reserved. Patents pending. $Id: //ariba/platform/util/core/ariba/util/core/TreeIterable.java#3 $ Responsible: dfinlay */ package ariba.util.core; import java.util.Iterator; import java.util.List; import java.util.Collections; /** @aribaapi ariba */ public class TreeIterable<T> implements Iterable<T> { public enum Traversal { PreOrder, LevelOrder } private Iterable<T> _roots; private Function<Iterable<T>> _childrenGetter; private Traversal _traversal; public TreeIterable ( Iterable<T> roots, Traversal traversal, Function<Iterable<T>> childrenGetter ) { _roots = roots; _traversal = traversal != null ? traversal : Traversal.PreOrder; _childrenGetter = childrenGetter; } public TreeIterable (List<T> roots, Traversal traversal) { this(roots, traversal, null); } public TreeIterable (T root, Traversal traversal, Function<Iterable<T>> childrenGetter) { this(Collections.singletonList(root), traversal, childrenGetter); } public TreeIterable (T root, Traversal traversal) { this(Collections.singletonList(root), traversal); } public TreeIterable (T root) { this(root, Traversal.PreOrder); } public TreeIterable (List<T> roots) { this(roots, Traversal.PreOrder); } public Iterator<T> iterator () { return new Iter(); } protected Iterable<T> getChildren (T parent) { return _childrenGetter != null ? _childrenGetter.evaluate(parent) : null; } private class Iter implements Iterator<T> { private List<Iterator<T>> _iterators; private int _min; private int _idx; private Iter () { if (_roots == null) { _iterators = ListUtil.list(); } else { _iterators = ListUtil.list(_roots.iterator()); } _min = 0; _idx = _traversal == Traversal.PreOrder ? _iterators.size() - 1 : _min; } public boolean hasNext () { int idx = _idx; int size = _iterators.size(); int delta = _traversal == Traversal.PreOrder ? -1 : +1; while (idx >= _min && idx < size) { if (_iterators.get(idx).hasNext()) { return true; } idx += delta; } return false; } public T next () { int size = _iterators.size(); int delta = _traversal == Traversal.PreOrder ? -1 : +1; while (_idx >= _min && _idx < size) { Iterator<T> iterator = _iterators.get(_idx); if (iterator.hasNext()) { T result = iterator.next(); Iterable<T> children = getChildren(result); if (children != null) { Iterator<T> iter = children.iterator(); if (iter.hasNext()) { _iterators.add(iter); _idx += (_traversal == Traversal.PreOrder ? 1 : 0); } } return result; } if (_traversal == Traversal.PreOrder) { _iterators.remove(_idx); } else { _iterators.set(_idx, null); _min += delta; } _idx += delta; } return null; } public void remove () { throw new UnsupportedOperationException(); } } }