/*license*\
XBN-Java: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)
This software is dual-licensed under the:
- Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
- Apache Software License (ASL) version 2.0.
Either license may be applied at your discretion. More information may be found at
- http://en.wikipedia.org/wiki/Multi-licensing.
The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
- LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
- ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
\*license*/
package com.github.xbn.experimental;
import com.github.xbn.list.ListUtil;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.NoSuchElementException;
/**
<p>Iterator tailored for {@code IterationOdometer}, with additional debugging functions. Returns a ArrayList of type T, containing as many elements, equal to the amount of times {@link IterationOdometer}{@code .add*()} was called.</p>
<p>The function {@link #nextString() nextAsStr}{@code ()} is useful for diagnostics and testing. It joins the {@code toString()} of all ArrayList elements together, into a single string. It is used by all the {@code IterationOdometer.test_get1stIdxIfNot*()} functions.</p>
<p>The {@code hasNext()} function in this class was one of the more challenging programming exercises I've encountered.</p>
**/
public class IteratorIOD<T> implements Iterator<ArrayList<T>> {
// private int iodColCount = -1;
private ArrayList<Iterable<T>> vitrblt = null;
private ArrayList<Iterator<T>> vitrt = null;
private int ixLastColumn = -1;
ArrayList<T> vtNext = null;
ArrayList<T> vtWrkg = null;
private int ixRLIRb = 0;
@SuppressWarnings("unchecked")
public IteratorIOD(ArrayList<Iterable<T>> itrbl_arrayList) {
vitrblt = itrbl_arrayList;
vtWrkg = (ArrayList<T>)ListUtil.newNulledArrayListOfSize(vitrblt.size());
ixLastColumn = (vitrblt.size() - 1);
vitrt = new ArrayList<Iterator<T>>(itrbl_arrayList.size());
for(int i = 0; i < vitrblt.size(); i++) {
vitrt.add(vitrblt.get(i).iterator());
}
hasNext();
}
@SuppressWarnings("unchecked")
public final boolean hasNext() {
if(vtNext != null) {
return true;
}
if(ixRLIRb == 0 && !vitrt.get(0).hasNext()) {
//For example: 9 9 9 9
// ^
return false;
}
for(int i = 0; i < vitrt.size(); i++) {
assert (ixRLIRb >= i) : "[io.a]";
Iterator<T> itrt1 = vitrt.get(i);
T tWrkg = vtWrkg.get(i);
if(i < ixRLIRb) {
//Recycle this column's value.
//i is to the left of the recycle-to-the-left/
//iterate-to-the-right boundary (ixRLIRb)
assert (tWrkg != null) : "[io.b]";
//&& tWrkg == itrt1.getMostRecentRetrieved() ?????
//Do nothing. It's in the working vector, and
//ready to go for when next() is called.
continue;
}
//i is to the right or (or equal to) the recycle-left/
//iterate-right boundary. Must get the next item in this
//column.
assert (tWrkg == null && itrt1.hasNext()) : "[io.c]";
vtWrkg.set(i, itrt1.next());
if(i == ixLastColumn) {
assert(ixRLIRb == ixLastColumn) : "[io.d]";
//Must start at last/right-most Iterable, and
//
//-1- hasNext() ?
// -a- Reset the iterator
// -b- break;
//-2- Decrement the ixRLIRb, to point to the previous
// column
//-3- Repeat until either a column's hasNext() is true, or
// every column has no next.
// Example 1 Example 2
//-1- 0 0 0 9 9 9 9 9
// ^ ^
//-2- 0 0 0 0 9 9 9 9
// ^ ^
// 9 9 9 9
// ^
// 9 9 9 9
// ^
// Next call to Done.
// next() will
// cause the
// 2nd-from-r
// to inc to 1,
// resulting in,
// ultimately:
// 0 0 1 0
// ^
//The overall IterationOdometer, however, always goes
//back to index zero. Hence, i=0 in the for loop
//above.
int j = (ixLastColumn + 1); //One extra...
while(j > 0) {
j--; //To decrement first.
if(vitrt.get(j).hasNext()) {
//Done resetting. 5 3 0 8 or 0 0 7 0
// ^ ^
// Was 0079
// About to be 0080
break;
}
if(j > 0) {
vitrt.set(j, vitrblt.get(j).iterator());
ixRLIRb--;
}
//Reset the column iterator
}
//Note, there IS at least one more item to get. Otherwise,
//The second line in this function would have prevented
//this point from being reached.
} else {
//This is not last column.
if(i == ixRLIRb) {
//ixRLIRb must be equal to or greater than i. Must
//increment this before the next iteration of this
//for-loop (where i is incremented).
ixRLIRb++;
}
//May be (about to do) last column.
}
}
vtNext = vtWrkg;
vtWrkg = (ArrayList<T>)ListUtil.newNulledArrayListOfSize(vitrblt.size());
//Recycle!
for(int i = 0; i < ixRLIRb; i++) {
vtWrkg.set(i, vtNext.get(i));
}
return true;
}
public final ArrayList<T> next() {
if(vtNext == null) {
throw new NoSuchElementException("next");
}
ArrayList<T> vt = vtNext;
vtNext = null;
hasNext();
return vt;
}
/**
<p>Joins the {@code toString()} value for all columns into a single string. Use for testing.</p>
*/
public final String getNextAsStr(ArrayList<T> v_t) {
if(v_t == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for(T t : v_t) {
sb.append(t);
}
return sb.toString();
}
public final String nextString() {
return getNextAsStr(next());
}
public final void remove() {
throw new UnsupportedOperationException("remove");
}
}