package net.varkhan.base.functor.expander; import net.varkhan.base.functor.Expander; import java.util.Iterator; import java.util.NoSuchElementException; /** * <b></b>. * <p/> * @author varkhan * @date 11/5/13 * @time 4:26 PM */ public class ChainExpander<T,S,C> implements Expander<T,S,C> { protected final Expander<T,/* U */ Object,C> l; protected final Expander</* U */ Object,S,C> r; @SuppressWarnings("unchecked") public <U> ChainExpander(Expander<T,U,C> l, Expander<U,S,C> r) { this.l=(Expander<T,Object,C>) l; this.r=(Expander<Object,S,C>) r; } public Expander<T,?,C> left() { return l; } public Expander<?,S,C> right() { return r; } @Override public Iterable<T> invoke(S src, C ctx) { return new ChainIterable<T>(l, r.invoke(src, ctx), ctx); } public static class ChainIterable<T> implements Iterable<T> { protected final Expander<T, /* U */ Object, /* C */ Object> exp; protected final Iterable</* U */ Object> itr; protected final /* C */ Object ctx; @SuppressWarnings("unchecked") public <U,C> ChainIterable(Expander<T,U,C> exp, Iterable<U> itr, C ctx) { this.exp=(Expander<T,Object,Object>) exp; this.itr=(Iterable<Object>) itr; this.ctx=ctx; } @Override public Iterator<T> iterator() { return new ChainIterator<T>(exp, itr.iterator(), ctx); } } public static class ChainIterator<T> implements Iterator<T> { protected final Expander<T, /* U */ Object, /* C */ Object> exp; protected final Iterator</* U */ Object> itr; protected final /* C */ Object ctx; protected volatile Iterator<T> next=null; @SuppressWarnings("unchecked") public <U,C> ChainIterator(Expander<T,U,C> exp, Iterator<U> itr, C ctx) { this.exp = (Expander<T, Object, Object>) exp; this.itr = (Iterator<Object>) itr; this.ctx = ctx; } @Override public boolean hasNext() { while(next==null || !next.hasNext()) { if(!itr.hasNext()) return false; Object val = itr.next(); next = exp.invoke(val, ctx).iterator(); } return true; } @Override public T next() { if(!hasNext()) throw new NoSuchElementException(); return next.next(); } @Override public void remove() { } } @Override public String toString() { String rs = right().toString(); String ls = left().toString(); if("$".equals(rs)) return ls; if("$".equals(ls)) return rs; StringBuilder buf = new StringBuilder(); int p1 = 0, p2; while(p1<ls.length() && (p2=ls.indexOf('$',p1))>=0) { buf.append(ls.substring(p1,p2)).append(rs); p1 = p2+1; } buf.append(ls.substring(p1,ls.length())); return buf.toString(); } }