Browse Source

feature #I6RF8Y EL表达式里支持并或非操作符

everywhere.z 2 years ago
parent
commit
d62611e90b
58 changed files with 775 additions and 204 deletions
  1. 7 16
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java
  2. 33 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AndOperator.java
  3. 4 7
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/BreakOperator.java
  4. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/DoOperator.java
  5. 3 5
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ElifOperator.java
  6. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IdOperator.java
  7. 5 5
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IfOperator.java
  8. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java
  9. 31 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NotOperator.java
  10. 33 0
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/OrOperator.java
  11. 1 1
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java
  12. 5 6
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhileOperator.java
  13. 1 2
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/BaseOperator.java
  14. 27 28
      liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java
  15. 6 0
      liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java
  16. 8 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBreakComponent.java
  17. 3 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java
  18. 8 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeForComponent.java
  19. 7 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIfComponent.java
  20. 8 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIteratorComponent.java
  21. 8 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeSwitchComponent.java
  22. 8 0
      liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeWhileComponent.java
  23. 15 3
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/ConditionTypeEnum.java
  24. 25 0
      liteflow-core/src/main/java/com/yomahub/liteflow/exception/AndOrConditionException.java
  25. 0 1
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java
  26. 3 2
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java
  27. 4 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Executable.java
  28. 4 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java
  29. 85 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/AndOrCondition.java
  30. 13 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/BooleanConditionTypeEnum.java
  31. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/CatchCondition.java
  32. 4 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ConditionKey.java
  33. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/FinallyCondition.java
  34. 7 10
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ForCondition.java
  35. 52 56
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/IfCondition.java
  36. 9 13
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/IteratorCondition.java
  37. 4 7
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/LoopCondition.java
  38. 48 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/NotCondition.java
  39. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/PreCondition.java
  40. 4 5
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/SwitchCondition.java
  41. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ThenCondition.java
  42. 1 0
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java
  43. 17 29
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhileCondition.java
  44. 4 4
      liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/ParallelSupplier.java
  45. 20 0
      liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java
  46. 70 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/BooleanOptELSpringbootTest.java
  47. 21 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/ACmp.java
  48. 21 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/BCmp.java
  49. 13 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/BK.java
  50. 20 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/W1.java
  51. 20 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/W2.java
  52. 12 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/X1.java
  53. 12 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/X2.java
  54. 12 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/X3.java
  55. 12 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/X4.java
  56. 1 1
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java
  57. 1 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/booleanOpt/application.properties
  58. 28 0
      liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/booleanOpt/flow.xml

+ 7 - 16
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java

@@ -16,7 +16,7 @@ import com.yomahub.liteflow.exception.FlowSystemException;
 import com.yomahub.liteflow.flow.FlowBus;
 import com.yomahub.liteflow.flow.element.Chain;
 import com.yomahub.liteflow.flow.element.Node;
-import com.yomahub.liteflow.flow.element.condition.Condition;
+import com.yomahub.liteflow.flow.element.Condition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -37,9 +37,9 @@ public class LiteFlowChainELBuilder {
 	private Chain chain;
 
 	/**
-	 * //这是主体的Condition //声明这个变量,而不是用chain.getConditionList的目的,是为了辅助平滑加载
-	 * //虽然FlowBus里面的map都是CopyOnWrite类型的,但是在buildCondition的时候,为了平滑加载,所以不能事先把chain.getConditionList给设为空List
-	 * //所以在这里做一个缓存,等conditionList全部build完毕后,再去一次性替换chain里面的conditionList
+	 * 这是主体的Condition //声明这个变量,而不是用chain.getConditionList的目的,是为了辅助平滑加载
+	 * 虽然FlowBus里面的map都是CopyOnWrite类型的,但是在buildCondition的时候,为了平滑加载,所以不能事先把chain.getConditionList给设为空List
+	 * 所以在这里做一个缓存,等conditionList全部build完毕后,再去一次性替换chain里面的conditionList
 	 */
 	private final List<Condition> conditionList;
 
@@ -62,6 +62,9 @@ public class LiteFlowChainELBuilder {
 		EXPRESS_RUNNER.addFunction(ChainConstant.WHILE, new WhileOperator());
 		EXPRESS_RUNNER.addFunction(ChainConstant.ITERATOR, new IteratorOperator());
 		EXPRESS_RUNNER.addFunction(ChainConstant.CATCH, new CatchOperator());
+		EXPRESS_RUNNER.addFunction(ChainConstant.AND, new AndOperator());
+		EXPRESS_RUNNER.addFunction(ChainConstant.OR, new OrOperator());
+		EXPRESS_RUNNER.addFunction(ChainConstant.NOT, new NotOperator());
 		EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ELSE, Object.class, new ElseOperator());
 		EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.ELIF, Object.class, new ElifOperator());
 		EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.TO, Object.class, new ToOperator());
@@ -139,18 +142,6 @@ public class LiteFlowChainELBuilder {
 			// 这里无论多复杂的,外面必定有一个最外层的Condition,所以这里只有一个,内部可以嵌套很多层,这点和以前的不太一样
 			Condition condition = (Condition) EXPRESS_RUNNER.execute(elStr, context, errorList, true, true);
 
-			// 从condition的第一层嵌套结构里拿出Pre和Finally节点
-			// 为什么只寻找第一层,而不往下寻找了呢?
-			// 因为这是一个规范,如果在后面的层级中出现pre和finally,语义上也不好理解,所以pre和finally只能定义在第一层
-			// 如果硬是要在后面定义,则执行的时候会忽略,相关代码已做了判断
-			/*
-			 * for (Executable executable : condition.getExecutableList()) { if
-			 * (executable instanceof PreCondition) {
-			 * this.preConditionList.add((PreCondition) executable); } else if (executable
-			 * instanceof FinallyCondition) {
-			 * this.finallyConditionList.add((FinallyCondition) executable); } }
-			 */
-
 			// 把主要的condition加入
 			this.conditionList.add(condition);
 			return this;

+ 33 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AndOperator.java

@@ -0,0 +1,33 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
+import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.AndOrCondition;
+import com.yomahub.liteflow.flow.element.condition.BooleanConditionTypeEnum;
+
+/**
+ * EL表达式中AND关键字的操作
+ * 主要用于适用于产生布尔类型结果的表达式中,比如IF(AND(a,b)),WHILE(AND(a,b))
+ *
+ * @author Bryan.Zhang
+ * @since 2.10.2
+ */
+public class AndOperator extends BaseOperator<AndOrCondition> {
+    @Override
+    public AndOrCondition build(Object[] objects) throws Exception {
+        OperatorHelper.checkObjectSizeGtTwo(objects);
+
+        AndOrCondition andOrCondition = new AndOrCondition();
+        andOrCondition.setBooleanConditionType(BooleanConditionTypeEnum.AND);
+
+        for (Object object : objects){
+            OperatorHelper.checkObjectMustBeBooleanItem(object);
+
+            Executable item = OperatorHelper.convert(object, Executable.class);
+            andOrCondition.addItem(item);
+        }
+
+        return andOrCondition;
+    }
+}

+ 4 - 7
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/BreakOperator.java

@@ -5,6 +5,7 @@ import com.ql.util.express.exception.QLException;
 import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
 import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
 import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.flow.element.Node;
 import com.yomahub.liteflow.flow.element.condition.LoopCondition;
 
@@ -25,13 +26,9 @@ public class BreakOperator extends BaseOperator<LoopCondition> {
 		LoopCondition condition = OperatorHelper.convert(objects[0], LoopCondition.class, errorMsg);
 
 		// 获得需要执行的可执行表达式
-		Node breakNode = OperatorHelper.convert(objects[1], Node.class);
-		if (ListUtil.toList(NodeTypeEnum.BREAK, NodeTypeEnum.BREAK_SCRIPT).contains(breakNode.getType())) {
-			condition.setBreakNode(breakNode);
-		}
-		else {
-			throw new QLException("The parameter must be node-break item");
-		}
+		Executable breakItem = OperatorHelper.convert(objects[1], Node.class);
+		OperatorHelper.checkObjectMustBeBooleanItem(breakItem);
+		condition.setBreakItem(breakItem);
 		return condition;
 	}
 

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/DoOperator.java

@@ -5,7 +5,7 @@ import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
 import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
 import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.flow.element.condition.CatchCondition;
-import com.yomahub.liteflow.flow.element.condition.Condition;
+import com.yomahub.liteflow.flow.element.Condition;
 import com.yomahub.liteflow.flow.element.condition.LoopCondition;
 
 /**

+ 3 - 5
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ElifOperator.java

@@ -25,17 +25,15 @@ public class ElifOperator extends BaseOperator<IfCondition> {
 		IfCondition ifCondition = OperatorHelper.convert(objects[0], IfCondition.class);
 
 		// 解析第一个参数
-		Node ifNode = OperatorHelper.convert(objects[1], Node.class);
-		if (!ListUtil.toList(NodeTypeEnum.IF, NodeTypeEnum.IF_SCRIPT).contains(ifNode.getType())) {
-			throw new QLException("The first parameter must be If item");
-		}
+		Executable ifItem = OperatorHelper.convert(objects[1], Node.class);
+		OperatorHelper.checkObjectMustBeBooleanItem(ifItem);
 
 		// 解析第二个参数
 		Executable trueCaseExecutableItem = OperatorHelper.convert(objects[2], Executable.class);
 
 		// 构建一个内部的IfCondition
 		IfCondition ifConditionItem = new IfCondition();
-		ifConditionItem.setIfNode(ifNode);
+		ifConditionItem.setIfItem(ifItem);
 		ifConditionItem.setTrueCaseExecutableItem(trueCaseExecutableItem);
 
 		// 因为可能会有多个ELIF,所以每一次拿到的caller总是最开始大的if,需要遍历到没有falseCaseExecutable的地方。

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IdOperator.java

@@ -2,7 +2,7 @@ package com.yomahub.liteflow.builder.el.operator;
 
 import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
 import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
-import com.yomahub.liteflow.flow.element.condition.Condition;
+import com.yomahub.liteflow.flow.element.Condition;
 
 /**
  * EL规则中的id的操作符,只有condition可加id

+ 5 - 5
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/IfOperator.java

@@ -7,7 +7,9 @@ import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
 import com.yomahub.liteflow.enums.NodeTypeEnum;
 import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.flow.element.condition.AndOrCondition;
 import com.yomahub.liteflow.flow.element.condition.IfCondition;
+import com.yomahub.liteflow.flow.element.condition.NotCondition;
 
 /**
  * EL规则中的IF的操作符
@@ -22,10 +24,8 @@ public class IfOperator extends BaseOperator<IfCondition> {
 		OperatorHelper.checkObjectSizeEq(objects, 2, 3);
 
 		// 解析第一个参数
-		Node ifNode = OperatorHelper.convert(objects[0], Node.class);
-		if (!ListUtil.toList(NodeTypeEnum.IF, NodeTypeEnum.IF_SCRIPT).contains(ifNode.getType())) {
-			throw new QLException("The first parameter must be If item");
-		}
+		Executable ifItem = OperatorHelper.convert(objects[0], Executable.class);
+		OperatorHelper.checkObjectMustBeBooleanItem(ifItem);
 
 		// 解析第二个参数
 		Executable trueCaseExecutableItem = OperatorHelper.convert(objects[1], Executable.class);
@@ -37,7 +37,7 @@ public class IfOperator extends BaseOperator<IfCondition> {
 		}
 
 		IfCondition ifCondition = new IfCondition();
-		ifCondition.setIfNode(ifNode);
+		ifCondition.setIfItem(ifItem);
 		ifCondition.setTrueCaseExecutableItem(trueCaseExecutableItem);
 		ifCondition.setFalseCaseExecutableItem(falseCaseExecutableItem);
 		return ifCondition;

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NodeOperator.java

@@ -20,7 +20,7 @@ public class NodeOperator extends BaseOperator<Node> {
 
 	@Override
 	public Node build(Object[] objects) throws Exception {
-		OperatorHelper.checkObjectSizeNeqOne(objects);
+		OperatorHelper.checkObjectSizeEqOne(objects);
 
 		String nodeId = OperatorHelper.convert(objects[0], String.class);
 

+ 31 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/NotOperator.java

@@ -0,0 +1,31 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
+import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.AndOrCondition;
+import com.yomahub.liteflow.flow.element.condition.BooleanConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.condition.NotCondition;
+
+/**
+ * EL表达式中NOT关键字的操作,表示非的操作
+ * 主要用于适用于产生布尔类型结果的表达式中,比如IF(NOT(a)),WHILE(NOT(a))
+ *
+ * @author Bryan.Zhang
+ * @since 2.10.2
+ */
+public class NotOperator extends BaseOperator<NotCondition> {
+    @Override
+    public NotCondition build(Object[] objects) throws Exception {
+        OperatorHelper.checkObjectSizeEqOne(objects);
+
+        Object object = objects[0];
+        OperatorHelper.checkObjectMustBeBooleanItem(object);
+        Executable item = OperatorHelper.convert(object, Executable.class);
+
+        NotCondition notCondition = new NotCondition();
+        notCondition.setItem(item);
+
+        return notCondition;
+    }
+}

+ 33 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/OrOperator.java

@@ -0,0 +1,33 @@
+package com.yomahub.liteflow.builder.el.operator;
+
+import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
+import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.AndOrCondition;
+import com.yomahub.liteflow.flow.element.condition.BooleanConditionTypeEnum;
+
+/**
+ * EL表达式中OR关键字的操作
+ * 主要用于适用于产生布尔类型结果的表达式中,比如IF(OR(a,b)),WHILE(OR(a,b))
+ *
+ * @author Bryan.Zhang
+ * @since 2.10.2
+ */
+public class OrOperator extends BaseOperator<AndOrCondition> {
+    @Override
+    public AndOrCondition build(Object[] objects) throws Exception {
+        OperatorHelper.checkObjectSizeGtTwo(objects);
+
+        AndOrCondition andOrCondition = new AndOrCondition();
+        andOrCondition.setBooleanConditionType(BooleanConditionTypeEnum.OR);
+
+        for (Object object : objects){
+            OperatorHelper.checkObjectMustBeBooleanItem(object);
+
+            Executable item = OperatorHelper.convert(object, Executable.class);
+            andOrCondition.addItem(item);
+        }
+
+        return andOrCondition;
+    }
+}

+ 1 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/SwitchOperator.java

@@ -18,7 +18,7 @@ public class SwitchOperator extends BaseOperator<SwitchCondition> {
 
 	@Override
 	public SwitchCondition build(Object[] objects) throws Exception {
-		OperatorHelper.checkObjectSizeNeqOne(objects);
+		OperatorHelper.checkObjectSizeEqOne(objects);
 
 		Node switchNode = OperatorHelper.convert(objects[0], Node.class);
 		if (!ListUtil.toList(NodeTypeEnum.SWITCH, NodeTypeEnum.SWITCH_SCRIPT).contains(switchNode.getType())) {

+ 5 - 6
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/WhileOperator.java

@@ -5,6 +5,7 @@ import com.ql.util.express.exception.QLException;
 import com.yomahub.liteflow.builder.el.operator.base.BaseOperator;
 import com.yomahub.liteflow.builder.el.operator.base.OperatorHelper;
 import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.flow.element.Node;
 import com.yomahub.liteflow.flow.element.condition.WhileCondition;
 
@@ -18,15 +19,13 @@ public class WhileOperator extends BaseOperator<WhileCondition> {
 
 	@Override
 	public WhileCondition build(Object[] objects) throws Exception {
-		OperatorHelper.checkObjectSizeEq(objects, 1);
+		OperatorHelper.checkObjectSizeEqOne(objects);
 
-		Node node = OperatorHelper.convert(objects[0], Node.class);
-		if (!ListUtil.toList(NodeTypeEnum.WHILE, NodeTypeEnum.WHILE_SCRIPT).contains(node.getType())) {
-			throw new QLException("The parameter must be while-node item");
-		}
+		Executable whileItem = OperatorHelper.convert(objects[0], Executable.class);
+		OperatorHelper.checkObjectMustBeBooleanItem(whileItem);
 
 		WhileCondition whileCondition = new WhileCondition();
-		whileCondition.setWhileNode(node);
+		whileCondition.setWhileItem(whileItem);
 		return whileCondition;
 	}
 

+ 1 - 2
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/BaseOperator.java

@@ -16,8 +16,7 @@ public abstract class BaseOperator<T extends Executable> extends Operator {
 	@Override
 	public T executeInner(Object[] objects) throws Exception {
 		try {
-			// 检查 node 和 chain 是否已经注册
-			OperatorHelper.checkNodeAndChainExist(objects);
+			OperatorHelper.checkItemNotNull(objects);
 			return build(objects);
 		}
 		catch (QLException e) {

+ 27 - 28
liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java

@@ -1,9 +1,13 @@
 package com.yomahub.liteflow.builder.el.operator.base;
 
+import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.util.StrUtil;
 import com.ql.util.express.exception.QLException;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
 import com.yomahub.liteflow.exception.DataNotFoundException;
 import com.yomahub.liteflow.flow.element.Node;
+import com.yomahub.liteflow.flow.element.condition.AndOrCondition;
+import com.yomahub.liteflow.flow.element.condition.NotCondition;
 
 import java.util.Objects;
 
@@ -15,28 +19,6 @@ import java.util.Objects;
  */
 public class OperatorHelper {
 
-	/**
-	 * 检查参数数量,不等于1
-	 * @param objects objects
-	 * @throws QLException QLException
-	 */
-	public static void checkObjectSizeNeqOne(Object[] objects) throws QLException {
-		checkObjectSizeNeq(objects, 1);
-	}
-
-	/**
-	 * 检查参数数量,不等于 size
-	 * @param objects objects
-	 * @param size 参数数量
-	 * @throws QLException QLException
-	 */
-	public static void checkObjectSizeNeq(Object[] objects, int size) throws QLException {
-		checkObjectSizeGtZero(objects);
-		if (objects.length != size) {
-			throw new QLException("parameter error");
-		}
-	}
-
 	/**
 	 * 检查参数数量,大于 0
 	 * @param objects objects
@@ -60,6 +42,15 @@ public class OperatorHelper {
 		}
 	}
 
+	/**
+	 * 检查参数数量,等于 1
+	 * @param objects objects
+	 * @throws QLException QLException
+	 */
+	public static void checkObjectSizeEqOne(Object[] objects) throws QLException {
+		checkObjectSizeEq(objects, 1);
+	}
+
 	/**
 	 * 检查参数数量,等于 2
 	 * @param objects objects
@@ -138,12 +129,7 @@ public class OperatorHelper {
 		throw new QLException(errorMsg);
 	}
 
-	/**
-	 * 检查 node 和 chain 是否已经注册
-	 * @param objects objects
-	 * @throws QLException QLException
-	 */
-	public static void checkNodeAndChainExist(Object[] objects) throws QLException {
+	public static void checkItemNotNull(Object[] objects) throws QLException {
 		for (Object object : objects) {
 			if (Objects.isNull(object)) {
 				throw new QLException(DataNotFoundException.MSG);
@@ -151,4 +137,17 @@ public class OperatorHelper {
 		}
 	}
 
+	/**
+	 * 所谓Boolean item,指的是那些最终的结果值为布尔类型的Item
+	 * 布尔类型的items有,if,while,break类型的Node,以及AndOrCondition以及NotCondition
+	 */
+	public static void checkObjectMustBeBooleanItem(Object object) throws Exception{
+		if (!(object instanceof Node && ListUtil.toList(
+				NodeTypeEnum.IF, NodeTypeEnum.IF_SCRIPT,
+				NodeTypeEnum.WHILE, NodeTypeEnum.WHILE_SCRIPT,
+				NodeTypeEnum.BREAK, NodeTypeEnum.BREAK_SCRIPT).contains(((Node) object).getType())
+				|| object instanceof AndOrCondition || object instanceof NotCondition)) {
+			throw new QLException("The first parameter must be boolean type Node or boolean type condition");
+		}
+	}
 }

+ 6 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java

@@ -75,4 +75,10 @@ public interface ChainConstant {
 
 	String CATCH = "CATCH";
 
+	String AND = "AND";
+
+	String OR = "OR";
+
+	String NOT = "NOT";
+
 }

+ 8 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBreakComponent.java

@@ -1,5 +1,6 @@
 package com.yomahub.liteflow.core;
 
+import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;
 import com.yomahub.liteflow.util.LiteFlowProxyUtil;
 
@@ -21,4 +22,11 @@ public abstract class NodeBreakComponent extends NodeComponent {
 
 	public abstract boolean processBreak() throws Exception;
 
+	@Override
+	@SuppressWarnings("unchecked")
+	public Boolean getItemResultMetaValue(Integer slotIndex) {
+		Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+		return DataBus.getSlot(slotIndex).getBreakResult(originalClass.getName());
+	}
+
 }

+ 3 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java

@@ -377,4 +377,7 @@ public abstract class NodeComponent {
 		return FlowExecutorHolder.loadInstance().invoke2RespInAsync(chainId, param, this.getSlotIndex());
 	}
 
+	public <T> T getItemResultMetaValue(Integer slotIndex){
+		return null;
+	}
 }

+ 8 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeForComponent.java

@@ -1,5 +1,6 @@
 package com.yomahub.liteflow.core;
 
+import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;
 import com.yomahub.liteflow.util.LiteFlowProxyUtil;
 
@@ -21,4 +22,11 @@ public abstract class NodeForComponent extends NodeComponent {
 
 	public abstract int processFor() throws Exception;
 
+	@Override
+	@SuppressWarnings("unchecked")
+	public Integer getItemResultMetaValue(Integer slotIndex) {
+		Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+		return DataBus.getSlot(slotIndex).getForResult(originalClass.getName());
+	}
+
 }

+ 7 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIfComponent.java

@@ -1,5 +1,6 @@
 package com.yomahub.liteflow.core;
 
+import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.util.LiteFlowProxyUtil;
 
 /**
@@ -19,4 +20,10 @@ public abstract class NodeIfComponent extends NodeComponent {
 
 	public abstract boolean processIf() throws Exception;
 
+	@Override
+	@SuppressWarnings("unchecked")
+	public Boolean getItemResultMetaValue(Integer slotIndex) {
+		Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+		return DataBus.getSlot(slotIndex).getIfResult(originalClass.getName());
+	}
 }

+ 8 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIteratorComponent.java

@@ -1,5 +1,6 @@
 package com.yomahub.liteflow.core;
 
+import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;
 import com.yomahub.liteflow.util.LiteFlowProxyUtil;
 
@@ -23,4 +24,11 @@ public abstract class NodeIteratorComponent extends NodeComponent {
 
 	public abstract Iterator<?> processIterator() throws Exception;
 
+	@Override
+	@SuppressWarnings("unchecked")
+	public Iterator<?> getItemResultMetaValue(Integer slotIndex) {
+		Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+		return DataBus.getSlot(slotIndex).getIteratorResult(originalClass.getName());
+	}
+
 }

+ 8 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeSwitchComponent.java

@@ -7,6 +7,7 @@
  */
 package com.yomahub.liteflow.core;
 
+import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.util.LiteFlowProxyUtil;
 
 /**
@@ -26,4 +27,11 @@ public abstract class NodeSwitchComponent extends NodeComponent {
 	// 用以返回路由节点的beanId
 	public abstract String processSwitch() throws Exception;
 
+	@Override
+	@SuppressWarnings("unchecked")
+	public String getItemResultMetaValue(Integer slotIndex) {
+		Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+		return DataBus.getSlot(slotIndex).getSwitchResult(originalClass.getName());
+	}
+
 }

+ 8 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeWhileComponent.java

@@ -1,5 +1,6 @@
 package com.yomahub.liteflow.core;
 
+import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;
 import com.yomahub.liteflow.util.LiteFlowProxyUtil;
 
@@ -21,4 +22,11 @@ public abstract class NodeWhileComponent extends NodeComponent {
 
 	public abstract boolean processWhile() throws Exception;
 
+	@Override
+	@SuppressWarnings("unchecked")
+	public Boolean getItemResultMetaValue(Integer slotIndex) {
+		Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+		return DataBus.getSlot(slotIndex).getWhileResult(originalClass.getName());
+	}
+
 }

+ 15 - 3
liteflow-core/src/main/java/com/yomahub/liteflow/enums/ConditionTypeEnum.java

@@ -5,9 +5,17 @@ package com.yomahub.liteflow.enums;
  */
 public enum ConditionTypeEnum {
 
-	TYPE_THEN("then", "then"), TYPE_WHEN("when", "when"), TYPE_SWITCH("switch", "switch"),
+	TYPE_THEN("then", "then"),
 
-	TYPE_IF("if", "if"), TYPE_PRE("pre", "pre"), TYPE_FINALLY("finally", "finally"),
+	TYPE_WHEN("when", "when"),
+
+	TYPE_SWITCH("switch", "switch"),
+
+	TYPE_IF("if", "if"),
+
+	TYPE_PRE("pre", "pre"),
+
+	TYPE_FINALLY("finally", "finally"),
 
 	TYPE_FOR("for", "for"),
 
@@ -15,7 +23,11 @@ public enum ConditionTypeEnum {
 
 	TYPE_ITERATOR("iterator", "iterator"),
 
-	TYPE_CATCH("catch", "catch");
+	TYPE_CATCH("catch", "catch"),
+
+	TYPE_AND_OR_OPT("and_or_opt", "and_or_opt"),
+
+	TYPE_NOT_OPT("not_opt", "not_opt");
 
 	private String type;
 

+ 25 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/exception/AndOrConditionException.java

@@ -0,0 +1,25 @@
+package com.yomahub.liteflow.exception;
+
+public class AndOrConditionException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 异常信息
+	 */
+	private String message;
+
+	public AndOrConditionException(String message) {
+		this.message = message;
+	}
+
+	@Override
+	public String getMessage() {
+		return message;
+	}
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+}

+ 0 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java

@@ -14,7 +14,6 @@ import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;
 import com.yomahub.liteflow.enums.ExecuteTypeEnum;
 import com.yomahub.liteflow.exception.FlowSystemException;
-import com.yomahub.liteflow.flow.element.condition.Condition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.util.ArrayList;

+ 3 - 2
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/Condition.java → liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java

@@ -5,7 +5,7 @@
  * @email weenyc31@163.com
  * @Date 2020/4/1
  */
-package com.yomahub.liteflow.flow.element.condition;
+package com.yomahub.liteflow.flow.element;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
@@ -14,6 +14,7 @@ import com.yomahub.liteflow.enums.ExecuteTypeEnum;
 import com.yomahub.liteflow.exception.ChainEndException;
 import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.condition.ConditionKey;
 import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;
 
@@ -65,7 +66,7 @@ public abstract class Condition implements Executable {
 		}
 	}
 
-	protected abstract void executeCondition(Integer slotIndex) throws Exception;
+	public abstract void executeCondition(Integer slotIndex) throws Exception;
 
 	@Override
 	public ExecuteTypeEnum getExecuteType() {

+ 4 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Executable.java

@@ -40,4 +40,8 @@ public interface Executable {
 
 	}
 
+	default <T> T getItemResultMetaValue(Integer slotIndex){
+		return null;
+	}
+
 }

+ 4 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java

@@ -275,4 +275,8 @@ public class Node implements Executable, Cloneable {
 		this.language = language;
 	}
 
+	@Override
+	public <T> T getItemResultMetaValue(Integer slotIndex) {
+		return instance.getItemResultMetaValue(slotIndex);
+	}
 }

+ 85 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/AndOrCondition.java

@@ -0,0 +1,85 @@
+package com.yomahub.liteflow.flow.element.condition;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.BooleanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.exception.AndOrConditionException;
+import com.yomahub.liteflow.flow.element.Condition;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.slot.DataBus;
+import com.yomahub.liteflow.slot.Slot;
+import java.util.List;
+
+public class AndOrCondition extends Condition {
+
+    private BooleanConditionTypeEnum booleanConditionType;
+
+    @Override
+    public void executeCondition(Integer slotIndex) throws Exception {
+        List<Executable> itemList = this.getItem();
+
+
+        if (CollUtil.isEmpty(itemList)){
+            throw new AndOrConditionException("boolean item list is null");
+        }
+
+        boolean[] booleanArray = new boolean[itemList.size()];
+
+        for (int i = 0; i < itemList.size(); i++) {
+            Executable item = itemList.get(i);
+            item.setCurrChainId(this.getCurrChainId());
+            item.execute(slotIndex);
+            booleanArray[i] = item.getItemResultMetaValue(slotIndex);
+        }
+
+        BooleanConditionTypeEnum booleanConditionType = this.getBooleanConditionType();
+
+        Slot slot = DataBus.getSlot(slotIndex);
+
+        String resultKey = StrUtil.format("{}_{}",this.getClass().getName(),this.hashCode());
+        switch (booleanConditionType) {
+            case AND:
+                slot.setAndOrResult(resultKey, BooleanUtil.and(booleanArray));
+                break;
+            case OR:
+                slot.setAndOrResult(resultKey, BooleanUtil.or(booleanArray));
+                break;
+            default:
+                throw new AndOrConditionException("condition type must be 'AND' or 'OR'");
+        }
+    }
+
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Boolean getItemResultMetaValue(Integer slotIndex) {
+        Slot slot = DataBus.getSlot(slotIndex);
+        String resultKey = StrUtil.format("{}_{}",this.getClass().getName(),this.hashCode());
+        return slot.getAndOrResult(resultKey);
+    }
+
+    @Override
+    public ConditionTypeEnum getConditionType() {
+        return ConditionTypeEnum.TYPE_AND_OR_OPT;
+    }
+
+    public void addItem(Executable item){
+        this.addExecutable(ConditionKey.AND_OR_ITEM_KEY, item);
+    }
+
+    public List<Executable> getItem(){
+        return this.getExecutableList(ConditionKey.AND_OR_ITEM_KEY);
+    }
+
+    public BooleanConditionTypeEnum getBooleanConditionType() {
+        return booleanConditionType;
+    }
+
+    public void setBooleanConditionType(BooleanConditionTypeEnum booleanConditionType) {
+        this.booleanConditionType = booleanConditionType;
+    }
+}

+ 13 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/BooleanConditionTypeEnum.java

@@ -0,0 +1,13 @@
+package com.yomahub.liteflow.flow.element.condition;
+
+/**
+ * 结果为Boolean类型的类型
+ * @author Bryan.Zhang
+ * @since 2.10.2
+ */
+public enum BooleanConditionTypeEnum {
+
+    AND,
+    OR,
+    NOT
+}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/CatchCondition.java

@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
 import com.yomahub.liteflow.exception.CatchErrorException;
+import com.yomahub.liteflow.flow.element.Condition;
 import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;

+ 4 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ConditionKey.java

@@ -32,4 +32,8 @@ public interface ConditionKey {
 
 	String CATCH_KEY = "CATCH_KEY";
 
+	String AND_OR_ITEM_KEY = "AND_OR_ITEM";
+
+	String NOT_ITEM_KEY = "NOT_ITEM_KEY";
+
 }

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/FinallyCondition.java

@@ -8,6 +8,7 @@
 package com.yomahub.liteflow.flow.element.condition;
 
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.Condition;
 import com.yomahub.liteflow.flow.element.Executable;
 
 /**

+ 7 - 10
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ForCondition.java

@@ -36,16 +36,14 @@ public class ForCondition extends LoopCondition {
 		forNode.setCurrChainId(this.getCurrChainId());
 		forNode.execute(slotIndex);
 
-		// 这里可能会有spring代理过的bean,所以拿到user原始的class
-		Class<?> originalForCountClass = LiteFlowProxyUtil.getUserClass(forNode.getInstance().getClass());
 		// 获得循环次数
-		int forCount = slot.getForResult(originalForCountClass.getName());
+		int forCount = forNode.getItemResultMetaValue(slotIndex);
 
 		// 获得要循环的可执行对象
 		Executable executableItem = this.getDoExecutor();
 
 		// 获取Break节点
-		Node breakNode = this.getBreakNode();
+		Executable breakItem = this.getBreakItem();
 
 		// 循环执行
 		for (int i = 0; i < forCount; i++) {
@@ -54,12 +52,11 @@ public class ForCondition extends LoopCondition {
 			setLoopIndex(executableItem, i);
 			executableItem.execute(slotIndex);
 			// 如果break组件不为空,则去执行
-			if (ObjectUtil.isNotNull(breakNode)) {
-				breakNode.setCurrChainId(this.getCurrChainId());
-				setLoopIndex(breakNode, i);
-				breakNode.execute(slotIndex);
-				Class<?> originalBreakClass = LiteFlowProxyUtil.getUserClass(breakNode.getInstance().getClass());
-				boolean isBreak = slot.getBreakResult(originalBreakClass.getName());
+			if (ObjectUtil.isNotNull(breakItem)) {
+				breakItem.setCurrChainId(this.getCurrChainId());
+				setLoopIndex(breakItem, i);
+				breakItem.execute(slotIndex);
+				boolean isBreak = breakItem.getItemResultMetaValue(slotIndex);
 				if (isBreak) {
 					break;
 				}

+ 52 - 56
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/IfCondition.java

@@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
 import com.yomahub.liteflow.enums.NodeTypeEnum;
 import com.yomahub.liteflow.exception.*;
+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.slot.DataBus;
@@ -22,67 +23,63 @@ public class IfCondition extends Condition {
 
 	@Override
 	public void executeCondition(Integer slotIndex) throws Exception {
-		if (ListUtil.toList(NodeTypeEnum.IF, NodeTypeEnum.IF_SCRIPT).contains(getIfNode().getType())) {
-			// 先去判断isAccess方法,如果isAccess方法都返回false,整个IF表达式不执行
-			if (!this.getIfNode().isAccess(slotIndex)) {
-				return;
+		Executable ifItem = this.getIfItem();
+
+		// 先去判断isAccess方法,如果isAccess方法都返回false,整个IF表达式不执行
+		if (!ifItem.isAccess(slotIndex)) {
+			return;
+		}
+
+		// 先执行IF节点
+		ifItem.setCurrChainId(this.getCurrChainId());
+		ifItem.execute(slotIndex);
+
+		// 拿到If执行过的结果
+		boolean ifResult = ifItem.getItemResultMetaValue(slotIndex);
+
+		Executable trueCaseExecutableItem = this.getTrueCaseExecutableItem();
+		Executable falseCaseExecutableItem = this.getFalseCaseExecutableItem();
+
+		Slot slot = DataBus.getSlot(slotIndex);
+
+		if (ifResult) {
+			// trueCaseExecutableItem这个不能为空,否则执行什么呢
+			if (ObjectUtil.isNull(trueCaseExecutableItem)) {
+				String errorInfo = StrUtil.format("[{}]:no if-true node found for the component[{}]",
+						slot.getRequestId(), ifItem.getExecuteId());
+				throw new NoIfTrueNodeException(errorInfo);
 			}
 
-			// 先执行IF节点
-			this.getIfNode().setCurrChainId(this.getCurrChainId());
-			this.getIfNode().execute(slotIndex);
-
-			Slot slot = DataBus.getSlot(slotIndex);
-			// 这里可能会有spring代理过的bean,所以拿到user原始的class
-			Class<?> originalClass = LiteFlowProxyUtil.getUserClass(this.getIfNode().getInstance().getClass());
-			// 拿到If执行过的结果
-			boolean ifResult = slot.getIfResult(originalClass.getName());
-
-			Executable trueCaseExecutableItem = this.getTrueCaseExecutableItem();
-			Executable falseCaseExecutableItem = this.getFalseCaseExecutableItem();
-
-			if (ifResult) {
-				// trueCaseExecutableItem这个不能为空,否则执行什么呢
-				if (ObjectUtil.isNull(trueCaseExecutableItem)) {
-					String errorInfo = StrUtil.format("[{}]:no if-true node found for the component[{}]",
-							slot.getRequestId(), this.getIfNode().getInstance().getDisplayName());
-					throw new NoIfTrueNodeException(errorInfo);
-				}
+			// trueCaseExecutableItem 不能为前置或者后置组件
+			if (trueCaseExecutableItem instanceof PreCondition
+					|| trueCaseExecutableItem instanceof FinallyCondition) {
+				String errorInfo = StrUtil.format(
+						"[{}]:if component[{}] error, if true node cannot be pre or finally", slot.getRequestId(),
+						ifItem.getExecuteId());
+				throw new IfTargetCannotBePreOrFinallyException(errorInfo);
+			}
 
-				// trueCaseExecutableItem 不能为前置或者后置组件
-				if (trueCaseExecutableItem instanceof PreCondition
-						|| trueCaseExecutableItem instanceof FinallyCondition) {
+			// 执行trueCaseExecutableItem
+			trueCaseExecutableItem.setCurrChainId(this.getCurrChainId());
+			trueCaseExecutableItem.execute(slotIndex);
+		}
+		else {
+			// falseCaseExecutableItem可以为null,但是不为null时就执行否的情况
+			if (ObjectUtil.isNotNull(falseCaseExecutableItem)) {
+				// falseCaseExecutableItem 不能为前置或者后置组件
+				if (falseCaseExecutableItem instanceof PreCondition
+						|| falseCaseExecutableItem instanceof FinallyCondition) {
 					String errorInfo = StrUtil.format(
-							"[{}]:if component[{}] error, if true node cannot be pre or finally", slot.getRequestId(),
-							this.getIfNode().getInstance().getDisplayName());
+							"[{}]:if component[{}] error, if true node cannot be pre or finally",
+							slot.getRequestId(), ifItem.getExecuteId());
 					throw new IfTargetCannotBePreOrFinallyException(errorInfo);
 				}
 
-				// 执行trueCaseExecutableItem
-				trueCaseExecutableItem.setCurrChainId(this.getCurrChainId());
-				trueCaseExecutableItem.execute(slotIndex);
-			}
-			else {
-				// falseCaseExecutableItem可以为null,但是不为null时就执行否的情况
-				if (ObjectUtil.isNotNull(falseCaseExecutableItem)) {
-					// falseCaseExecutableItem 不能为前置或者后置组件
-					if (falseCaseExecutableItem instanceof PreCondition
-							|| falseCaseExecutableItem instanceof FinallyCondition) {
-						String errorInfo = StrUtil.format(
-								"[{}]:if component[{}] error, if true node cannot be pre or finally",
-								slot.getRequestId(), this.getIfNode().getInstance().getDisplayName());
-						throw new IfTargetCannotBePreOrFinallyException(errorInfo);
-					}
-
-					// 执行falseCaseExecutableItem
-					falseCaseExecutableItem.setCurrChainId(this.getCurrChainId());
-					falseCaseExecutableItem.execute(slotIndex);
-				}
+				// 执行falseCaseExecutableItem
+				falseCaseExecutableItem.setCurrChainId(this.getCurrChainId());
+				falseCaseExecutableItem.execute(slotIndex);
 			}
 		}
-		else {
-			throw new IfTypeErrorException("if instance must be NodeIfComponent");
-		}
 	}
 
 	@Override
@@ -106,12 +103,11 @@ public class IfCondition extends Condition {
 		this.addExecutable(ConditionKey.IF_FALSE_CASE_KEY, falseCaseExecutableItem);
 	}
 
-	public void setIfNode(Node ifNode) {
+	public void setIfItem(Executable ifNode) {
 		this.addExecutable(ConditionKey.IF_KEY, ifNode);
 	}
 
-	public Node getIfNode() {
-		return (Node) this.getExecutableOne(ConditionKey.IF_KEY);
+	public Executable getIfItem() {
+		return this.getExecutableOne(ConditionKey.IF_KEY);
 	}
-
 }

+ 9 - 13
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/IteratorCondition.java

@@ -25,7 +25,7 @@ public class IteratorCondition extends LoopCondition {
 		}
 
 		// 先去判断isAccess方法,如果isAccess方法都返回false,整个ITERATOR表达式不执行
-		if (!this.getIteratorNode().isAccess(slotIndex)) {
+		if (!iteratorNode.isAccess(slotIndex)) {
 			return;
 		}
 
@@ -33,16 +33,13 @@ public class IteratorCondition extends LoopCondition {
 		iteratorNode.setCurrChainId(this.getCurrChainId());
 		iteratorNode.execute(slotIndex);
 
-		// 这里可能会有spring代理过的bean,所以拿到user原始的class
-		Class<?> originalForCountClass = LiteFlowProxyUtil.getUserClass(iteratorNode.getInstance().getClass());
-		// 获得迭代器
-		Iterator<?> it = slot.getIteratorResult(originalForCountClass.getName());
+		Iterator<?> it = iteratorNode.getItemResultMetaValue(slotIndex);
 
 		// 获得要循环的可执行对象
 		Executable executableItem = this.getDoExecutor();
 
 		// 获取Break节点
-		Node breakNode = this.getBreakNode();
+		Executable breakItem = this.getBreakItem();
 
 		int index = 0;
 		while (it.hasNext()) {
@@ -56,13 +53,12 @@ public class IteratorCondition extends LoopCondition {
 			// 执行可执行对象
 			executableItem.execute(slotIndex);
 			// 如果break组件不为空,则去执行
-			if (ObjectUtil.isNotNull(breakNode)) {
-				breakNode.setCurrChainId(this.getCurrChainId());
-				setLoopIndex(breakNode, index);
-				setCurrLoopObject(breakNode, itObj);
-				breakNode.execute(slotIndex);
-				Class<?> originalBreakClass = LiteFlowProxyUtil.getUserClass(breakNode.getInstance().getClass());
-				boolean isBreak = slot.getBreakResult(originalBreakClass.getName());
+			if (ObjectUtil.isNotNull(breakItem)) {
+				breakItem.setCurrChainId(this.getCurrChainId());
+				setLoopIndex(breakItem, index);
+				setCurrLoopObject(breakItem, itObj);
+				breakItem.execute(slotIndex);
+				boolean isBreak = breakItem.getItemResultMetaValue(slotIndex);
 				if (isBreak) {
 					break;
 				}

+ 4 - 7
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/LoopCondition.java

@@ -1,13 +1,10 @@
 package com.yomahub.liteflow.flow.element.condition;
 
 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 java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
 /**
  * 循环Condition的抽象类 主要继承对象有ForCondition和WhileCondition
  *
@@ -16,11 +13,11 @@ import java.util.function.Consumer;
  */
 public abstract class LoopCondition extends Condition {
 
-	protected Node getBreakNode() {
-		return (Node) this.getExecutableOne(ConditionKey.BREAK_KEY);
+	protected Executable getBreakItem() {
+		return this.getExecutableOne(ConditionKey.BREAK_KEY);
 	}
 
-	public void setBreakNode(Node breakNode) {
+	public void setBreakItem(Executable breakNode) {
 		this.addExecutable(ConditionKey.BREAK_KEY, breakNode);
 	}
 

+ 48 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/NotCondition.java

@@ -0,0 +1,48 @@
+package com.yomahub.liteflow.flow.element.condition;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.Condition;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.slot.DataBus;
+import com.yomahub.liteflow.slot.Slot;
+
+public class NotCondition extends Condition {
+
+    @Override
+    public void executeCondition(Integer slotIndex) throws Exception {
+        Executable item = this.getItem();
+
+        item.setCurrChainId(this.getCurrChainId());
+        item.execute(slotIndex);
+        boolean flag = item.getItemResultMetaValue(slotIndex);
+
+        Slot slot = DataBus.getSlot(slotIndex);
+
+        String resultKey = StrUtil.format("{}_{}",this.getClass().getName(),this.hashCode());
+        slot.setAndOrResult(resultKey, !flag);
+    }
+
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Boolean getItemResultMetaValue(Integer slotIndex) {
+        Slot slot = DataBus.getSlot(slotIndex);
+        String resultKey = StrUtil.format("{}_{}",this.getClass().getName(),this.hashCode());
+        return slot.getAndOrResult(resultKey);
+    }
+
+    @Override
+    public ConditionTypeEnum getConditionType() {
+        return ConditionTypeEnum.TYPE_NOT_OPT;
+    }
+
+    public void setItem(Executable item){
+        this.addExecutable(ConditionKey.NOT_ITEM_KEY, item);
+    }
+
+    public Executable getItem(){
+        return this.getExecutableOne(ConditionKey.NOT_ITEM_KEY);
+    }
+
+}

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/PreCondition.java

@@ -8,6 +8,7 @@
 package com.yomahub.liteflow.flow.element.condition;
 
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
+import com.yomahub.liteflow.flow.element.Condition;
 import com.yomahub.liteflow.flow.element.Executable;
 
 /**

+ 4 - 5
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/SwitchCondition.java

@@ -8,13 +8,13 @@ import com.yomahub.liteflow.enums.NodeTypeEnum;
 import com.yomahub.liteflow.exception.NoSwitchTargetNodeException;
 import com.yomahub.liteflow.exception.SwitchTargetCannotBePreOrFinallyException;
 import com.yomahub.liteflow.exception.SwitchTypeErrorException;
+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.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;
 import com.yomahub.liteflow.util.LiteFlowProxyUtil;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -46,11 +46,10 @@ public class SwitchCondition extends Condition {
 			switchNode.setCurrChainId(this.getCurrChainId());
 			switchNode.execute(slotIndex);
 
-			// 根据switch节点执行出来的结果选择
+			// 拿到switch节点的结果
+			String targetId = switchNode.getItemResultMetaValue(slotIndex);
+
 			Slot slot = DataBus.getSlot(slotIndex);
-			// 这里可能会有spring代理过的bean,所以拿到user原始的class
-			Class<?> originalClass = LiteFlowProxyUtil.getUserClass(switchNode.getInstance().getClass());
-			String targetId = slot.getSwitchResult(originalClass.getName());
 
 			Executable targetExecutor = null;
 			if (StrUtil.isNotBlank(targetId)) {

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/ThenCondition.java

@@ -9,6 +9,7 @@ package com.yomahub.liteflow.flow.element.condition;
 
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
 import com.yomahub.liteflow.exception.ChainEndException;
+import com.yomahub.liteflow.flow.element.Condition;
 import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.slot.DataBus;
 import com.yomahub.liteflow.slot.Slot;

+ 1 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhenCondition.java

@@ -11,6 +11,7 @@ import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.common.LocalDefaultFlowConstant;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
 import com.yomahub.liteflow.exception.WhenExecuteException;
+import com.yomahub.liteflow.flow.element.Condition;
 import com.yomahub.liteflow.flow.parallel.CompletableFutureTimeout;
 import com.yomahub.liteflow.flow.parallel.ParallelSupplier;
 import com.yomahub.liteflow.flow.parallel.WhenFutureObj;

+ 17 - 29
liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/condition/WhileCondition.java

@@ -1,14 +1,9 @@
 package com.yomahub.liteflow.flow.element.condition;
 
 import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
 import com.yomahub.liteflow.enums.ConditionTypeEnum;
-import com.yomahub.liteflow.exception.NoWhileNodeException;
 import com.yomahub.liteflow.flow.element.Executable;
 import com.yomahub.liteflow.flow.element.Node;
-import com.yomahub.liteflow.slot.DataBus;
-import com.yomahub.liteflow.slot.Slot;
-import com.yomahub.liteflow.util.LiteFlowProxyUtil;
 
 /**
  * 循环条件Condition
@@ -20,15 +15,10 @@ public class WhileCondition extends LoopCondition {
 
 	@Override
 	public void executeCondition(Integer slotIndex) throws Exception {
-		Slot slot = DataBus.getSlot(slotIndex);
-		Node whileNode = this.getWhileNode();
-		if (ObjectUtil.isNull(whileNode)) {
-			String errorInfo = StrUtil.format("[{}]:no while-node found", slot.getRequestId());
-			throw new NoWhileNodeException(errorInfo);
-		}
+		Executable whileItem = this.getWhileItem();
 
 		// 先去判断isAccess方法,如果isAccess方法都返回false,整个WHILE表达式不执行
-		if (!this.getWhileNode().isAccess(slotIndex)) {
+		if (!whileItem.isAccess(slotIndex)) {
 			return;
 		}
 
@@ -36,7 +26,7 @@ public class WhileCondition extends LoopCondition {
 		Executable executableItem = this.getDoExecutor();
 
 		// 获取Break节点
-		Node breakNode = this.getBreakNode();
+		Executable breakItem = this.getBreakItem();
 
 		// 循环执行
 		int index = 0;
@@ -45,12 +35,11 @@ public class WhileCondition extends LoopCondition {
 			setLoopIndex(executableItem, index);
 			executableItem.execute(slotIndex);
 			// 如果break组件不为空,则去执行
-			if (ObjectUtil.isNotNull(breakNode)) {
-				breakNode.setCurrChainId(this.getCurrChainId());
-				setLoopIndex(breakNode, index);
-				breakNode.execute(slotIndex);
-				Class<?> originalBreakClass = LiteFlowProxyUtil.getUserClass(breakNode.getInstance().getClass());
-				boolean isBreak = slot.getBreakResult(originalBreakClass.getName());
+			if (ObjectUtil.isNotNull(breakItem)) {
+				breakItem.setCurrChainId(this.getCurrChainId());
+				setLoopIndex(breakItem, index);
+				breakItem.execute(slotIndex);
+				boolean isBreak = breakItem.getItemResultMetaValue(slotIndex);
 				if (isBreak) {
 					break;
 				}
@@ -60,13 +49,12 @@ public class WhileCondition extends LoopCondition {
 	}
 
 	private boolean getWhileResult(Integer slotIndex) throws Exception {
-		Slot slot = DataBus.getSlot(slotIndex);
-		Node whileNode = this.getWhileNode();
+		Executable whileItem = this.getWhileItem();
 		// 执行while组件
-		whileNode.setCurrChainId(this.getCurrChainId());
-		whileNode.execute(slotIndex);
-		Class<?> originalWhileClass = LiteFlowProxyUtil.getUserClass(whileNode.getInstance().getClass());
-		return slot.getWhileResult(originalWhileClass.getName());
+		whileItem.setCurrChainId(this.getCurrChainId());
+		whileItem.execute(slotIndex);
+
+		return whileItem.getItemResultMetaValue(slotIndex);
 	}
 
 	@Override
@@ -74,12 +62,12 @@ public class WhileCondition extends LoopCondition {
 		return ConditionTypeEnum.TYPE_WHILE;
 	}
 
-	public Node getWhileNode() {
-		return (Node) this.getExecutableOne(ConditionKey.WHILE_KEY);
+	public Executable getWhileItem() {
+		return this.getExecutableOne(ConditionKey.WHILE_KEY);
 	}
 
-	public void setWhileNode(Node whileNode) {
-		this.addExecutable(ConditionKey.WHILE_KEY, whileNode);
+	public void setWhileItem(Executable whileItem) {
+		this.addExecutable(ConditionKey.WHILE_KEY, whileItem);
 	}
 
 }

+ 4 - 4
liteflow-core/src/main/java/com/yomahub/liteflow/flow/parallel/ParallelSupplier.java

@@ -17,20 +17,20 @@ public class ParallelSupplier implements Supplier<WhenFutureObj> {
 
 	private final Executable executableItem;
 
-	private final String currChainName;
+	private final String currChainId;
 
 	private final Integer slotIndex;
 
-	public ParallelSupplier(Executable executableItem, String currChainName, Integer slotIndex) {
+	public ParallelSupplier(Executable executableItem, String currChainId, Integer slotIndex) {
 		this.executableItem = executableItem;
-		this.currChainName = currChainName;
+		this.currChainId = currChainId;
 		this.slotIndex = slotIndex;
 	}
 
 	@Override
 	public WhenFutureObj get() {
 		try {
-			executableItem.setCurrChainId(currChainName);
+			executableItem.setCurrChainId(currChainId);
 			executableItem.execute(slotIndex);
 			return WhenFutureObj.success(executableItem.getExecuteId());
 		}

+ 20 - 0
liteflow-core/src/main/java/com/yomahub/liteflow/slot/Slot.java

@@ -50,6 +50,10 @@ public class Slot {
 
 	private static final String IF_NODE_PREFIX = "_if_";
 
+	private static final String AND_OR_PREFIX = "_and_or_";
+
+	private static final String NOT_PREFIX = "_not_";
+
 	private static final String FOR_PREFIX = "_for_";
 
 	private static final String WHILE_PREFIX = "_while_";
@@ -233,6 +237,22 @@ public class Slot {
 		return getThreadMetaData(IF_NODE_PREFIX + key);
 	}
 
+	public void setAndOrResult(String key, boolean result) {
+		putThreadMetaDataMap(AND_OR_PREFIX + key, result);
+	}
+
+	public boolean getAndOrResult(String key) {
+		return getThreadMetaData(AND_OR_PREFIX + key);
+	}
+
+	public void setNotResult(String key, boolean result) {
+		putThreadMetaDataMap(NOT_PREFIX + key, result);
+	}
+
+	public boolean getNotResult(String key) {
+		return getThreadMetaData(NOT_PREFIX + key);
+	}
+
 	public void setForResult(String key, int forCount) {
 		putThreadMetaDataMap(FOR_PREFIX + key, forCount);
 	}

+ 70 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/BooleanOptELSpringbootTest.java

@@ -0,0 +1,70 @@
+package com.yomahub.liteflow.test.booleanOpt;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+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 org.springframework.test.context.junit4.SpringRunner;
+
+import javax.annotation.Resource;
+
+/**
+ * springboot环境EL常规的例子测试
+ *
+ * @author Bryan.Zhang
+ */
+@RunWith(SpringRunner.class)
+@TestPropertySource(value = "classpath:/booleanOpt/application.properties")
+@SpringBootTest(classes = BooleanOptELSpringbootTest.class)
+@EnableAutoConfiguration
+@ComponentScan({ "com.yomahub.liteflow.test.booleanOpt.cmp" })
+public class BooleanOptELSpringbootTest extends BaseTest {
+
+	@Resource
+	private FlowExecutor flowExecutor;
+
+	// IF情况下AND
+	@Test
+	public void testBooleanOpt1() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+		Assert.assertTrue(response.isSuccess());
+		Assert.assertEquals("x1==>x2==>x3==>b", response.getExecuteStepStr());
+	}
+
+	// IF情况下OR
+	@Test
+	public void testBooleanOpt2() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
+		Assert.assertTrue(response.isSuccess());
+		Assert.assertEquals("x1==>x2==>x3==>a", response.getExecuteStepStr());
+	}
+
+	// IF情况下AND+NOT
+	@Test
+	public void testBooleanOpt3() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
+		Assert.assertTrue(response.isSuccess());
+		Assert.assertEquals("x1==>x2==>x3==>a", response.getExecuteStepStr());
+	}
+
+	// IF情况下AND+OR+NOT混合复杂
+	@Test
+	public void testBooleanOpt4() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
+		Assert.assertTrue(response.isSuccess());
+		Assert.assertEquals("x1==>x3==>x3==>x4==>a", response.getExecuteStepStr());
+	}
+
+	@Test
+	public void testBooleanOpt5() throws Exception {
+		LiteflowResponse response = flowExecutor.execute2Resp("chain5", "arg");
+		Assert.assertTrue(response.isSuccess());
+		Assert.assertEquals("w1==>w2==>a==>bk==>w1==>w2==>a==>bk==>w1==>w2==>a==>bk==>w1==>w2==>a==>bk", response.getExecuteStepStr());
+	}
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/ACmp.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.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("a")
+public class ACmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("ACmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/BCmp.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.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeComponent;
+import org.springframework.stereotype.Component;
+
+@Component("b")
+public class BCmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("BCmp executed!");
+	}
+
+}

+ 13 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/BK.java

@@ -0,0 +1,13 @@
+package com.yomahub.liteflow.test.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeBreakComponent;
+import org.springframework.stereotype.Component;
+
+@Component("bk")
+public class BK extends NodeBreakComponent {
+    @Override
+    public boolean processBreak() throws Exception {
+        int index = this.getLoopIndex();
+        return index > 2;
+    }
+}

+ 20 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/W1.java

@@ -0,0 +1,20 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeWhileComponent;
+import org.springframework.stereotype.Component;
+
+@Component("w1")
+public class W1 extends NodeWhileComponent {
+
+	@Override
+	public boolean processWhile() throws Exception {
+		return true;
+	}
+}

+ 20 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/W2.java

@@ -0,0 +1,20 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeWhileComponent;
+import org.springframework.stereotype.Component;
+
+@Component("w2")
+public class W2 extends NodeWhileComponent {
+
+	@Override
+	public boolean processWhile() throws Exception {
+		return false;
+	}
+}

+ 12 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/X1.java

@@ -0,0 +1,12 @@
+package com.yomahub.liteflow.test.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeIfComponent;
+import org.springframework.stereotype.Component;
+
+@Component("x1")
+public class X1 extends NodeIfComponent {
+    @Override
+    public boolean processIf() throws Exception {
+        return true;
+    }
+}

+ 12 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/X2.java

@@ -0,0 +1,12 @@
+package com.yomahub.liteflow.test.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeIfComponent;
+import org.springframework.stereotype.Component;
+
+@Component("x2")
+public class X2 extends NodeIfComponent {
+    @Override
+    public boolean processIf() throws Exception {
+        return true;
+    }
+}

+ 12 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/X3.java

@@ -0,0 +1,12 @@
+package com.yomahub.liteflow.test.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeIfComponent;
+import org.springframework.stereotype.Component;
+
+@Component("x3")
+public class X3 extends NodeIfComponent {
+    @Override
+    public boolean processIf() throws Exception {
+        return false;
+    }
+}

+ 12 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/booleanOpt/cmp/X4.java

@@ -0,0 +1,12 @@
+package com.yomahub.liteflow.test.booleanOpt.cmp;
+
+import com.yomahub.liteflow.core.NodeIfComponent;
+import org.springframework.stereotype.Component;
+
+@Component("x4")
+public class X4 extends NodeIfComponent {
+    @Override
+    public boolean processIf() throws Exception {
+        return false;
+    }
+}

+ 1 - 1
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/monitorFile/MonitorFileELSpringbootTest.java

@@ -30,7 +30,7 @@ public class MonitorFileELSpringbootTest extends BaseTest {
 
 	@Test
 	public void testMonitor() throws Exception {
-		String absolutePath = new ClassPathResource("classpath:/monitorFile/flow.el.xml").getAbsolutePath();
+		String absolutePath = new ClassPathResource("classpath:/monitorFile/flow.xml").getAbsolutePath();
 		String content = FileUtil.readUtf8String(absolutePath);
 		String newContent = content.replace("THEN(a, b, c);", "THEN(a, c, b);");
 		FileUtil.writeString(newContent, new File(absolutePath), CharsetUtil.CHARSET_UTF_8);

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

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

+ 28 - 0
liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/resources/booleanOpt/flow.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE flow PUBLIC  "liteflow" "liteflow.dtd">
+<flow>
+    <chain name="chain1">
+        IF(AND(x1, x2, x3), a, b);
+    </chain>
+
+    <chain name="chain2">
+        IF(OR(x1, x2, x3), a, b);
+    </chain>
+
+    <chain name="chain3">
+        IF(AND(x1, x2, NOT(x3)), a, b);
+    </chain>
+
+    <chain name="chain4">
+        IF(
+            OR(
+                AND(x1, x3), NOT(OR(x3, x4))
+            ),
+            a, b
+        );
+    </chain>
+
+    <chain name="chain5">
+        WHILE(AND(w1, NOT(w2))).DO(a).BREAK(bk);
+    </chain>
+</flow>