package ecologylab.generic; import java.util.Iterator; /** * Iterates through a Collection of things, and then through an Iterator * of such (nested) Collections of things. * Provides flat access to all members. * * @author andruid * * @param <I> Class that we iterate over. * @param <O> Class of objects that are applied in the context of what we iterate over. * This typically starts as this, but shifts as we iterate through * the nested Collection of Iterators. */ public class OneLevelNestingIterator<I, O extends Iterable<I>> implements Iterator<I> { protected Iterator<I> firstIterator; protected Iterator<? extends O> collection; protected O currentObject; protected Iterator<I> currentIterator; public OneLevelNestingIterator(O firstObject) { this.firstIterator = firstObject.iterator(); this.currentObject = firstObject; } public OneLevelNestingIterator(O firstObject, Iterator<? extends O> iterableCollection) { this(firstObject); this.collection = iterableCollection; } public OneLevelNestingIterator(O firstObject, Iterable<? extends O> iterableCollection) { this(firstObject); this.collection = (iterableCollection != null) ? iterableCollection.iterator() : null; } private boolean collectionHasNext() { return collection != null && (collection.hasNext() || currentHasNext()); } private boolean currentHasNext() { return (currentIterator != null) && currentIterator.hasNext(); } @Override public boolean hasNext() { return firstIterator.hasNext() || collectionHasNext(); } @Override public I next() { if (firstIterator.hasNext()) { I firstNext = firstIterator.next(); // avoid returning the collection, itself, when it is a field in the firstIterator return (firstNext != collection) ? firstNext : next(); } // else if (currentHasNext()) return currentIterator.next(); // else if (collectionHasNext()) { currentObject = collection.next(); currentIterator = currentObject.iterator(); return currentIterator.next(); } return null; } public O currentObject() { return currentObject; } @Override public void remove() { throw new UnsupportedOperationException(); } }