Browse Source

feature #IBW9PC 上下文表达式搜索&设置,摆脱对上下文的依赖

everywhere.z 1 month ago
parent
commit
9e9d1e28b2
14 changed files with 401 additions and 7 deletions
  1. 11 7
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java
  2. 51 0
      liteflow-core/src/main/java/com/yomahub/liteflow/util/LiteflowContextRegexMatcher.java
  3. 100 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/SearchContextSpringbootTest.java
  4. 23 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A1Cmp.java
  5. 23 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A2Cmp.java
  6. 22 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A3Cmp.java
  7. 22 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A4Cmp.java
  8. 22 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A5Cmp.java
  9. 28 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/context/Member.java
  10. 24 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/context/MemberContext.java
  11. 34 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/context/OrderContext.java
  12. 17 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/context/UserInfoContext.java
  13. 1 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/searchContext/application.properties
  14. 23 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/searchContext/flow.xml

+ 11 - 7
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java

@@ -476,14 +476,23 @@ public abstract class NodeComponent{
 		}
 		}
 	}
 	}
 
 
-	public <T> List<T> getBindDataList(Class<T> clazz) {
-		String bindData = getRefNode().getCmpData();
+	public <T> List<T> getBindDataList(String key, Class<T> clazz) {
+		String bindData = getRefNode().getBindData(key);
 		if (StrUtil.isBlank(bindData)) {
 		if (StrUtil.isBlank(bindData)) {
 			return null;
 			return null;
 		}
 		}
 		return JsonUtil.parseList(bindData, clazz);
 		return JsonUtil.parseList(bindData, clazz);
 	}
 	}
 
 
+	@SuppressWarnings("unchecked")
+	public <T> T getContextValue(String expression){
+		return (T)LiteflowContextRegexMatcher.searchContext(this.getSlot().getContextBeanList(), expression);
+	}
+
+	public void setContextValue(String methodExpress, Object... values){
+		LiteflowContextRegexMatcher.searchAndSetContext(this.getSlot().getContextBeanList(), methodExpress, values);
+	}
+
 	public Integer getLoopIndex() {
 	public Integer getLoopIndex() {
 		return this.getRefNode().getLoopIndex();
 		return this.getRefNode().getLoopIndex();
 	}
 	}
@@ -539,9 +548,4 @@ public abstract class NodeComponent{
 		return originalClass.getName();
 		return originalClass.getName();
 	}
 	}
 
 
-	public static void main(String[] args) {
-
-		boolean flag = ReUtil.isMatch(ChainConstant.CONTEXT_SEARCH_REGEX, "${user.name}");
-		System.out.println(ReUtil.getGroup1(ChainConstant.CONTEXT_SEARCH_REGEX, "${user.name}"));
-	}
 }
 }

+ 51 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/util/LiteflowContextRegexMatcher.java

@@ -1,14 +1,22 @@
 package com.yomahub.liteflow.util;
 package com.yomahub.liteflow.util;
 
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.lang.Tuple;
 import cn.hutool.core.lang.Tuple;
+import cn.hutool.core.util.BooleanUtil;
+import cn.hutool.core.util.StrUtil;
 import com.ql.util.express.DefaultContext;
 import com.ql.util.express.DefaultContext;
 import com.ql.util.express.ExpressRunner;
 import com.ql.util.express.ExpressRunner;
 import com.ql.util.express.InstructionSet;
 import com.ql.util.express.InstructionSet;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.IntFunction;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 
 /**
 /**
  * LiteFlow上下文正则表达式匹配器
  * LiteFlow上下文正则表达式匹配器
@@ -54,4 +62,47 @@ public class LiteflowContextRegexMatcher {
 
 
         return result;
         return result;
     }
     }
+
+    public static void searchAndSetContext(List<Tuple> contextList, String methodExpress, Object... args){
+        // 把上下文数据转换成map形式的,key为别名,value为上下文
+        Map<String, Object> contextMap = contextList.stream().collect(
+                Collectors.toMap(tuple -> tuple.get(0), tuple -> tuple.get(1))
+        );
+
+        List<String> errorList = new ArrayList<>();
+
+        boolean flag = false;
+
+        String argStr = IntStream.range(0, args.length).mapToObj(
+                idx -> StrUtil.format("arg{}", idx)
+        ).collect(Collectors.joining(","));
+
+        List<TupleOf2<String, Integer>> tupleList = IntStream.range(0, args.length).mapToObj(
+                idx -> new TupleOf2<>(StrUtil.format("arg{}", idx), idx)
+        ).collect(Collectors.toList());
+
+        for(Map.Entry<String, Object> entry : contextMap.entrySet()){
+            try{
+                InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(StrUtil.format("{}.{}({})", entry.getKey(), methodExpress, argStr));
+                DefaultContext<String, Object> context = new DefaultContext<>();
+                context.put(entry.getKey(), entry.getValue());
+                tupleList.forEach(tuple -> context.put(tuple.getA(), args[tuple.getB()]));
+                expressRunner.execute(instructionSet, context, errorList, false, false);
+                flag = true;
+                break;
+            }catch (Exception ignore){}
+        }
+
+        // 根据表达式去上下文里搜索相匹配的数据
+        if (BooleanUtil.isFalse(flag)){
+            try{
+                // 如果没有搜到,那么尝试推断表达式是指定的上下文,按照指定上下文的方式去再获取
+                InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(StrUtil.format("contextMap.{}({})", methodExpress, argStr));
+                DefaultContext<String, Object> context = new DefaultContext<>();
+                context.put("contextMap", contextMap);
+                tupleList.forEach(tuple -> context.put(tuple.getA(), args[tuple.getB()]));
+                expressRunner.execute(instructionSet, context, errorList, false, false);
+            }catch (Exception ignore){}
+        }
+    }
 }
 }

+ 100 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/SearchContextSpringbootTest.java

@@ -0,0 +1,100 @@
+package com.yomahub.liteflow.test.searchContext;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.test.searchContext.context.Member;
+import com.yomahub.liteflow.test.searchContext.context.MemberContext;
+import com.yomahub.liteflow.test.searchContext.context.OrderContext;
+import com.yomahub.liteflow.test.searchContext.context.UserInfoContext;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.TestPropertySource;
+
+import javax.annotation.Resource;
+
+/**
+ * springboot环境EL常规的例子测试
+ *
+ * @author Bryan.Zhang
+ */
+@TestPropertySource(value = "classpath:/searchContext/application.properties")
+@SpringBootTest(classes = SearchContextSpringbootTest.class)
+@EnableAutoConfiguration
+@ComponentScan({"com.yomahub.liteflow.test.searchContext.cmp"})
+public class SearchContextSpringbootTest extends BaseTest {
+
+	@Resource
+	private FlowExecutor flowExecutor;
+
+	// 测试动态取,动态设置的基础情况
+	@Test
+	public void testSearchContext1() throws Exception {
+		MemberContext memberContext = new MemberContext();
+		memberContext.setId(31);
+		memberContext.setName("jack");
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", memberContext, new DefaultContext());
+		Assertions.assertTrue(response.isSuccess());
+		MemberContext context = response.getContextBean(MemberContext.class);
+		Assertions.assertEquals("hello,jack", context.getName());
+	}
+
+	// 测试动态取,2个上下文智能设置,1个参数
+	@Test
+	public void testSearchContext2() throws Exception {
+		MemberContext memberContext = new MemberContext();
+		memberContext.setId(31);
+		memberContext.setName("jack");
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg", memberContext, new DefaultContext());
+		Assertions.assertTrue(response.isSuccess());
+		MemberContext context = response.getContextBean(MemberContext.class);
+		Assertions.assertEquals("hello,jack", context.getName());
+	}
+
+	// 多级动态取,2个上下文智能设置,多个参数
+	@Test
+	public void testSearchContext3() throws Exception {
+		OrderContext orderContext = new OrderContext();
+		orderContext.setOrderCode("SO1234");
+		orderContext.setMember(new Member("M0001","jack"));
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg", orderContext, new DefaultContext());
+		Assertions.assertTrue(response.isSuccess());
+		DefaultContext context = response.getContextBean(DefaultContext.class);
+		Assertions.assertEquals("M0001", context.getData("test"));
+	}
+
+	// 3个上下文指定上下文取和设置
+	@Test
+	public void testSearchContext4() throws Exception {
+		MemberContext memberContext = new MemberContext();
+		memberContext.setId(2000);
+		memberContext.setName("jack");
+
+		OrderContext orderContext = new OrderContext();
+		orderContext.setId(3000);
+		orderContext.setOrderCode("SO1234");
+		orderContext.setMember(new Member("M0001","jack"));
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg", memberContext, orderContext, new DefaultContext());
+		Assertions.assertTrue(response.isSuccess());
+		DefaultContext context = response.getContextBean(DefaultContext.class);
+		Assertions.assertEquals(3000, (Integer) context.getData("test"));
+	}
+
+	// 多个上下文,结合@ContextBean测试
+	@Test
+	public void testSearchContext5() throws Exception {
+		UserInfoContext userInfoContext = new UserInfoContext();
+		userInfoContext.setInfo("test info");
+
+		LiteflowResponse response = flowExecutor.execute2Resp("chain5", "arg", userInfoContext, new DefaultContext());
+		Assertions.assertTrue(response.isSuccess());
+		DefaultContext context = response.getContextBean(DefaultContext.class);
+		Assertions.assertEquals("test info", context.getData("test"));
+	}
+
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A1Cmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.searchContext.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("a1")
+public class A1Cmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		String name = this.getContextValue("name");
+
+		this.setContextValue("setName", "hello," + name);
+
+	}
+}

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A2Cmp.java

@@ -0,0 +1,23 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.searchContext.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("a2")
+public class A2Cmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		String name = this.getContextValue("name");
+
+		this.setContextValue("memberContext.setName", "hello," + name);
+
+	}
+}

+ 22 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A3Cmp.java

@@ -0,0 +1,22 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.searchContext.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("a3")
+public class A3Cmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		String name = this.getContextValue("member.memberCode");
+		this.setContextValue("setData", "test", name);
+
+	}
+}

+ 22 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A4Cmp.java

@@ -0,0 +1,22 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.searchContext.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("a4")
+public class A4Cmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		Integer id = this.getContextValue("orderContext.id");
+		this.setContextValue("setData", "test", id);
+
+	}
+}

+ 22 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/cmp/A5Cmp.java

@@ -0,0 +1,22 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.searchContext.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("a5")
+public class A5Cmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		String str = this.getContextValue("userCx.info");
+		this.setContextValue("setData", "test", str);
+
+	}
+}

+ 28 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/context/Member.java

@@ -0,0 +1,28 @@
+package com.yomahub.liteflow.test.searchContext.context;
+
+public class Member {
+    private String memberCode;
+
+    private String memberName;
+
+    public Member(String memberCode, String memberName) {
+        this.memberCode = memberCode;
+        this.memberName = memberName;
+    }
+
+    public String getMemberCode() {
+        return memberCode;
+    }
+
+    public void setMemberCode(String memberCode) {
+        this.memberCode = memberCode;
+    }
+
+    public String getMemberName() {
+        return memberName;
+    }
+
+    public void setMemberName(String memberName) {
+        this.memberName = memberName;
+    }
+}

+ 24 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/context/MemberContext.java

@@ -0,0 +1,24 @@
+package com.yomahub.liteflow.test.searchContext.context;
+
+public class MemberContext {
+
+    private Integer id;
+
+    private String name;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

+ 34 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/context/OrderContext.java

@@ -0,0 +1,34 @@
+package com.yomahub.liteflow.test.searchContext.context;
+
+public class OrderContext {
+
+    private Integer id;
+
+    private String orderCode;
+
+    private Member member;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getOrderCode() {
+        return orderCode;
+    }
+
+    public void setOrderCode(String orderCode) {
+        this.orderCode = orderCode;
+    }
+
+    public Member getMember() {
+        return member;
+    }
+
+    public void setMember(Member member) {
+        this.member = member;
+    }
+}

+ 17 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/searchContext/context/UserInfoContext.java

@@ -0,0 +1,17 @@
+package com.yomahub.liteflow.test.searchContext.context;
+
+import com.yomahub.liteflow.context.ContextBean;
+
+@ContextBean("userCx")
+public class UserInfoContext {
+
+    private String info;
+
+    public String getInfo() {
+        return info;
+    }
+
+    public void setInfo(String info) {
+        this.info = info;
+    }
+}

+ 1 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/searchContext/application.properties

@@ -0,0 +1 @@
+liteflow.rule-source=searchContext/flow.xml

+ 23 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/searchContext/flow.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE flow PUBLIC  "liteflow" "liteflow.dtd">
+<flow>
+    <chain name="chain1">
+        THEN(a1);
+    </chain>
+
+    <chain name="chain2">
+        THEN(a2);
+    </chain>
+
+    <chain name="chain3">
+        THEN(a3);
+    </chain>
+
+    <chain name="chain4">
+        THEN(a4);
+    </chain>
+
+    <chain name="chain5">
+        THEN(a5);
+    </chain>
+</flow>