mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 12:12:08 +08:00
@@ -1,10 +1,12 @@
|
||||
package com.yomahub.liteflow.builder;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.entity.flow.Chain;
|
||||
import com.yomahub.liteflow.entity.flow.Condition;
|
||||
import com.yomahub.liteflow.entity.data.ExecutableEntity;
|
||||
import com.yomahub.liteflow.entity.flow.Node;
|
||||
import com.yomahub.liteflow.enums.ConditionTypeEnum;
|
||||
import com.yomahub.liteflow.exception.ExecutableItemNotFoundException;
|
||||
@@ -14,6 +16,7 @@ import com.yomahub.liteflow.parser.RegexNodeEntity;
|
||||
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Condition基于代码形式的组装器
|
||||
@@ -58,51 +61,87 @@ public class LiteFlowConditionBuilder {
|
||||
|
||||
RegexEntity regexEntity;
|
||||
String itemExpression;
|
||||
RegexNodeEntity item;
|
||||
for (String s : condArray) {
|
||||
itemExpression = s.trim();
|
||||
regexEntity = RegexEntity.parse(itemExpression);
|
||||
item = regexEntity.getItem();
|
||||
if (FlowBus.containNode(item.getId())) {
|
||||
Node node = FlowBus.copyNode(item.getId());
|
||||
node.setTag(regexEntity.getItem().getTag());
|
||||
this.condition.getNodeList().add(node);
|
||||
//这里判断是不是条件节点,条件节点会含有realItem,也就是括号里的node
|
||||
if (ObjectUtil.isNotNull(regexEntity.getRealItemArray())) {
|
||||
for (RegexNodeEntity realItem : regexEntity.getRealItemArray()) {
|
||||
if (FlowBus.containNode(realItem.getId())) {
|
||||
Node condNode = FlowBus.copyNode(realItem.getId());
|
||||
condNode.setTag(realItem.getTag());
|
||||
node.setCondNode(condNode.getId(), condNode);
|
||||
} else if (hasChain(realItem.getId())) {
|
||||
Chain chain = FlowBus.getChain(realItem.getId());
|
||||
node.setCondNode(chain.getChainName(), chain);
|
||||
} else{
|
||||
String errorMsg = StrUtil.format("executable node[{}] is not found!", realItem.getId());
|
||||
throw new ExecutableItemNotFoundException(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (hasChain(item.getId())) {
|
||||
Chain chain = FlowBus.getChain(item.getId());
|
||||
this.condition.getNodeList().add(chain);
|
||||
} else {
|
||||
//元数据没有的话,从spring上下文再取一遍
|
||||
//这部分有2个目的
|
||||
//一是为了防止标有@Lazy懒加载的组件,二是spring负责扫描,而用代码的形式加载chain这种情况。
|
||||
NodeComponent nodeComponent = ContextAwareHolder.loadContextAware().getBean(item.getId());
|
||||
if (ObjectUtil.isNotNull(nodeComponent)){
|
||||
FlowBus.addSpringScanNode(item.getId(), nodeComponent);
|
||||
setValue(item.getId());
|
||||
} else{
|
||||
String errorMsg = StrUtil.format("executable node[{}] is not found!", regexEntity.getItem().getId());
|
||||
throw new ExecutableItemNotFoundException(errorMsg);
|
||||
}
|
||||
// 先转化为执行实体对象
|
||||
ExecutableEntity executableEntity = convertExecutableEntity(regexEntity);
|
||||
// 构建节点或流程
|
||||
setExecutable(executableEntity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 将正则表达式实体转化为执行实体
|
||||
private ExecutableEntity convertExecutableEntity(RegexEntity regexEntity) {
|
||||
RegexNodeEntity item = regexEntity.getItem();
|
||||
ExecutableEntity executableEntity = new ExecutableEntity(item.getId(), item.getTag());
|
||||
if (ObjectUtil.isNotNull(regexEntity.getRealItemArray())) {
|
||||
for (RegexNodeEntity realItem : regexEntity.getRealItemArray()) {
|
||||
executableEntity.addNodeCondComponent(new ExecutableEntity(realItem.getId(), realItem.getTag()));
|
||||
}
|
||||
}
|
||||
return executableEntity;
|
||||
}
|
||||
|
||||
// 设置执行节点或流程列表
|
||||
public LiteFlowConditionBuilder setExecutables(List<ExecutableEntity> executableEntities) {
|
||||
if (CollUtil.isEmpty(executableEntities)) {
|
||||
return this;
|
||||
}
|
||||
for (ExecutableEntity conditionNodeEntity : executableEntities) {
|
||||
setExecutable(conditionNodeEntity);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 设置执行节点或者流程
|
||||
public LiteFlowConditionBuilder setExecutable(ExecutableEntity executableEntity) {
|
||||
if (FlowBus.containNode(executableEntity.getId())) {
|
||||
Node node = FlowBus.copyNode(executableEntity.getId());
|
||||
node.setTag(executableEntity.getTag());
|
||||
this.condition.getNodeList().add(node);
|
||||
// 构建条件节点-通过是否包含条件节点列表-解析条件节点会含有realItem,也就是括号里的node
|
||||
buildCondNode(node, executableEntity.getNodeCondComponents());
|
||||
} else if (hasChain(executableEntity.getId())) {
|
||||
Chain chain = FlowBus.getChain(executableEntity.getId());
|
||||
this.condition.getNodeList().add(chain);
|
||||
} else {
|
||||
//元数据没有的话,从spring上下文再取一遍
|
||||
//这部分有2个目的
|
||||
//一是为了防止标有@Lazy懒加载的组件,二是spring负责扫描,而用代码的形式加载chain这种情况。
|
||||
NodeComponent nodeComponent = ContextAwareHolder.loadContextAware().getBean(executableEntity.getId());
|
||||
if (ObjectUtil.isNotNull(nodeComponent)){
|
||||
FlowBus.addSpringScanNode(executableEntity.getId(), nodeComponent);
|
||||
setExecutable(executableEntity);
|
||||
} else{
|
||||
String errorMsg = StrUtil.format("executable node[{}] is not found!", executableEntity.getId());
|
||||
throw new ExecutableItemNotFoundException(errorMsg);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 构建条件节点
|
||||
private void buildCondNode(Node node, List<ExecutableEntity> executableEntities) {
|
||||
if (CollUtil.isEmpty(executableEntities)) {
|
||||
return;
|
||||
}
|
||||
for (ExecutableEntity realItem : executableEntities) {
|
||||
if (FlowBus.containNode(realItem.getId())) {
|
||||
Node condNode = FlowBus.copyNode(realItem.getId());
|
||||
condNode.setTag(realItem.getTag());
|
||||
node.setCondNode(condNode.getId(), condNode);
|
||||
} else if (hasChain(realItem.getId())) {
|
||||
Chain chain = FlowBus.getChain(realItem.getId());
|
||||
node.setCondNode(chain.getChainName(), chain);
|
||||
} else{
|
||||
String errorMsg = StrUtil.format("executable node[{}] is not found!", realItem.getId());
|
||||
throw new ExecutableItemNotFoundException(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Condition build(){
|
||||
return this.condition;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.yomahub.liteflow.entity.data;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 执行器的实体类
|
||||
* </pre>
|
||||
*
|
||||
* @author sikadai
|
||||
* @version 2.6.11
|
||||
* @since 2022/3/13 15:28
|
||||
*/
|
||||
public class ExecutableEntity {
|
||||
private String id;
|
||||
private String tag;
|
||||
private List<ExecutableEntity> nodeCondComponents;
|
||||
|
||||
public ExecutableEntity() {
|
||||
|
||||
}
|
||||
|
||||
public ExecutableEntity(String id, String tag) {
|
||||
this.id = id;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ExecutableEntity setId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public ExecutableEntity setTag(String tag) {
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<ExecutableEntity> getNodeCondComponents() {
|
||||
return nodeCondComponents;
|
||||
}
|
||||
|
||||
public ExecutableEntity setNodeCondComponents(List<ExecutableEntity> nodeCondComponents) {
|
||||
this.nodeCondComponents = nodeCondComponents;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExecutableEntity addNodeCondComponent(ExecutableEntity conditionNodeEntity) {
|
||||
if (CollUtil.isEmpty(this.nodeCondComponents)) {
|
||||
this.nodeCondComponents = Lists.newArrayList();
|
||||
}
|
||||
this.nodeCondComponents.add(conditionNodeEntity);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.core.FlowExecutorHolder;
|
||||
import com.yomahub.liteflow.entity.data.DefaultSlot;
|
||||
import com.yomahub.liteflow.entity.data.LiteflowResponse;
|
||||
import com.yomahub.liteflow.entity.data.ExecutableEntity;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.property.LiteflowConfig;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
@@ -145,4 +146,72 @@ public class BuilderTest extends BaseTest {
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getSlot().getExecuteStepStr());
|
||||
}
|
||||
|
||||
//基于普通组件的builder模式测试
|
||||
@Test
|
||||
public void testBuilderForConditionNode() throws Exception {
|
||||
LiteFlowNodeBuilder.createNode().setId("a")
|
||||
.setName("组件A")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(ACmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("b")
|
||||
.setName("组件B")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(BCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("c")
|
||||
.setName("组件C")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(CCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("d")
|
||||
.setName("组件D")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(DCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("e")
|
||||
.setName("组件E")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(ECmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("f")
|
||||
.setName("组件F")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(FCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("g")
|
||||
.setName("组件G")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(GCmp.class)
|
||||
.build();
|
||||
|
||||
|
||||
LiteFlowChainBuilder.createChain().setChainName("chain2").setCondition(
|
||||
LiteFlowConditionBuilder.createThenCondition()
|
||||
.setExecutable(new ExecutableEntity().setId("c"))
|
||||
.setExecutable(new ExecutableEntity().setId("d"))
|
||||
.build()
|
||||
).build();
|
||||
|
||||
LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition(
|
||||
LiteFlowConditionBuilder
|
||||
.createWhenCondition()
|
||||
.setExecutable(new ExecutableEntity().setId("a").setTag("hello"))
|
||||
.setExecutable(new ExecutableEntity().setId("b"))
|
||||
.build()
|
||||
).setCondition(
|
||||
LiteFlowConditionBuilder.createWhenCondition()
|
||||
.setExecutable(
|
||||
new ExecutableEntity().setId("e")
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("f").setTag("FHello"))
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("g"))
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("chain2")
|
||||
)).build()
|
||||
).build();
|
||||
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain1");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getSlot().getExecuteStepStr());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.entity.data.DefaultSlot;
|
||||
import com.yomahub.liteflow.entity.data.LiteflowResponse;
|
||||
import com.yomahub.liteflow.entity.data.ExecutableEntity;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import com.yomahub.liteflow.test.builder.cmp1.ACmp;
|
||||
@@ -150,4 +151,73 @@ public class BuilderSpringbootTest1 extends BaseTest {
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getSlot().getExecuteStepStr());
|
||||
}
|
||||
|
||||
|
||||
//基于普通组件的builder模式测试
|
||||
@Test
|
||||
public void testBuilderForConditionNode() throws Exception {
|
||||
LiteFlowNodeBuilder.createNode().setId("a")
|
||||
.setName("组件A")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(ACmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("b")
|
||||
.setName("组件B")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(BCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("c")
|
||||
.setName("组件C")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(CCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("d")
|
||||
.setName("组件D")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(DCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("e")
|
||||
.setName("组件E")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(ECmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("f")
|
||||
.setName("组件F")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(FCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("g")
|
||||
.setName("组件G")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(GCmp.class)
|
||||
.build();
|
||||
|
||||
|
||||
LiteFlowChainBuilder.createChain().setChainName("chain2").setCondition(
|
||||
LiteFlowConditionBuilder.createThenCondition()
|
||||
.setExecutable(new ExecutableEntity().setId("c"))
|
||||
.setExecutable(new ExecutableEntity().setId("d"))
|
||||
.build()
|
||||
).build();
|
||||
|
||||
LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition(
|
||||
LiteFlowConditionBuilder
|
||||
.createWhenCondition()
|
||||
.setExecutable(new ExecutableEntity().setId("a").setTag("hello"))
|
||||
.setExecutable(new ExecutableEntity().setId("b"))
|
||||
.build()
|
||||
).setCondition(
|
||||
LiteFlowConditionBuilder.createWhenCondition()
|
||||
.setExecutable(
|
||||
new ExecutableEntity().setId("e")
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("f").setTag("FHello"))
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("g"))
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("chain2")
|
||||
)).build()
|
||||
).build();
|
||||
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain1");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getSlot().getExecuteStepStr());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.entity.data.DefaultSlot;
|
||||
import com.yomahub.liteflow.entity.data.LiteflowResponse;
|
||||
import com.yomahub.liteflow.entity.data.ExecutableEntity;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import com.yomahub.liteflow.test.builder.cmp1.*;
|
||||
@@ -131,7 +132,7 @@ public class BuilderSpringTest1 extends BaseTest {
|
||||
LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition(
|
||||
LiteFlowConditionBuilder
|
||||
.createWhenCondition()
|
||||
.setValue("a,b").build()
|
||||
.setValue("a[hello],b").build()
|
||||
).setCondition(
|
||||
LiteFlowConditionBuilder.createWhenCondition()
|
||||
.setValue("e(f|g|chain2)").build()
|
||||
@@ -140,4 +141,71 @@ public class BuilderSpringTest1 extends BaseTest {
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain1");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
}
|
||||
|
||||
//基于普通组件的builder模式测试
|
||||
@Test
|
||||
public void testBuilderForConditionNode() throws Exception {
|
||||
LiteFlowNodeBuilder.createNode().setId("a")
|
||||
.setName("组件A")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(ACmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("b")
|
||||
.setName("组件B")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(BCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("c")
|
||||
.setName("组件C")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(CCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("d")
|
||||
.setName("组件D")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(DCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("e")
|
||||
.setName("组件E")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(ECmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("f")
|
||||
.setName("组件F")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(FCmp.class)
|
||||
.build();
|
||||
LiteFlowNodeBuilder.createNode().setId("g")
|
||||
.setName("组件G")
|
||||
.setTypeCode(NodeTypeEnum.COMMON.getCode())
|
||||
.setNodeComponentClazz(GCmp.class)
|
||||
.build();
|
||||
|
||||
|
||||
LiteFlowChainBuilder.createChain().setChainName("chain2").setCondition(
|
||||
LiteFlowConditionBuilder.createThenCondition()
|
||||
.setExecutable(new ExecutableEntity().setId("c"))
|
||||
.setExecutable(new ExecutableEntity().setId("d"))
|
||||
.build()
|
||||
).build();
|
||||
|
||||
LiteFlowChainBuilder.createChain().setChainName("chain1").setCondition(
|
||||
LiteFlowConditionBuilder
|
||||
.createWhenCondition()
|
||||
.setExecutable(new ExecutableEntity().setId("a").setTag("hello"))
|
||||
.setExecutable(new ExecutableEntity().setId("b"))
|
||||
.build()
|
||||
).setCondition(
|
||||
LiteFlowConditionBuilder.createWhenCondition()
|
||||
.setExecutable(
|
||||
new ExecutableEntity().setId("e")
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("f").setTag("FHello"))
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("g"))
|
||||
.addNodeCondComponent(new ExecutableEntity().setId("chain2")
|
||||
)).build()
|
||||
).build();
|
||||
|
||||
LiteflowResponse<DefaultSlot> response = flowExecutor.execute2Resp("chain1");
|
||||
Assert.assertTrue(response.isSuccess());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
System.out.println(getTag() + ",ACmp executed!");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user