// This file is part of Penn TotalRecall <http://memory.psych.upenn.edu/TotalRecall>.
//
// TotalRecall is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 only.
//
// TotalRecall is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TotalRecall. If not, see <http://www.gnu.org/licenses/>.
package util;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* An iterator that visits each element of an array, in either increasing or decreasing order,
* resolving boundary limitations by "looping" to the other side of the array.
*
* In the increasing order case, traversal starts at index x, ends at index x - 1, and the first element of the array is visited after the last.
* In the decreasing order case, traversal starts at index x, ends at index x + 1, and the last element of the array is visited after the first.
*
* Does not support remove().
*
* @author Yuvi Masory
*
* @param <T> The type of the array to be iterated over
*/
public class LoopIterator<T> implements Iterator<T> {
private boolean hasMore;
private boolean forward; //direction of traversal
private int originalIndex;
private int curIndex;
private T[] arr;
/**
* Constructs an iterator with the provided input.
*
* The first element to be returned will be arr[index].
*
* @param arr The array to be iterated over
* @param index The index at which to begin iteration
* @param forward Whether iteration will take place in increasing order, decreasing order otherwise
* @throws IllegalArgumentException if the array is null or if index is not in bounds
*/
public LoopIterator(T[] arr, int index, boolean forward) {
if(arr == null) {
throw new IllegalArgumentException("array cannot be null");
}
if(index < 0 || index > (arr.length - 1)) {
throw new IllegalArgumentException("provided index not in bounds");
}
this.forward = forward;
this.arr = arr;
this.originalIndex = index;
this.curIndex = index;
this.hasMore = true;
}
/**
* Determines if there are more elements to return.
* If <tt>false</tt> is returned, calling next() will lead to a NoSuchElementException.
*
* @return <tt>true</tt> if the iteration has more elements
*/
public boolean hasNext() {
return hasMore;
}
/**
* Returns the next element in the iteration, if available.
*
* @return T The next element
* @throws NoSuchElementException If there are no more elements to return
*/
public T next() {
if(hasMore == false) {
throw new NoSuchElementException("there are no more elements");
}
int tmp = curIndex;
if(forward) {
if(curIndex >= (arr.length - 1)) {
curIndex = 0;
}
else {
curIndex++;
}
}
else {
if(curIndex == 0) {
curIndex = arr.length - 1;
}
else {
curIndex--;
}
}
if(curIndex == originalIndex) {
hasMore = false;
}
return arr[tmp];
}
/**
* Unsupported.
*
* @throws UnsupportedOperationException In all cases
*/
public void remove() {
throw new UnsupportedOperationException("remove not supported");
}
}