diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java index befa91137..e8faff6a1 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java @@ -11,8 +11,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; public class LiteFlowNodeBuilder { @@ -132,33 +137,16 @@ public class LiteFlowNodeBuilder { public void build() { checkBuild(); try { - if (this.node.getType().equals(NodeTypeEnum.COMMON)) { - FlowBus.addCommonNode(this.node.getId(), this.node.getName(), this.node.getClazz()); - } else if (this.node.getType().equals(NodeTypeEnum.SWITCH)) { - FlowBus.addSwitchNode(this.node.getId(), this.node.getName(), this.node.getClazz()); - } else if (this.node.getType().equals(NodeTypeEnum.IF)) { - FlowBus.addIfNode(this.node.getId(), this.node.getName(), this.node.getClazz()); - } else if (this.node.getType().equals(NodeTypeEnum.FOR)) { - FlowBus.addForNode(this.node.getId(), this.node.getName(), this.node.getClazz()); - } else if (this.node.getType().equals(NodeTypeEnum.WHILE)) { - FlowBus.addWhileNode(this.node.getId(), this.node.getName(), this.node.getClazz()); - } else if (this.node.getType().equals(NodeTypeEnum.BREAK)) { - FlowBus.addBreakNode(this.node.getId(), this.node.getName(), this.node.getClazz()); - } else if (this.node.getType().equals(NodeTypeEnum.SCRIPT)) { - FlowBus.addCommonScriptNode(this.node.getId(), this.node.getName(), this.node.getScript()); - } else if (this.node.getType().equals(NodeTypeEnum.SWITCH_SCRIPT)) { - FlowBus.addSwitchScriptNode(this.node.getId(), this.node.getName(), this.node.getScript()); - } else if (this.node.getType().equals(NodeTypeEnum.IF_SCRIPT)) { - FlowBus.addIfScriptNode(this.node.getId(), this.node.getName(), this.node.getScript()); - } else if (this.node.getType().equals(NodeTypeEnum.FOR_SCRIPT)) { - FlowBus.addForScriptNode(this.node.getId(), this.node.getName(), this.node.getScript()); - } else if (this.node.getType().equals(NodeTypeEnum.WHILE_SCRIPT)) { - FlowBus.addWhileScriptNode(this.node.getId(), this.node.getName(), this.node.getScript()); - } else if (this.node.getType().equals(NodeTypeEnum.BREAK_SCRIPT)) { - FlowBus.addBreakScriptNode(this.node.getId(), this.node.getName(), this.node.getScript()); - } + // 用于处理脚本 node + if (this.node.getType().isScript()){ + FlowBus.addScriptNode(this.node.getId(), this.node.getName(), this.node.getType(), this.node.getScript()); + } + // 用于处理普通 node + else{ + FlowBus.addNode(this.node.getId(), this.node.getName(), this.node.getType(), this.node.getClazz()); + } } catch (Exception e) { - String errMsg = StrUtil.format("An exception occurred while building the node[{}],{}", this.node.getId(),e.getMessage()); + String errMsg = StrUtil.format("An exception occurred while building the node[{}],{}", this.node.getId(), e.getMessage()); LOG.error(errMsg, e); throw new NodeBuildException(errMsg); } diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java index 6584e1897..8a95c8840 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java @@ -1,11 +1,28 @@ package com.yomahub.liteflow.core; +import com.yomahub.liteflow.enums.NodeTypeEnum; + +import java.util.HashMap; +import java.util.Map; + /** * 脚本接口 * @author Bryan.Zhang * @since 2.9.0 */ public interface ScriptComponent { + /** + * 用于维护脚本类型和脚本 cmp 的映射关系 + */ + Map> ScriptComponentClassMap = new HashMap>() {{ + put(NodeTypeEnum.SCRIPT, ScriptCommonComponent.class); + put(NodeTypeEnum.SWITCH_SCRIPT, ScriptSwitchComponent.class); + put(NodeTypeEnum.IF_SCRIPT, ScriptIfComponent.class); + put(NodeTypeEnum.FOR_SCRIPT, ScriptForComponent.class); + put(NodeTypeEnum.WHILE_SCRIPT, ScriptWhileComponent.class); + put(NodeTypeEnum.BREAK_SCRIPT, ScriptBreakComponent.class); + }}; + /** * 加载脚本 diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java index 49ec8410a..e7c42879d 100644 --- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java +++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java @@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -43,6 +44,7 @@ import java.util.stream.Collectors; /** * 流程元数据类 + * * @author Bryan.Zhang */ public class FlowBus { @@ -56,13 +58,13 @@ public class FlowBus { private FlowBus() { } - public static Chain getChain(String id){ + public static Chain getChain(String id) { return chainMap.get(id); } //这一方法主要用于第一阶段chain的预装载 - public static void addChain(String chainName){ - if (!chainMap.containsKey(chainName)){ + public static void addChain(String chainName) { + if (!chainMap.containsKey(chainName)) { chainMap.put(chainName, new Chain(chainName)); } } @@ -88,119 +90,53 @@ public class FlowBus { //根据class来猜测类型 NodeTypeEnum type = NodeTypeEnum.guessType(nodeComponent.getClass()); - if (type == null){ + if (type == null) { throw new NullNodeTypeException(StrUtil.format("node type is null for node[{}]", nodeId)); } nodeMap.put(nodeId, new Node(ComponentInitializer.loadInstance().initComponent(nodeComponent, type, null, nodeId))); } - public static void addCommonNode(String nodeId, String name, String cmpClazzStr){ + /** + * 添加 node + * + * @param nodeId 节点id + * @param name 节点名称 + * @param type 节点类型 + * @param cmpClazz 节点组件类 + */ + public static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz) { + addNode(nodeId, name, type, cmpClazz, null); + } + + /** + * 添加 node + * + * @param nodeId 节点id + * @param name 节点名称 + * @param nodeType 节点类型 + * @param cmpClazzStr 节点组件类路径 + */ + public static void addNode(String nodeId, String name, NodeTypeEnum nodeType, String cmpClazzStr) { Class cmpClazz; - try{ + try { cmpClazz = Class.forName(cmpClazzStr); - }catch (Exception e){ + } catch (Exception e) { throw new ComponentCannotRegisterException(e.getMessage()); } - addNode(nodeId, name, NodeTypeEnum.COMMON, cmpClazz, null); + addNode(nodeId, name, nodeType, cmpClazz, null); } - public static void addCommonNode(String nodeId, String name, Class cmpClazz){ - addNode(nodeId, name, NodeTypeEnum.COMMON, cmpClazz, null); - } - - public static void addSwitchNode(String nodeId, String name, String cmpClazzStr){ - Class cmpClazz; - try{ - cmpClazz = Class.forName(cmpClazzStr); - }catch (Exception e){ - throw new ComponentCannotRegisterException(e.getMessage()); - } - addNode(nodeId, name, NodeTypeEnum.SWITCH, cmpClazz, null); - } - - public static void addSwitchNode(String nodeId, String name, Class cmpClazz){ - addNode(nodeId, name, NodeTypeEnum.SWITCH, cmpClazz, null); - } - - public static void addIfNode(String nodeId, String name, String cmpClazzStr){ - Class cmpClazz; - try{ - cmpClazz = Class.forName(cmpClazzStr); - }catch (Exception e){ - throw new ComponentCannotRegisterException(e.getMessage()); - } - addNode(nodeId, name, NodeTypeEnum.IF, cmpClazz, null); - } - - public static void addIfNode(String nodeId, String name, Class cmpClazz){ - addNode(nodeId, name, NodeTypeEnum.IF, cmpClazz, null); - } - - public static void addForNode(String nodeId, String name, String cmpClazzStr){ - Class cmpClazz; - try{ - cmpClazz = Class.forName(cmpClazzStr); - }catch (Exception e){ - throw new ComponentCannotRegisterException(e.getMessage()); - } - addNode(nodeId, name, NodeTypeEnum.FOR, cmpClazz, null); - } - - public static void addForNode(String nodeId, String name, Class cmpClazz){ - addNode(nodeId, name, NodeTypeEnum.FOR, cmpClazz, null); - } - - public static void addWhileNode(String nodeId, String name, String cmpClazzStr){ - Class cmpClazz; - try{ - cmpClazz = Class.forName(cmpClazzStr); - }catch (Exception e){ - throw new ComponentCannotRegisterException(e.getMessage()); - } - addNode(nodeId, name, NodeTypeEnum.WHILE, cmpClazz, null); - } - - public static void addWhileNode(String nodeId, String name, Class cmpClazz){ - addNode(nodeId, name, NodeTypeEnum.WHILE, cmpClazz, null); - } - - public static void addBreakNode(String nodeId, String name, String cmpClazzStr){ - Class cmpClazz; - try{ - cmpClazz = Class.forName(cmpClazzStr); - }catch (Exception e){ - throw new ComponentCannotRegisterException(e.getMessage()); - } - addNode(nodeId, name, NodeTypeEnum.BREAK, cmpClazz, null); - } - - public static void addBreakNode(String nodeId, String name, Class cmpClazz){ - addNode(nodeId, name, NodeTypeEnum.BREAK, cmpClazz, null); - } - - public static void addCommonScriptNode(String nodeId, String name, String script){ - addNode(nodeId, name, NodeTypeEnum.SCRIPT, ScriptCommonComponent.class, script); - } - - public static void addSwitchScriptNode(String nodeId, String name, String script){ - addNode(nodeId, name, NodeTypeEnum.SWITCH_SCRIPT, ScriptSwitchComponent.class, script); - } - - public static void addIfScriptNode(String nodeId, String name, String script){ - addNode(nodeId, name, NodeTypeEnum.IF_SCRIPT, ScriptIfComponent.class, script); - } - - public static void addForScriptNode(String nodeId, String name, String script){ - addNode(nodeId, name, NodeTypeEnum.FOR_SCRIPT, ScriptForComponent.class, script); - } - - public static void addWhileScriptNode(String nodeId, String name, String script){ - addNode(nodeId, name, NodeTypeEnum.WHILE_SCRIPT, ScriptWhileComponent.class, script); - } - - public static void addBreakScriptNode(String nodeId, String name, String script){ - addNode(nodeId, name, NodeTypeEnum.BREAK_SCRIPT, ScriptBreakComponent.class, script); + /** + * 添加脚本 node + * + * @param nodeId 节点id + * @param name 节点名称 + * @param nodeType 节点类型 + * @param script 脚本 + */ + public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script) { + addNode(nodeId, name, nodeType, ScriptComponent.ScriptComponentClassMap.get(nodeType), script); } private static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz, String script) { @@ -208,7 +144,7 @@ public class FlowBus { //判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例 //如果不是声明式的,就用传统的方式进行判断 List cmpInstances = new ArrayList<>(); - if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)){ + if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)) { //这里的逻辑要仔细看下 //如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中 //由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了 @@ -217,16 +153,16 @@ public class FlowBus { //这里用ContextAware的spi机制来判断是否spring体系 ContextAware contextAware = ContextAwareHolder.loadContextAware(); Object bean = ContextAwareHolder.loadContextAware().registerBean(nodeId, cmpClazz); - if (LocalContextAware.class.isAssignableFrom(contextAware.getClass())){ + if (LocalContextAware.class.isAssignableFrom(contextAware.getClass())) { cmpInstances = LiteFlowProxyUtil.proxy2NodeComponent(bean, nodeId); - }else { + } else { cmpInstances = ListUtil.toList((NodeComponent) bean); } - }else{ + } else { //以node方式配置,本质上是为了适配无spring的环境,如果有spring环境,其实不用这么配置 //这里的逻辑是判断是否能从spring上下文中取到,如果没有spring,则就是new instance了 //如果是script类型的节点,因为class只有一个,所以也不能注册进spring上下文,注册的时候需要new Instance - if (!type.isScript()){ + if (!type.isScript()) { cmpInstances = ListUtil.toList((NodeComponent) ContextAwareHolder.loadContextAware().registerOrGet(nodeId, cmpClazz)); } // 去除null元素 @@ -254,11 +190,11 @@ public class FlowBus { Node node = nodes.get(i); NodeComponent cmpInstance = cmpInstances.get(i); //如果是脚本节点,则还要加载script脚本 - if (type.isScript()){ - if (StrUtil.isNotBlank(script)){ + if (type.isScript()) { + if (StrUtil.isNotBlank(script)) { node.setScript(script); - ((ScriptComponent)cmpInstance).loadScript(script); - }else{ + ((ScriptComponent) cmpInstance).loadScript(script); + } else { String errorMsg = StrUtil.format("script for node[{}] is empty", nodeId); throw new ScriptLoadException(errorMsg); } @@ -269,7 +205,7 @@ public class FlowBus { } } catch (Exception e) { - String error = StrUtil.format("component[{}] register error", StrUtil.isEmpty(name)?nodeId:StrUtil.format("{}({})",nodeId,name)); + String error = StrUtil.format("component[{}] register error", StrUtil.isEmpty(name) ? nodeId : StrUtil.format("{}({})", nodeId, name)); LOG.error(e.getMessage()); throw new ComponentCannotRegisterException(error); } @@ -283,19 +219,19 @@ public class FlowBus { //那condNodeMap共用有关系么,原则上没有关系。但是从设计理念上,以后应该要分开 //tag和condNodeMap这2个属性不属于全局概念,属于每个chain范围的属性 public static Node copyNode(String nodeId) { - try{ + try { Node node = nodeMap.get(nodeId); return node.copy(); - }catch (Exception e){ + } catch (Exception e) { return null; } } - public static Map getNodeMap(){ + public static Map getNodeMap() { return nodeMap; } - public static Map getChainMap(){ + public static Map getChainMap() { return chainMap; } @@ -307,12 +243,13 @@ public class FlowBus { public static void cleanScriptCache() { //如果引入了脚本组件SPI,则还需要清理脚本的缓存 - try{ + try { ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance().getScriptExecutor(); - if (ObjectUtil.isNotNull(scriptExecutor)){ + if (ObjectUtil.isNotNull(scriptExecutor)) { scriptExecutor.cleanCache(); } - }catch (ScriptSpiException ignored){} + } catch (ScriptSpiException ignored) { + } } public static void refreshFlowMetaData(FlowParserTypeEnum type, String content) throws Exception { @@ -325,18 +262,18 @@ public class FlowBus { } } - public static boolean removeChain(String chainId){ - if (containChain(chainId)){ + public static boolean removeChain(String chainId) { + if (containChain(chainId)) { chainMap.remove(chainId); return true; - }else{ + } else { String errMsg = StrUtil.format("cannot find the chain[{}]", chainId); LOG.error(errMsg); return false; } } - public static void removeChain(String... chainIds){ + public static void removeChain(String... chainIds) { Arrays.stream(chainIds).forEach(FlowBus::removeChain); } } diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/flowmeta/FlowMetaTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/flowmeta/FlowMetaTest.java index 57dadf2b4..088f926e1 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/flowmeta/FlowMetaTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/flowmeta/FlowMetaTest.java @@ -2,6 +2,7 @@ package com.yomahub.liteflow.test.flowmeta; import com.yomahub.liteflow.core.FlowExecutor; import com.yomahub.liteflow.core.FlowExecutorHolder; +import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.property.LiteflowConfig; @@ -26,7 +27,7 @@ public class FlowMetaTest extends BaseTest { //测试动态添加元信息节点 @Test public void testFlowMeta() { - FlowBus.addCommonNode("d", "d组件", DCmp.class); + FlowBus.addNode("d", "d组件", NodeTypeEnum.COMMON, DCmp.class); LiteflowResponse response= flowExecutor.execute2Resp("chain1", "it's a request"); Assert.assertTrue(response.isSuccess()); Assert.assertEquals("a==>b==>c==>d[d组件]", response.getExecuteStepStr()); diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/flowmeta/FlowMetaELSpringTest.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/flowmeta/FlowMetaELSpringTest.java index 9891f4f55..610cb7b55 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/flowmeta/FlowMetaELSpringTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/flowmeta/FlowMetaELSpringTest.java @@ -1,6 +1,7 @@ package com.yomahub.liteflow.test.flowmeta; import com.yomahub.liteflow.core.FlowExecutor; +import com.yomahub.liteflow.enums.NodeTypeEnum; import com.yomahub.liteflow.flow.LiteflowResponse; import com.yomahub.liteflow.flow.FlowBus; import com.yomahub.liteflow.slot.DefaultContext; @@ -24,7 +25,7 @@ public class FlowMetaELSpringTest extends BaseTest { //测试动态添加元信息节点 @Test public void testFlowMeta() { - FlowBus.addCommonNode("d", "d组件", DCmp.class); + FlowBus.addNode("d", "d组件", NodeTypeEnum.COMMON, DCmp.class); LiteflowResponse response= flowExecutor.execute2Resp("chain1", "it's a request"); Assert.assertTrue(response.isSuccess()); Assert.assertEquals("a==>b==>c==>d[d组件]", response.getExecuteStepStr());