From 9f8794649baebfdb971033ff636161b6a3052024 Mon Sep 17 00:00:00 2001 From: daiqi <466608943@qq.com> Date: Sun, 13 Mar 2022 16:30:13 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8F=AF=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=AE=9E=E4=BD=93=E5=AF=B9=E8=B1=A1=E4=BD=9C=E4=B8=BA?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E6=B5=81=E7=A8=8B=E7=9A=84=E4=B8=AD=E9=97=B4?= =?UTF-8?q?=E8=BD=BD=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/LiteFlowConditionBuilder.java | 113 ++++++++++++------ .../entity/data/ExecutableEntity.java | 65 ++++++++++ .../liteflow/test/builder/BuilderTest.java | 69 +++++++++++ .../test/builder/BuilderSpringbootTest1.java | 70 +++++++++++ .../test/builder/BuilderSpringTest1.java | 70 ++++++++++- 5 files changed, 349 insertions(+), 38 deletions(-) create mode 100644 liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/ExecutableEntity.java diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowConditionBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowConditionBuilder.java index 97228e77e..926844c26 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowConditionBuilder.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowConditionBuilder.java @@ -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 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 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; } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/ExecutableEntity.java b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/ExecutableEntity.java new file mode 100644 index 000000000..749396ecb --- /dev/null +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/entity/data/ExecutableEntity.java @@ -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; + +/** + *
+ *  执行器的实体类
+ * 
+ * + * @author sikadai + * @version 2.6.11 + * @since 2022/3/13 15:28 + */ +public class ExecutableEntity { + private String id; + private String tag; + private List 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 getNodeCondComponents() { + return nodeCondComponents; + } + + public ExecutableEntity setNodeCondComponents(List 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; + } +} diff --git a/liteflow-testcase-nospring/src/test/java/com/yomahub/liteflow/test/builder/BuilderTest.java b/liteflow-testcase-nospring/src/test/java/com/yomahub/liteflow/test/builder/BuilderTest.java index 739935f9c..e9a83f7e5 100644 --- a/liteflow-testcase-nospring/src/test/java/com/yomahub/liteflow/test/builder/BuilderTest.java +++ b/liteflow-testcase-nospring/src/test/java/com/yomahub/liteflow/test/builder/BuilderTest.java @@ -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 response = flowExecutor.execute2Resp("chain1"); + Assert.assertTrue(response.isSuccess()); + Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getSlot().getExecuteStepStr()); + } } diff --git a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringbootTest1.java b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringbootTest1.java index 57fd896bc..c42ece71a 100644 --- a/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringbootTest1.java +++ b/liteflow-testcase-springboot/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringbootTest1.java @@ -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 response = flowExecutor.execute2Resp("chain1"); + Assert.assertTrue(response.isSuccess()); + Assert.assertEquals("a[组件A]==>b[组件B]==>e[组件E]==>c[组件C]==>d[组件D]", response.getSlot().getExecuteStepStr()); + } } diff --git a/liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringTest1.java b/liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringTest1.java index 2ea2cf458..bfa137c34 100644 --- a/liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringTest1.java +++ b/liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/builder/BuilderSpringTest1.java @@ -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 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 response = flowExecutor.execute2Resp("chain1"); + Assert.assertTrue(response.isSuccess()); + } } From c4551fbd8fe3c69fbaf73f413aa4b51feb37ef80 Mon Sep 17 00:00:00 2001 From: sikadai Date: Sun, 13 Mar 2022 17:12:02 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9Acmp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java b/liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java index 9fbbfba46..ed0e7458d 100644 --- a/liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java +++ b/liteflow-testcase-springnative/src/test/java/com/yomahub/liteflow/test/builder/cmp1/ACmp.java @@ -13,6 +13,6 @@ public class ACmp extends NodeComponent { @Override public void process() { - System.out.println("ACmp executed!"); + System.out.println(getTag() + ",ACmp executed!"); } }