package com.yoursway.utils.strings; import java.lang.reflect.Array; import java.util.Iterator; public class TupleIterable<T> implements Iterable<T[]> { private final static class TupleIterator<T> implements Iterator<T[]> { private final Iterable<T>[] elements; private final Iterator<T>[] iterators; private final T[] values; private boolean hasNext = true; private final Class<T> klass; @SuppressWarnings("unchecked") public TupleIterator(Class<T> klass, Iterable<T>[] elements) { if (klass == null) throw new NullPointerException("klass is null"); if (elements == null) throw new NullPointerException("elements is null"); this.klass = klass; this.elements = elements; iterators = (Iterator<T>[]) new Iterator<?>[elements.length]; values = (T[]) Array.newInstance(klass, elements.length); resetIteratorsStartingWith(0); } public boolean hasNext() { return hasNext; } @SuppressWarnings("unchecked") public T[] next() { T[] result = (T[]) Array.newInstance(klass, values.length); System.arraycopy(values, 0, result, 0, values.length); advance(); return result; } private void advance() { int incr = findRightmostIteratorThatHasNextValue(); if (incr < 0) hasNext = false; else { values[incr] = iterators[incr].next(); resetIteratorsStartingWith(incr + 1); } } private int findRightmostIteratorThatHasNextValue() { int nextIterator = -1; for (int i = iterators.length - 1; i >= 0; i--) if (iterators[i].hasNext()) { nextIterator = i; break; } return nextIterator; } public void remove() { throw new UnsupportedOperationException(); } private void resetIteratorsStartingWith(int index) { for (int i = index; i < iterators.length; i++) { iterators[i] = elements[i].iterator(); if (!iterators[i].hasNext()) hasNext = false; else values[i] = iterators[i].next(); } } } private final Iterable<T>[] elements; private final Class<T> klass; public TupleIterable(Class<T> klass, Iterable<T>[] elements) { if (klass == null) throw new NullPointerException("klass is null"); if (elements == null) throw new NullPointerException("elements is null"); this.klass = klass; this.elements = elements; } public Iterator<T[]> iterator() { return new TupleIterator<T>(klass, elements); } }