package xapi.fu; /** * @author James X. Nelson (james@wetheinter.net) * Created on 07/11/15. */ public interface InMany extends HasInput { Many<HasInput> children(); default void in(Object ... args) { Fu.jutsu.applyArguments(0, children(), args); } @Override default int accept(int index, Object ... values) { int res = Fu.jutsu.applyArguments(index, children(), values); return res; } default void in1(Object one) { in(one); } default <I1> In1<I1> toIn1() { return this::in1; } default void in2(Object one, Object two) { in(one, two); } default <I1, I2> In2<I1, I2> toIn2() { return this::in2; } default void in3(Object one, Object two, Object three) { in(one, two, three); } default <I1, I2, I3> In3<I1, I2, I3> toIn3() { return this::in3; } default void in4(Object one, Object two, Object three, Object four) { in(one, two, three, four); } default <I1, I2, I3, I4> In4<I1, I2, I3, I4> toIn4() { return this::in4; } class InManyBuilder { Many<Out2<Integer, HasInput>> tail, head = tail = new Many<>(); InManyBuilder add(In1 in) { tail = tail.add(Out2.out2Immutable(1, in)); return this; } InManyBuilder add(In2 in) { tail = tail.add(Out2.out2Immutable(2, in)); return this; } InManyBuilder add(In3 in) { tail = tail.add(Out2.out2Immutable(3, in)); return this; } InManyBuilder add(In4 in) { tail = tail.add(Out2.out2Immutable(4, in)); return this; } InManyBuilder add(InManyBuilder multi) { tail = tail.add(Out2.out2(()->(Integer)multi.size(), ()->multi.build())); return this; } private int size() { int size = 1; Many<Out2<Integer, HasInput>> test = head; while (test.next != null) { size ++; test = test.next; } return size; } InMany build() { // Waits until invocation to peek in the stack return ()->head.map(Out2::out2); } InMany buildSnapshot() { // Copy from the the stack so when we invoke, we see the builder state at this instant. final Many<HasInput> snapshot = head.map(Out2::out2); return ()->snapshot; } } static InMany of(HasInput in) { return ()->new Many<HasInput>().add(in); } static InMany of(HasInput before, HasInput after) { return ()->new Many<HasInput>().add(before).add(after); } static InMany of(HasInput before, HasInput middle, HasInput after) { return ()->new Many<HasInput>().add(before).add(middle).add(after); } static InMany of(HasInput... ins) { Many<HasInput> tail, head = tail = new Many<HasInput>(); for (HasInput in : ins) { tail = tail.add(in); } return ()->head; } }