package net.varkhan.base.functor.expander; import net.varkhan.base.functor.Expander; import java.lang.reflect.Array; import java.util.Iterator; import java.util.NoSuchElementException; /** * <b></b>. * <p/> * @author varkhan * @date 11/5/13 * @time 4:48 PM */ public class BlockExpander<T,S,C> implements Expander<T[],S,C> { protected final Class<T> cls; protected final Expander<T,S,C> exp; protected final int min; protected final int max; public BlockExpander(Class<T> cls, Expander<T,S,C> exp, int min, int max) { this.cls=cls; this.exp=exp; this.min=min; this.max=max; } @Override public Iterable<T[]> invoke(S src, C ctx) { return new BlockIterable<T>(cls, exp.invoke(src, ctx), min, max); } protected static class BlockIterable<T> implements Iterable<T[]> { protected final Class<T> cls; protected final Iterable<T> itr; protected final int min; protected final int max; public BlockIterable(Class<T> cls, Iterable<T> itr, int min, int max) { this.cls=cls; this.itr=itr; this.min=min; this.max=max; } @Override public Iterator<T[]> iterator() { return new BlockIterator<T>(cls, itr.iterator(), min, max); } } protected static class BlockIterator<T> implements Iterator<T[]> { protected final Class<T> cls; protected final Iterator<T> itr; protected final int min; protected final int max; protected final Object[] buf; protected volatile int lps=0; protected volatile int hps=0; public BlockIterator(Class<T> cls, Iterator<T> itr, int min, int max) { this.cls=cls; this.itr=itr; this.min=min; this.max = max; this.buf = new Object[max]; } @Override public boolean hasNext() { while(lps<min) { if(!getToken()) return false; lps ++; } if(lps>hps) { if(!getToken()) return false; lps=min; } return true; } protected boolean getToken() { if(!itr.hasNext()) return false; T tk = itr.next(); System.arraycopy(buf,0,buf,1,buf.length-1); buf[0] = tk; if(hps<max) hps++; return true; } @Override @SuppressWarnings("unchecked") public T[] next() { if(!hasNext()) throw new NoSuchElementException(); T[] ta = (T[])Array.newInstance(cls,lps); for(int i=0; i<lps; i++) { ta[i] = (T) buf[lps-i-1]; } lps ++; return ta; } @Override public void remove() { } } }