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 d21dbf86..f010c102 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 @@ -15,6 +15,8 @@ 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 { @@ -24,19 +26,22 @@ public class LiteFlowNodeBuilder { /** * 用于维护不同类型 node 的处理逻辑 */ - private static final Map> NodeBuildConsumerMap = new HashMap>() {{ - put(NodeTypeEnum.COMMON, _node -> FlowBus.addCommonNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.SWITCH, _node -> FlowBus.addSwitchNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.IF, _node -> FlowBus.addIfNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.FOR, _node -> FlowBus.addForNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.WHILE, _node -> FlowBus.addWhileNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.BREAK, _node -> FlowBus.addBreakNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.SCRIPT, _node -> FlowBus.addCommonScriptNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.SWITCH_SCRIPT, _node -> FlowBus.addSwitchScriptNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.IF_SCRIPT, _node -> FlowBus.addIfScriptNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.FOR_SCRIPT, _node -> FlowBus.addForScriptNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.WHILE_SCRIPT, _node -> FlowBus.addWhileScriptNode(_node.getId(), _node.getName(), _node.getClazz())); - put(NodeTypeEnum.BREAK_SCRIPT, _node -> FlowBus.addBreakScriptNode(_node.getId(), _node.getName(), _node.getClazz())); + private static final Map> NodeBuildConsumerMap = new HashMap>() {{ + // 用于处理普通 node + put(NodeTypeEnum.COMMON, (_node, nodeType) -> FlowBus.addNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.SWITCH, (_node, nodeType) -> FlowBus.addNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.IF, (_node, nodeType) -> FlowBus.addNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.FOR, (_node, nodeType) -> FlowBus.addNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.WHILE, (_node, nodeType) -> FlowBus.addNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.BREAK, (_node, nodeType) -> FlowBus.addNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + + // 用于处理脚本 node + put(NodeTypeEnum.SCRIPT, (_node, nodeType) -> FlowBus.addScriptNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.SWITCH_SCRIPT, (_node, nodeType) -> FlowBus.addScriptNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.IF_SCRIPT, (_node, nodeType) -> FlowBus.addScriptNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.FOR_SCRIPT, (_node, nodeType) -> FlowBus.addScriptNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.WHILE_SCRIPT, (_node, nodeType) -> FlowBus.addScriptNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); + put(NodeTypeEnum.BREAK_SCRIPT, (_node, nodeType) -> FlowBus.addScriptNode(_node.getId(), _node.getName(), nodeType, _node.getClazz())); }}; private final Node node; @@ -153,7 +158,13 @@ public class LiteFlowNodeBuilder { public void build() { checkBuild(); try { - NodeBuildConsumerMap.get(this.node.getType()).accept(this.node); + for (Map.Entry> entry : NodeBuildConsumerMap.entrySet()) { + NodeTypeEnum nodeType = entry.getKey(); + if (nodeType == this.node.getType()) { + entry.getValue().accept(this.node, nodeType); + return; + } + } } catch (Exception e) { String errMsg = StrUtil.format("An exception occurred while building the node[{}],{}", this.node.getId(), e.getMessage()); LOG.error(errMsg, e); 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 5da625e9..c1f3f00c 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 { @@ -53,16 +55,28 @@ public class FlowBus { private static final Map nodeMap = new CopyOnWriteHashMap<>(); + /** + * 用于维护脚本类型和脚本 cmp 的映射关系 + */ + private static final 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); + }}; + 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,133 +102,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){ - throw new ComponentCannotRegisterException(e.getMessage()); - } - addNode(nodeId, name, NodeTypeEnum.COMMON, 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); - } - - public static void addNode(String nodeId, String name, NodeTypeEnum nodeType, String cmpClazzStr){ - Class cmpClazz; - try{ - cmpClazz = Class.forName(cmpClazzStr); - }catch (Exception e){ + } catch (Exception e) { throw new ComponentCannotRegisterException(e.getMessage()); } addNode(nodeId, name, nodeType, cmpClazz, null); } - public static void addScriptNode(String nodeId, String name, NodeTypeEnum nodeType, String script){ - addNode(nodeId, name, nodeType, ScriptCommonComponent.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, ScriptComponentClassMap.get(nodeType), script); } private static void addNode(String nodeId, String name, NodeTypeEnum type, Class cmpClazz, String script) { @@ -222,7 +156,7 @@ public class FlowBus { //判断此类是否是声明式的组件,如果是声明式的组件,就用动态代理生成实例 //如果不是声明式的,就用传统的方式进行判断 List cmpInstances = new ArrayList<>(); - if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)){ + if (LiteFlowProxyUtil.isDeclareCmp(cmpClazz)) { //这里的逻辑要仔细看下 //如果是spring体系,把原始的类往spring上下文中进行注册,那么会走到ComponentScanner中 //由于ComponentScanner中已经对原始类进行了动态代理,出来的对象已经变成了动态代理类,所以这时候的bean已经是NodeComponent的子类了 @@ -231,16 +165,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元素 @@ -268,11 +202,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); } @@ -283,7 +217,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); } @@ -297,19 +231,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; } @@ -321,12 +255,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 { @@ -339,18 +274,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 57dadf2b..088f926e 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 9891f4f5..610cb7b5 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());