Przeglądaj źródła

#IB0SJ1 新增不同Executable的处理和增加测试用例

jay li 5 miesięcy temu
rodzic
commit
48cce21896

+ 60 - 25
liteflow-core/src/main/java/com/yomahub/liteflow/flow/instanceId/BaseNodeInstanceIdManageSpi.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.crypto.digest.MD5;
 import com.yomahub.liteflow.flow.element.Chain;
 import com.yomahub.liteflow.flow.element.Condition;
+import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.flow.element.Node;
 import com.yomahub.liteflow.flow.entity.InstanceInfoDto;
 import org.apache.commons.lang.StringUtils;
@@ -60,37 +61,66 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
                 instanceInfos = parseList(instanceIdFile.get(i), InstanceInfoDto.class);
             }
             List<InstanceInfoDto> finalInstanceInfos = instanceInfos;
-            condition.getExecutableGroup().forEach((key, executables) -> {
-                Map<String, Integer> idCntMap = new HashMap<>();
-                executables.forEach(executable -> {
-                    if (executable instanceof Node) {
-                        Node node = (Node) executable;
-                        idCntMap.put(node.getId(), idCntMap.getOrDefault(node.getId(), -1) + 1);
-
-                        for (InstanceInfoDto dto : finalInstanceInfos) {
-                            if (Objects.equals(dto.getNodeId(), node.getId())
-                                    && Objects.equals(dto.getChainId(), chainId)
-                                    && Objects.equals(dto.getIndex(), idCntMap.get(node.getId()))) {
-                                node.setInstanceId(dto.getInstanceId());
-                                break;
-                            }
-                        }
+            Map<String, Integer> idCntMap = new HashMap<>();
+
+            setInstanceIdFromFile(finalInstanceInfos, chainId, condition.getExecutableGroup(), idCntMap);
+        }
+    }
+
+    // 从instanceIdFile里设置instanceId
+    private void setInstanceIdFromFile(List<InstanceInfoDto> finalInstanceInfos, String chainId,
+                                       Map<String, List<Executable>> executableGroup, Map<String, Integer> idCntMap) {
+        if (CollUtil.isEmpty(executableGroup)) {
+            return;
+        }
+
+        executableGroup.forEach((key, executables) -> {
+            executables.forEach(executable -> {
+                if (executable instanceof Node) {
+                    Node node = (Node) executable;
+                    idCntMap.put(node.getId(), idCntMap.getOrDefault(node.getId(), -1) + 1);
 
+                    for (InstanceInfoDto dto : finalInstanceInfos) {
+                        if (Objects.equals(dto.getNodeId(), node.getId())
+                                && Objects.equals(dto.getChainId(), chainId)
+                                && Objects.equals(dto.getIndex(), idCntMap.get(node.getId()))) {
+                            node.setInstanceId(dto.getInstanceId());
+                            break;
+                        }
                     }
-                });
+                } else if (executable instanceof Condition) {
+                    Condition conditionTmp = (Condition) executable;
+                    setInstanceIdFromFile(finalInstanceInfos, chainId, conditionTmp.getExecutableGroup(), idCntMap);
+                } else if (executable instanceof Chain) {
+                    Chain chainTmp = (Chain) executable;
+                    List<Condition> conditionList = chainTmp.getConditionList();
+                    conditionList.forEach(condition ->
+                            setInstanceIdFromFile(finalInstanceInfos, chainId, condition.getExecutableGroup(), idCntMap));
+                }
             });
-        }
+        });
     }
 
-    // 写入时第一行为el的md5,第二行为json格式的groupKey和对应的nodeId 和实例id
-    //          instanceId  a_XXX_0
-    //         {"chainId":"chain1","nodeId":"a","instanceId":"XXXX","index":0},
+    /**
+     * 写入时第一行为el的md5,第二行为json格式的groupKey和对应的nodeId 和实例id
+     * instanceId  a_XXX_0
+     * {"chainId":"chain1","nodeId":"a","instanceId":"XXXX","index":0},
+     */
     private List<InstanceInfoDto> writeNodeInstanceId(Condition condition, String chainId) {
         ArrayList<InstanceInfoDto> instanceInfos = new ArrayList<>();
 
-        condition.getExecutableGroup().forEach((key, executables) -> {
-            // 统计每个nodeId的索引
-            Map<String, Integer> idCntMap = new HashMap<>();
+        addInstanceIdFromExecutableGroup(instanceInfos, condition.getExecutableGroup(), chainId, new HashMap<>());
+
+        return instanceInfos;
+    }
+
+    // 往instanceInfos里添加实例id
+    private void addInstanceIdFromExecutableGroup(List<InstanceInfoDto> instanceInfos, Map<String, List<Executable>> executableGroup,
+                                                  String chainId, Map<String, Integer> idCntMap) {
+        if (CollUtil.isEmpty(executableGroup)) {
+            return;
+        }
+        executableGroup.forEach((key, executables) -> {
             executables.forEach(executable -> {
                 if (executable instanceof Node) {
                     Node node = (Node) executable;
@@ -110,11 +140,16 @@ public abstract class BaseNodeInstanceIdManageSpi implements NodeInstanceIdManag
                     instanceInfoDto.setIndex(idCntMap.get(node.getId()));
 
                     instanceInfos.add(instanceInfoDto);
+                } else if (executable instanceof Condition) {
+                    Condition conditionTmp = (Condition) executable;
+                    addInstanceIdFromExecutableGroup(instanceInfos, conditionTmp.getExecutableGroup(), chainId, idCntMap);
+                } else if (executable instanceof Chain) {
+                    Chain chainTmp = (Chain) executable;
+                    List<Condition> conditionList = chainTmp.getConditionList();
+                    conditionList.forEach(condition -> addInstanceIdFromExecutableGroup(instanceInfos, condition.getExecutableGroup(), chainId, idCntMap));
                 }
             });
         });
-
-        return instanceInfos;
     }
 
 }

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/cmp/ESwitchCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.sql.cmp;
+
+import com.yomahub.liteflow.core.NodeSwitchComponent;
+import org.springframework.stereotype.Component;
+
+@Component("e")
+public class ESwitchCmp extends NodeSwitchComponent {
+
+	@Override
+	public String processSwitch() throws Exception {
+		return "c";
+	}
+
+}

+ 17 - 0
liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sql/cmp/XCmp.java

@@ -0,0 +1,17 @@
+package com.yomahub.liteflow.test.sql.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;
+
+@LiteflowComponent("x")
+public class XCmp {
+
+	@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_FOR, nodeType = NodeTypeEnum.FOR)
+	public int processFor(NodeComponent bindCmp) throws Exception {
+		return 1;
+	}
+
+}

+ 99 - 11
liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/java/com/yomahub/liteflow/test/sqlInstanceId/SQLWithXmlELInstanceIdSpringbootTest.java

@@ -24,9 +24,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
 
 import javax.annotation.Resource;
 import java.sql.*;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -95,25 +93,103 @@ public class SQLWithXmlELInstanceIdSpringbootTest extends BaseTest {
     // 测试chain 表达式更改后,实例id是否变化
     @Test
     public void testSQLWithXmlChain3() throws SQLException, JSONException {
-        String chain4InstanceStr = querySqlInstanceId("r_chain4");
+        String chain4InstanceStr = queryInstanceStrByChainId("r_chain4");
         LiteflowResponse response = flowExecutor.execute2Resp("r_chain4", "arg");
         Assertions.assertEquals("c==>b==>a", response.getExecuteStepStr());
         Assertions.assertEquals(chain4InstanceStr, response.getExecuteStepStrWithInstanceId());
 
         // 更该数据 查实例id是否变化
-        changeData();
+        changeData("THEN(a, c, b);", "r_chain4");
         flowExecutor.reloadRule();
 
         // 重复查询
         response = flowExecutor.execute2Resp("r_chain4", "arg");
-        String chain4InstanceStr2 = querySqlInstanceId("r_chain4");
+        String chain4InstanceStr2 = queryInstanceStrByChainId("r_chain4");
         Assertions.assertNotEquals(chain4InstanceStr2, chain4InstanceStr);
         Assertions.assertEquals("a==>c==>b", flowExecutor.execute2Resp("r_chain4", "arg").getExecuteStepStr());
         Assertions.assertEquals(chain4InstanceStr2, response.getExecuteStepStrWithInstanceId());
     }
 
+    // chain3 if 脚本 切换 if表达试
+    @Test
+    public void testSQLWithXmlChain4() throws SQLException {
+
+        String chain4InstanceStr = queryInstanceStrByChainId("chain3");
+        LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
+
+        Assertions.assertEquals("x0[if 脚本]==>a==>b", response.getExecuteStepStr());
+        System.out.println(chain4InstanceStr);
+        Assertions.assertEquals(chain4InstanceStr, response.getExecuteStepStrWithInstanceId());
+        List<String> extractStrings = extractValuesList(chain4InstanceStr);
+        Assertions.assertEquals(Sets.newHashSet(extractStrings).size(), 3);
+
+        // 更该数据 查实例id是否变化
+        changeData("IF(x2, IF(x0, THEN(a, b)));", "chain3");
+        flowExecutor.reloadRule();
+
+        // 重复查询
+        response = flowExecutor.execute2Resp("chain3", "arg");
+        String chain4InstanceStr2 = queryInstanceStrByChainId("chain3");
+
+        Assertions.assertNotEquals(chain4InstanceStr2, chain4InstanceStr);
+        Assertions.assertEquals("x2[python脚本]==>x0[if 脚本]==>a==>b", response.getExecuteStepStr());
+        Assertions.assertEquals(chain4InstanceStr2, response.getExecuteStepStrWithInstanceId());
+
+        extractStrings = extractValuesList(chain4InstanceStr2);
+        Assertions.assertEquals(Sets.newHashSet(extractStrings).size(), 4);
+    }
+
+
+    // chain5 switch 切换 for 表达式
+    @Test
+    public void testSQLWithXmlChain5() throws SQLException {
+        String chainId = "chain5";
+
+        LiteflowResponse response = flowExecutor.execute2Resp(chainId, "arg");
+        String executeStepStr = response.getExecuteStepStr();
+        Assertions.assertEquals("e==>c", response.getExecuteStepStr());
+
+        String instancePath = constructInstancePath(executeStepStr, chainId);
+        Assertions.assertEquals(instancePath, response.getExecuteStepStrWithInstanceId());
+        List<String> extractStrings = extractValuesList(instancePath);
+        Assertions.assertEquals(Sets.newHashSet(extractStrings).size(), 2);
+
+        // 更该数据 查实例id是否变化
+        changeData("FOR(x).DO(CATCH(THEN(a,b,a)))", chainId);
+        flowExecutor.reloadRule();
+
+        // 重复查询
+        response = flowExecutor.execute2Resp(chainId, "arg");
+        String chain4InstanceStr2 = queryInstanceStrByChainId(chainId);
+        executeStepStr = response.getExecuteStepStr();
+        Assertions.assertEquals("x==>a==>b==>a", executeStepStr);
+
+        instancePath = constructInstancePath(executeStepStr, chainId);
+        Assertions.assertEquals(instancePath, response.getExecuteStepStrWithInstanceId());
+
+        extractStrings = extractValuesList(chain4InstanceStr2);
+        Assertions.assertEquals(Sets.newHashSet(extractStrings).size(), 4);
+    }
+
+    private String constructInstancePath(String executeStepStr, String chainId) throws SQLException {
+        Map<String, InstanceInfoDto> instanceMap = queryInstanceMapByChainId(chainId);
+        String[] nodes = executeStepStr.split("==>");
+
+        StringBuilder nodePathStr = new StringBuilder();
+        Map<String, Integer> tmpMap = new HashMap<>();
+        for (String node : nodes) {
+            tmpMap.put(node, tmpMap.getOrDefault(node, -1) + 1);
+            nodePathStr.append("==>").append(node).append("[")
+                    .append(instanceMap.get(node + "_" + tmpMap.get(node)).getInstanceId())
+                    .append("]");
+        }
+
+        return nodePathStr.toString().replaceFirst("==>", "");
+
+    }
+
     // 修改数据库数据
-    private void changeData() {
+    private void changeData(String chainElData, String chainId) {
         LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
         SQLParserVO sqlParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), SQLParserVO.class);
         Connection connection;
@@ -121,14 +197,13 @@ public class SQLWithXmlELInstanceIdSpringbootTest extends BaseTest {
             connection = DriverManager.getConnection(sqlParserVO.getUrl(), sqlParserVO.getUsername(),
                     sqlParserVO.getPassword());
             Statement statement = connection.createStatement();
-            statement.executeUpdate("UPDATE EL_TABLE SET EL_DATA='THEN(a, c, b);' WHERE chain_name='r_chain4'");
-        }
-        catch (SQLException e) {
+            statement.executeUpdate("UPDATE EL_TABLE SET EL_DATA='" + chainElData + "' WHERE chain_name='" + chainId + "'");
+        } catch (SQLException e) {
             throw new ELSQLException(e.getMessage());
         }
     }
 
-    private String querySqlInstanceId(String chainId) throws SQLException {
+    private String queryInstanceStrByChainId(String chainId) throws SQLException {
         // 查询数据库实例id
         String instanceId = queryInstanceIdInfo(chainId);
         // 解析 JSON
@@ -146,6 +221,19 @@ public class SQLWithXmlELInstanceIdSpringbootTest extends BaseTest {
         }
 
         return result.toString();
+    }
+
+    // key 为 nodeId_index
+    private Map<String, InstanceInfoDto> queryInstanceMapByChainId(String chainId) throws SQLException {
+        // 查询数据库实例id
+        String instanceId = queryInstanceIdInfo(chainId);
+        // 解析 JSON
+        List<InstanceInfoDto> instanceInfos = JsonUtil.parseList(instanceId, InstanceInfoDto.class);
+        // 构造实例id字符串
+        Map<String, InstanceInfoDto> result = new HashMap<>();
+        instanceInfos.forEach(instanceInfo -> result.put(instanceInfo.getNodeId() + "_" + instanceInfo.getIndex(), instanceInfo));
+
+        return result;
 
     }
 

+ 1 - 0
liteflow-testcase-el/liteflow-testcase-el-sql-springboot/src/test/resources/sql/data.sql

@@ -9,6 +9,7 @@ INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA,ROUTE,NAMESPACE) value
 INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA,ROUTE,NAMESPACE) values ('demo','r_chain2','THEN(c,b,a);','OR(r1,r2)','ns');
 INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA,CUSTOM_FILTER_TYPE) values ('demo','r_chain3','THEN(a,b,c);','biz1');
 INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA,CUSTOM_FILTER_TYPE) values ('demo','r_chain4','THEN(c,b,a);','biz2');
+INSERT INTO EL_TABLE (APPLICATION_NAME,CHAIN_NAME,EL_DATA) values ('demo','chain5','THEN(SWITCH(e).to(b, c));');
 
 DELETE FROM SCRIPT_NODE_TABLE;