feature #I6A2GL 增加迭代器表达式特性,用于迭代循环中的集合

This commit is contained in:
everywhere.z 2023-01-11 18:01:15 +08:00
parent 429d8ed2d6
commit cebfb2867e
42 changed files with 848 additions and 11 deletions

View File

@ -53,6 +53,10 @@ public class LiteFlowNodeBuilder {
return new LiteFlowNodeBuilder(NodeTypeEnum.BREAK);
}
public static LiteFlowNodeBuilder createIteratorNode() {
return new LiteFlowNodeBuilder(NodeTypeEnum.ITERATOR);
}
public static LiteFlowNodeBuilder createScriptNode() {
return new LiteFlowNodeBuilder(NodeTypeEnum.SCRIPT);
}

View File

@ -69,6 +69,7 @@ public class LiteFlowChainELBuilder {
EXPRESS_RUNNER.addFunction(ChainConstant.NODE, new NodeOperator());
EXPRESS_RUNNER.addFunction(ChainConstant.FOR, new ForOperator());
EXPRESS_RUNNER.addFunction(ChainConstant.WHILE, new WhileOperator());
EXPRESS_RUNNER.addFunction(ChainConstant.ITERATOR, new IteratorOperator());
EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.DO, Object.class, new DoOperator());
EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.BREAK, Object.class, new BreakOperator());
EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.DATA, Object.class, new DataOperator());

View File

@ -0,0 +1,26 @@
package com.yomahub.liteflow.builder.el.operator;
import cn.hutool.core.collection.ListUtil;
import com.ql.util.express.exception.QLException;
import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.flow.element.Node;
import com.yomahub.liteflow.flow.element.condition.IteratorCondition;
public class IteratorOperator extends BaseOperator<IteratorCondition> {
@Override
public IteratorCondition build(Object[] objects) throws Exception {
OperatorHelper.checkObjectSizeEq(objects, 1);
Node node = OperatorHelper.convert(objects[0], Node.class);
if (!ListUtil.toList(NodeTypeEnum.ITERATOR).contains(node.getType())) {
throw new QLException("The parameter must be iterator-node item");
}
IteratorCondition iteratorCondition = new IteratorCondition();
iteratorCondition.setIteratorNode(node);
return iteratorCondition;
}
}

View File

@ -63,6 +63,8 @@ public interface ChainConstant {
String DATA = "data";
String ITERATOR = "ITERATOR";
String MONITOR_BUS = "monitorBus";
String CURR_CHAIN_ID = "currChainId";

View File

@ -349,6 +349,10 @@ public abstract class NodeComponent{
return this.refNodeTL.get().getLoopIndex();
}
public <T> T getCurrLoopObj(){
return this.refNodeTL.get().getCurrLoopObject();
}
@Deprecated
public void invoke(String chainId, Object param) throws Exception {
FlowExecutorHolder.loadInstance().invoke(chainId, param, this.getSlotIndex());

View File

@ -0,0 +1,24 @@
package com.yomahub.liteflow.core;
import com.yomahub.liteflow.slot.Slot;
import com.yomahub.liteflow.util.LiteFlowProxyUtil;
import java.util.Iterator;
/**
* ITERATOR迭代器循环组件抽象类
* @author Bryan.Zhang
* @since 2.9.7
*/
public abstract class NodeIteratorComponent extends NodeComponent{
@Override
public void process() throws Exception {
Iterator<?> it = processIterator();
Slot slot = this.getSlot();
Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
slot.setIteratorResult(originalClass.getName(), it);
}
public abstract Iterator<?> processIterator() throws Exception;
}

View File

@ -14,7 +14,9 @@ public enum ConditionTypeEnum {
TYPE_FOR("for", "for"),
TYPE_WHILE("while", "while")
TYPE_WHILE("while", "while"),
TYPE_ITERATOR("iterator", "iterator")
;
private String type;
private String name;

View File

@ -7,6 +7,9 @@ public enum LiteFlowMethodEnum {
PROCESS_FOR("processFor", true),
PROCESS_WHILE("processWhile", true),
PROCESS_BREAK("processBreak", true),
PROCESS_ITERATOR("processIterator", true),
IS_ACCESS("isAccess", false),
IS_END("isEnd", false),

View File

@ -35,6 +35,8 @@ public enum NodeTypeEnum {
BREAK("break", "循环跳出", false, NodeBreakComponent.class),
ITERATOR("iterator", "循环迭代", false, NodeIteratorComponent.class),
SCRIPT("script", "脚本", true, ScriptCommonComponent.class),
SWITCH_SCRIPT("switch_script", "选择脚本", true, ScriptSwitchComponent.class),

View File

@ -0,0 +1,29 @@
package com.yomahub.liteflow.exception;
/**
* 没有节点异常
* @author Yun
*/
public class NoIteratorNodeException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 异常信息
*/
private String message;
public NoIteratorNodeException(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -56,6 +56,8 @@ public class Node implements Executable,Cloneable{
private TransmittableThreadLocal<Integer> loopIndexTL = new TransmittableThreadLocal<>();
private TransmittableThreadLocal<Object> currLoopObject = new TransmittableThreadLocal<>();
public Node(){
}
@ -241,4 +243,16 @@ public class Node implements Executable,Cloneable{
public void removeLoopIndex(){
this.loopIndexTL.remove();
}
public void setCurrLoopObject(Object obj){
this.currLoopObject.set(obj);
}
public <T> T getCurrLoopObject(){
return (T)this.currLoopObject.get();
}
public void removeCurrLoopObject(){
this.currLoopObject.remove();
}
}

View File

@ -49,6 +49,7 @@ public class ForCondition extends LoopCondition{
//如果break组件不为空则去执行
if (ObjectUtil.isNotNull(breakNode)){
breakNode.setCurrChainId(this.getCurrChainId());
setLoopIndex(breakNode, i);
breakNode.execute(slotIndex);
Class<?> originalBreakClass = LiteFlowProxyUtil.getUserClass(this.breakNode.getInstance().getClass());
boolean isBreak = slot.getBreakResult(originalBreakClass.getName());
@ -64,10 +65,6 @@ public class ForCondition extends LoopCondition{
return ConditionTypeEnum.TYPE_FOR;
}
public Executable getDoExecutor() {
return this.getExecutableList().get(0);
}
public Node getForNode() {
return forNode;
}

View File

@ -0,0 +1,78 @@
package com.yomahub.liteflow.flow.element.condition;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.exception.NoIteratorNodeException;
import com.yomahub.liteflow.flow.element.Executable;
import com.yomahub.liteflow.flow.element.Node;
import com.yomahub.liteflow.slot.DataBus;
import com.yomahub.liteflow.slot.Slot;
import com.yomahub.liteflow.util.LiteFlowProxyUtil;
import java.util.Iterator;
public class IteratorCondition extends LoopCondition{
private Node iteratorNode;
@Override
public void execute(Integer slotIndex) throws Exception {
Slot slot = DataBus.getSlot(slotIndex);
if (ObjectUtil.isNull(iteratorNode)){
String errorInfo = StrUtil.format("[{}]:no iterator-node found", slot.getRequestId());
throw new NoIteratorNodeException(errorInfo);
}
//执行Iterator组件
iteratorNode.setCurrChainId(this.getCurrChainId());
iteratorNode.execute(slotIndex);
//这里可能会有spring代理过的bean所以拿到user原始的class
Class<?> originalForCountClass = LiteFlowProxyUtil.getUserClass(this.iteratorNode.getInstance().getClass());
//获得迭代器
Iterator<?> it = slot.getIteratorResult(originalForCountClass.getName());
//获得要循环的可执行对象
Executable executableItem = this.getDoExecutor();
int index = 0;
while(it.hasNext()){
Object itObj = it.next();
executableItem.setCurrChainId(this.getCurrChainId());
//设置循环index
setLoopIndex(executableItem, index);
//设置循环迭代器对象
setCurrLoopObject(executableItem, itObj);
//执行可执行对象
executableItem.execute(slotIndex);
//如果break组件不为空则去执行
if (ObjectUtil.isNotNull(breakNode)){
breakNode.setCurrChainId(this.getCurrChainId());
setLoopIndex(breakNode, index);
setCurrLoopObject(breakNode, itObj);
breakNode.execute(slotIndex);
Class<?> originalBreakClass = LiteFlowProxyUtil.getUserClass(this.breakNode.getInstance().getClass());
boolean isBreak = slot.getBreakResult(originalBreakClass.getName());
if (isBreak){
break;
}
}
index++;
}
}
@Override
public ConditionTypeEnum getConditionType() {
return ConditionTypeEnum.TYPE_ITERATOR;
}
public Node getIteratorNode() {
return iteratorNode;
}
public void setIteratorNode(Node iteratorNode) {
this.iteratorNode = iteratorNode;
}
}

View File

@ -32,4 +32,18 @@ public abstract class LoopCondition extends Condition {
((Node)executableItem).setLoopIndex(index);
}
}
protected void setCurrLoopObject(Executable executableItem, Object obj){
if (executableItem instanceof Chain){
((Chain)executableItem).getConditionList().forEach(condition -> setCurrLoopObject(condition, obj));
}else if(executableItem instanceof Condition){
((Condition)executableItem).getExecutableList().forEach(executable -> setCurrLoopObject(executable, obj));
}else if(executableItem instanceof Node){
((Node)executableItem).setCurrLoopObject(obj);
}
}
protected Executable getDoExecutor() {
return this.getExecutableList().get(0);
}
}

View File

@ -35,11 +35,12 @@ public class WhileCondition extends LoopCondition{
int index = 0;
while(getWhileResult(slotIndex)){
executableItem.setCurrChainId(this.getCurrChainId());
setLoopIndex(executableItem, index++);
setLoopIndex(executableItem, index);
executableItem.execute(slotIndex);
//如果break组件不为空则去执行
if (ObjectUtil.isNotNull(breakNode)){
breakNode.setCurrChainId(this.getCurrChainId());
setLoopIndex(breakNode, index);
breakNode.execute(slotIndex);
Class<?> originalBreakClass = LiteFlowProxyUtil.getUserClass(this.breakNode.getInstance().getClass());
boolean isBreak = slot.getBreakResult(originalBreakClass.getName());
@ -47,22 +48,19 @@ public class WhileCondition extends LoopCondition{
break;
}
}
index++;
}
}
private boolean getWhileResult(Integer slotIndex) throws Exception{
Slot slot = DataBus.getSlot(slotIndex);
//执行while组件
whileNode.setCurrChainName(this.getCurrChainName());
whileNode.setCurrChainId(this.getCurrChainId());
whileNode.execute(slotIndex);
Class<?> originalWhileClass = LiteFlowProxyUtil.getUserClass(this.whileNode.getInstance().getClass());
return slot.getWhileResult(originalWhileClass.getName());
}
public Executable getDoExecutor() {
return this.getExecutableList().get(0);
}
@Override
public ConditionTypeEnum getConditionType() {
return ConditionTypeEnum.TYPE_WHILE;

View File

@ -0,0 +1,57 @@
package com.yomahub.liteflow.test.iterator;
import cn.hutool.core.collection.ListUtil;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
/**
* springboot环境最普通的例子测试
* @author Bryan.Zhang
* @since 2.6.4
*/
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/iterator/application.properties")
@SpringBootTest(classes = IteratorELDeclMultiSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.iterator.cmp"})
public class IteratorELDeclMultiSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
//最简单的情况
@Test
public void testIt1() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain1", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("123", str);
}
//迭代器带break
@Test
public void testIt2() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain2", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("12", str);
}
}

View File

@ -0,0 +1,42 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.base.cmp.TestDomain;
import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;
@LiteflowComponent
public class CmpConfig {
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeId = "a")
public void processA(NodeComponent bindCmp) {
String key = "test";
DefaultContext context = bindCmp.getFirstContextBean();
if (!context.hasData(key)){
context.setData(key, bindCmp.getCurrLoopObj());
}else{
String str = context.getData(key);
str += bindCmp.getCurrLoopObj();
context.setData(key, str);
}
}
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_BREAK, nodeId = "b", nodeType = NodeTypeEnum.BREAK)
public boolean processB(NodeComponent bindCmp) {
return bindCmp.getLoopIndex() == 1;
}
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_ITERATOR, nodeId = "it", nodeType = NodeTypeEnum.ITERATOR)
public Iterator<?> processIT(NodeComponent bindCmp) {
List<String> list = bindCmp.getRequestData();
return list.iterator();
}
}

View File

@ -0,0 +1 @@
liteflow.rule-source=iterator/flow.xml

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
<flow>
<chain name="chain1">
ITERATOR(it).DO(a);
</chain>
<chain name="chain2">
ITERATOR(it).DO(a).BREAK(b);
</chain>
</flow>

View File

@ -0,0 +1,57 @@
package com.yomahub.liteflow.test.iterator;
import cn.hutool.core.collection.ListUtil;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
/**
* springboot环境最普通的例子测试
* @author Bryan.Zhang
* @since 2.6.4
*/
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/iterator/application.properties")
@SpringBootTest(classes = IteratorELDeclSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.iterator.cmp"})
public class IteratorELDeclSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
//最简单的情况
@Test
public void testIt1() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain1", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("123", str);
}
//迭代器带break
@Test
public void testIt2() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain2", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("12", str);
}
}

View File

@ -0,0 +1,34 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.slot.DefaultContext;
import org.springframework.stereotype.Component;
@Component("a")
@LiteflowCmpDefine(NodeTypeEnum.COMMON)
public class ACmp{
@LiteflowMethod(LiteFlowMethodEnum.PROCESS)
public void process(NodeComponent bindCmp) {
String key = "test";
DefaultContext context = bindCmp.getFirstContextBean();
if (!context.hasData(key)){
context.setData(key, bindCmp.getCurrLoopObj());
}else{
String str = context.getData(key);
str += bindCmp.getCurrLoopObj();
context.setData(key, str);
}
}
}

View File

@ -0,0 +1,20 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeBreakComponent;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import org.springframework.stereotype.Component;
@Component("b")
@LiteflowCmpDefine(NodeTypeEnum.BREAK)
public class BCmp{
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_BREAK)
public boolean processBreak(NodeComponent bindCmp) throws Exception {
return bindCmp.getLoopIndex() == 1;
}
}

View File

@ -0,0 +1,22 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.core.NodeIteratorComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import org.springframework.stereotype.Component;
import java.util.Iterator;
import java.util.List;
@Component("it")
@LiteflowCmpDefine(NodeTypeEnum.ITERATOR)
public class ITCmp{
@LiteflowMethod(LiteFlowMethodEnum.PROCESS_ITERATOR)
public Iterator<?> processIterator(NodeComponent bindCmp) throws Exception {
List<String> list = bindCmp.getRequestData();
return list.iterator();
}
}

View File

@ -0,0 +1 @@
liteflow.rule-source=iterator/flow.xml

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
<flow>
<chain name="chain1">
ITERATOR(it).DO(a);
</chain>
<chain name="chain2">
ITERATOR(it).DO(a).BREAK(b);
</chain>
</flow>

View File

@ -0,0 +1,48 @@
package com.yomahub.liteflow.test.iterator;
import cn.hutool.core.collection.ListUtil;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.FlowExecutorHolder;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.List;
public class IteratorTest extends BaseTest{
private static FlowExecutor flowExecutor;
@BeforeClass
public static void init(){
LiteflowConfig config = new LiteflowConfig();
config.setRuleSource("iterator/flow.xml");
flowExecutor = FlowExecutorHolder.loadInstance(config);
}
//最简单的情况
@Test
public void testIt1() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain1", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("123", str);
}
//迭代器带break
@Test
public void testIt2() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain2", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("12", str);
}
}

View File

@ -0,0 +1,27 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.slot.DefaultContext;
public class ACmp extends NodeComponent {
@Override
public void process() {
String key = "test";
DefaultContext context = this.getFirstContextBean();
if (!context.hasData(key)){
context.setData(key, this.getCurrLoopObj());
}else{
String str = context.getData(key);
str += this.getCurrLoopObj();
context.setData(key, str);
}
}
}

View File

@ -0,0 +1,12 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeBreakComponent;
public class BCmp extends NodeBreakComponent {
@Override
public boolean processBreak() throws Exception {
return this.getLoopIndex() == 1;
}
}

View File

@ -0,0 +1,14 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeIteratorComponent;
import java.util.Iterator;
import java.util.List;
public class ITCmp extends NodeIteratorComponent {
@Override
public Iterator<?> processIterator() throws Exception {
List<String> list = this.getRequestData();
return list.iterator();
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
<flow>
<nodes>
<node id="a" class="com.yomahub.liteflow.test.iterator.cmp.ACmp"/>
<node id="b" class="com.yomahub.liteflow.test.iterator.cmp.BCmp"/>
<node id="it" class="com.yomahub.liteflow.test.iterator.cmp.ITCmp"/>
</nodes>
<chain name="chain1">
ITERATOR(it).DO(a);
</chain>
<chain name="chain2">
ITERATOR(it).DO(a).BREAK(b);
</chain>
</flow>

View File

@ -0,0 +1,55 @@
package com.yomahub.liteflow.test.iterator;
import cn.hutool.core.collection.ListUtil;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
/**
* springboot环境EL常规的例子测试
* @author Bryan.Zhang
*/
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/iterator/application.properties")
@SpringBootTest(classes = IteratorELSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.iterator.cmp"})
public class IteratorELSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
//最简单的情况
@Test
public void testIt1() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain1", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("123", str);
}
//迭代器带break
@Test
public void testIt2() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain2", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("12", str);
}
}

View File

@ -0,0 +1,29 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.slot.DefaultContext;
import org.springframework.stereotype.Component;
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
String key = "test";
DefaultContext context = this.getFirstContextBean();
if (!context.hasData(key)){
context.setData(key, this.getCurrLoopObj());
}else{
String str = context.getData(key);
str += this.getCurrLoopObj();
context.setData(key, str);
}
}
}

View File

@ -0,0 +1,15 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeBreakComponent;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@Component("b")
public class BCmp extends NodeBreakComponent {
@Override
public boolean processBreak() throws Exception {
return this.getLoopIndex() == 1;
}
}

View File

@ -0,0 +1,16 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeIteratorComponent;
import org.springframework.stereotype.Component;
import java.util.Iterator;
import java.util.List;
@Component("it")
public class ITCmp extends NodeIteratorComponent {
@Override
public Iterator<?> processIterator() throws Exception {
List<String> list = this.getRequestData();
return list.iterator();
}
}

View File

@ -0,0 +1 @@
liteflow.rule-source=iterator/flow.xml

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
<flow>
<chain name="chain1">
ITERATOR(it).DO(a);
</chain>
<chain name="chain2">
ITERATOR(it).DO(a).BREAK(b);
</chain>
</flow>

View File

@ -0,0 +1,45 @@
package com.yomahub.liteflow.test.iterator;
import cn.hutool.core.collection.ListUtil;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:/iterator/application.xml")
public class IteratorELSpringTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
//最简单的情况
@Test
public void testIt1() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain1", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("123", str);
}
//迭代器带break
@Test
public void testIt2() throws Exception{
List<String> list = ListUtil.toList("1","2","3");
LiteflowResponse response = flowExecutor.execute2Resp("chain2", list);
Assert.assertTrue(response.isSuccess());
DefaultContext context = response.getFirstContextBean();
String str = context.getData("test");
Assert.assertEquals("12", str);
}
}

View File

@ -0,0 +1,29 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.slot.DefaultContext;
import org.springframework.stereotype.Component;
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
String key = "test";
DefaultContext context = this.getFirstContextBean();
if (!context.hasData(key)){
context.setData(key, this.getCurrLoopObj());
}else{
String str = context.getData(key);
str += this.getCurrLoopObj();
context.setData(key, str);
}
}
}

View File

@ -0,0 +1,14 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeBreakComponent;
import org.springframework.stereotype.Component;
@Component("b")
public class BCmp extends NodeBreakComponent {
@Override
public boolean processBreak() throws Exception {
return this.getLoopIndex() == 1;
}
}

View File

@ -0,0 +1,16 @@
package com.yomahub.liteflow.test.iterator.cmp;
import com.yomahub.liteflow.core.NodeIteratorComponent;
import org.springframework.stereotype.Component;
import java.util.Iterator;
import java.util.List;
@Component("it")
public class ITCmp extends NodeIteratorComponent {
@Override
public Iterator<?> processIterator() throws Exception {
List<String> list = this.getRequestData();
return list.iterator();
}
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.yomahub.liteflow.test.iterator.cmp" />
<bean id="springAware" class="com.yomahub.liteflow.spi.spring.SpringAware"/>
<bean class="com.yomahub.liteflow.spring.ComponentScanner"/>
<bean id="liteflowConfig" class="com.yomahub.liteflow.property.LiteflowConfig">
<property name="ruleSource" value="iterator/flow.xml"/>
</bean>
<bean id="flowExecutor" class="com.yomahub.liteflow.core.FlowExecutor">
<constructor-arg name="liteflowConfig" ref="liteflowConfig"/>
</bean>
</beans>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
<flow>
<chain name="chain1">
ITERATOR(it).DO(a);
</chain>
<chain name="chain2">
ITERATOR(it).DO(a).BREAK(b);
</chain>
</flow>