package org.codefx.libfx.collection.tree.stream;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
/**
* An {@link Iterator} which uses a {@link TreeIterationStrategy} to iterate over a tree.
*
* @param <E>
* the type of elements returned by this iterator
*/
class TreeIterator<E> implements Iterator<E> {
/*
* The important task of choosing the next node in the tree is delegated to the iteration strategy. This class
* merely delays looking for that node as long as possible. Its state consists of a single node of the tree and
* whether it was already returned
*/
// #begin FIELDS
private final TreeIterationStrategy<E> iterationStrategy;
/**
* The next node to return; if it is {@link Optional#empty() empty}, the iteration will end.
*/
private Optional<E> nextNode;
/**
* Indicates whether the {@link #nextNode} was already returned as an element in {@link #next()}.
*/
private boolean returnedNextNode;
// #end FIELDS
// #begin CONSTRUCTION
/**
* Creates a new tree iterator which uses the specified strategy to determine the order of nodes.
*
* @param iterationStrategy
* the strategy used by this iterator
*/
public TreeIterator(TreeIterationStrategy<E> iterationStrategy) {
Objects.requireNonNull(iterationStrategy, "The argument 'iterationStrategy' must not be null.");
this.iterationStrategy = iterationStrategy;
this.nextNode = Optional.empty();
this.returnedNextNode = true;
}
// #end CONSTRUCTION
// #begin IMPLEMENTATION OF 'Iterator'
@Override
public final boolean hasNext() {
goToNextNodeIfNecessary();
return nextNode.isPresent();
}
@Override
public final E next() {
goToNextNodeIfNecessary();
return returnNextNode();
}
// #end IMPLEMENTATION OF 'Iterator'
// #begin GO TO NEXT NODE & RETURN
private void goToNextNodeIfNecessary() {
if (returnedNextNode) {
nextNode = iterationStrategy.goToNextNode();
returnedNextNode = false;
}
}
private E returnNextNode() {
if (nextNode.isPresent()) {
returnedNextNode = true;
return nextNode.get();
} else
throw new NoSuchElementException("All nodes in the tree have been visited.");
}
// #end GO TO NEXT NODE & RETURN
}