/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.script.inst; import divconq.lang.op.FuncCallback; import divconq.lang.op.OperationCallback; import divconq.lang.op.OperationContext; import divconq.script.BlockInstruction; import divconq.script.ExecuteState; import divconq.script.StackBlockEntry; import divconq.script.StackEntry; import divconq.struct.IItemCollection; import divconq.struct.RecordStruct; import divconq.struct.Struct; import divconq.struct.scalar.AnyStruct; import divconq.util.IAsyncIterator; public class ForEach extends BlockInstruction { @Override public void alignInstruction(final StackEntry stack, final OperationCallback callback) { final StackBlockEntry bstack = (StackBlockEntry)stack; // signal end if conditional logic fails after loop if (bstack.getPosition() >= this.instructions.size()) { RecordStruct store = stack.getStore(); AnyStruct collection = (AnyStruct) store.getField("Collection"); final String name = store.getFieldAsString("Name"); @SuppressWarnings("unchecked") final IAsyncIterator<Struct> it = (IAsyncIterator<Struct>) collection.getValue(); if (it != null) { it.hasNext(new FuncCallback<Boolean>() { @Override public void callback() { if (this.getResult()) { it.next(new FuncCallback<Struct>() { @Override public void callback() { bstack.addVariable(name, this.getResult()); bstack.setPosition(0); ForEach.super.alignInstruction(stack, callback); } }); } else { stack.setState(ExecuteState.Done); ForEach.super.alignInstruction(stack, callback); } } }); return; } else stack.setState(ExecuteState.Done); } super.alignInstruction(stack, callback); } @Override public void run(final StackEntry stack) { if (stack.getState() == ExecuteState.Ready) { String name = stack.stringFromSource("Name"); Struct source = stack.refFromSource("In"); AnyStruct collection = new AnyStruct(); collection.setType(OperationContext.get().getSchema().getType("Any")); // TODO shouldn't need this if (source instanceof IItemCollection) collection.setValue(((IItemCollection)source).getItemsAsync().iterator()); RecordStruct store = stack.getStore(); store.setField("Collection", collection); store.setField("Name", name); // tell alignment to do first iteration by passing position beyond end StackBlockEntry bstack = (StackBlockEntry)stack; bstack.setPosition(this.instructions.size()); } super.run(stack); } }