package ecologylab.generic; import java.lang.reflect.Field; import java.util.Iterator; import ecologylab.serialization.FieldDescriptor; /** * Iterates through a Collection of things, and then through an Iterator * of such (nested) Collections of things. * Provides flat access to all members. * * @author jmole, damaraju * * @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 ClassAndCollectionIterator<I extends FieldDescriptor, O extends Iterable<I>> implements Iterator<O> { private Iterator<I> iterator; private Iterator<O> collectionIterator; private O root; private O currentObject; /** * * @param firstObject - The object whose elements need to be iterated over. */ public ClassAndCollectionIterator(O firstObject) { root = firstObject; this.iterator = firstObject.iterator(); } /** * @return The next field in the Object.<br> * If the next object is a non-null collection, it iterates through the objects of that collection */ @Override public O next() { try { if (collectionIterator != null) return nextInCollection(); if (iterator.hasNext()) { I firstNext = iterator.next(); Field field = firstNext.getField(); if(firstNext.isCollection()) { Iterable<O> collection = (Iterable<O>)field.get(root); if(collection != null) { collectionIterator = collection.iterator(); return nextInCollection(); } else { //Collection is null ? //Debug.println("next(): Collection is null"); return next(); } } O next = (O) field.get(root); currentObject = next; return next; } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } private O nextInCollection() { if (!collectionIterator.hasNext()) { collectionIterator = null; return next(); } O next = collectionIterator.next(); currentObject = next; return next; } /** * * @return */ public O currentObject() { return currentObject; } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public boolean hasNext() { return iterator.hasNext() || (collectionIterator != null && collectionIterator.hasNext()); } }