TypeIterator.java
package org.codefilarete.tool.bean;
import javax.annotation.Nullable;
import java.util.NoSuchElementException;
import org.codefilarete.tool.collection.ReadOnlyIterator;
/**
* Iterator over the types (classes and interfaces) of a hierarchy.
* The iteration is by class-floor: it returns first the class and its interfaces, then the superclass and its interfaces, etc.
*
* @see ClassIterator
* @see InterfaceIterator
* @author Guillaume Mary
*/
public class TypeIterator extends ReadOnlyIterator<Class<?>> {
private ClassIterator classIterator;
@Nullable // null at initialization
private InterfaceIterator interfaceIterator;
/**
* Constructor for an {@link java.util.Iterator} from fromClass to {@link Object} class included
* @param fromClass the start point (included) of this {@link java.util.Iterator}
*/
public TypeIterator(Class<?> fromClass) {
this(fromClass, Object.class);
}
/**
* Constructor for an {@link java.util.Iterator} from fromClass to toClass included
* @param fromClass the start point (included) of this {@link java.util.Iterator}
* @param toClass end point (included) of this {@link java.util.Iterator}, null authorized
*/
public TypeIterator(Class<?> fromClass, Class<?> toClass) {
this.classIterator = new ClassIterator(fromClass, toClass);
}
@Override
public boolean hasNext() {
return classIterator.hasNext() || interfaceIterator != null && interfaceIterator.hasNext();
}
@Override
public Class<?> next() {
if (!hasNext()) {
// this is necessary to be compliant with Iterator#next(..) contract
throw new NoSuchElementException();
}
// we detect the very first iteration (by checking interfaceIterator against null) to return the initial class
if (interfaceIterator == null) {
return prepareNextClassScan();
} else if (interfaceIterator.hasNext()) {
return interfaceIterator.next();
} else if (classIterator.hasNext()) {
return prepareNextClassScan();
} else {
return null;
}
}
private Class<?> prepareNextClassScan() {
Class<?> next = classIterator.next();
interfaceIterator = new InterfaceIterator(new ClassIterator(next, next.getSuperclass()));
return next;
}
}