diff --git a/README.md b/README.md
index 31d5086b9..dc7523213 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,31 @@ Looking forward to your use!
Discord Link: [https://discord.gg/MpdBSBnFTu](https://discord.gg/MpdBSBnFTu)
+## 👑LF CLUB Community
+
+LF CLUB is a premium paid community founded by the author of LiteFlow.
+
+LF CLUB can help all users of the LiteFlow framework, as well as potential developers who want to use LiteFlow.
+
+LF CLUB provides the following services:
+
+**1.Weekly releases of a condensed analysis series for LF. As long as users study along with the Planet series articles, they will definitely be able to fully grasp LF.**
+
+**2.Provide a Q&A service where members can ask unlimited questions and receive detailed replies and guidance on the same day.**
+
+**3.Each enrolled user is entitled to two remote one-on-one tutoring sessions per year as part of the remote assistance service.**
+
+**4.Every 1 to 2 days, there will be updates on LF's current progress and the focus of the next version.**
+
+The LF CLUB can solve all the problems you encounter when using the LiteFlow framework. It offers a series of courses to help you gain a deep understanding of the LiteFlow framework. Unlike the WeChat community, the LF CLUB prioritizes the importance of questions and provides detailed answers.
+
+Exclusive content helps you gain a profound understanding without the need to search for answers on other platforms. The author personally teaches, providing expert guidance at your fingertips, eliminating the need to seek help from others.
+
+To join the LF CLUB, please scan the QR code below or click on the image to go directly to the website.
+
+
+
+
## 🦾Sponsor
**MISBoot低代码开发平台**
@@ -76,6 +101,10 @@ Discord Link: [https://discord.gg/MpdBSBnFTu](https://discord.gg/MpdBSBnFTu)
+**FastBee物联网平台**
+
+
+
**WECHAT OFFICIAL ACCOUNT**
Since the community group is over 200 people, you need to be invited to join the group. Follow the WECHAT OFFICIAL ACCOUNT and click `Personal WeChat` to add me, I can invite you into the group
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 66de111d2..d15e96de6 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -57,6 +57,30 @@ LiteFlow拥有极其详细易懂的文档体系,能帮助你解决在使用框
LiteFlow期待你的了解!
+## 👑LF CLUB社区
+
+LF CLUB是由LiteFlow作者创办的高级付费社区
+
+LF CLUB能帮助到所有LiteFlow框架的使用者,以及想使用LiteFlow的潜在开发者。
+
+LF CLUB提供以下服务:
+
+**1.每周发布一篇LF的解析精华系列。从头开始解析LF,只要跟着星球解析系列走,使用者一定能完全掌握LF。**
+
+**2.提供答疑服务,会员可以无限制提问,当天必定得到详细的回复和指导建议。**
+
+**3.每个加入的用户每年提供2次远程一对一答疑,远程协助服务。**
+
+**4.每1到2天会分享LF目前的进度,以及下一个版本的重点。**
+
+LF CLUB里能解决你在使用LiteFlow框架时碰到的所有问题,并有系列课程能帮助你深刻理解LiteFlow框架,不同于微信社区,LF CLUB的问题优先级程度是最高的,且答疑非常详细。
+
+独家内容帮助深刻理解,不用在其他平台去搜索问题的答案。作者亲授,相当于随时拥有专家在身边,不用再去求助其他人。
+
+加入LF CLUB,请扫描以下二维码,或者直接点击图片也可以直达:
+
+
+
## 🦾赞助商
**MISBoot低代码开发平台**
@@ -71,6 +95,10 @@ LiteFlow期待你的了解!
+**FastBee物联网平台**
+
+
+
**微信公众号**
社区群需要邀请入群。关注公众号后点击`个人微信`加我,我可以拉你入群
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java
index a1e9ae2bd..dbc1cf57f 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/FallbackCmp.java
@@ -1,5 +1,6 @@
package com.yomahub.liteflow.annotation;
+import com.yomahub.liteflow.enums.BooleanTypeEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import java.lang.annotation.Documented;
@@ -20,4 +21,6 @@ import java.lang.annotation.Target;
@Documented
@Inherited
public @interface FallbackCmp {
+
+ BooleanTypeEnum value() default BooleanTypeEnum.NOT_BOOL;
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowRetry.java b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowRetry.java
index 2af9f5dae..f436c6554 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowRetry.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/LiteflowRetry.java
@@ -12,6 +12,12 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
+@Deprecated
+/**
+ * This class has been deprecated due to its only component retry function. Please use the retry method in the EL expression.
+ * @Deprecated
+ * @see # retry(int retryTimes) e.g. THEN( a, b.retry(3) ); WHEN( a, b ).retry(3);
+ */
public @interface LiteflowRetry {
@LFAliasFor("retry")
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/util/AnnoUtil.java b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/util/AnnoUtil.java
index ab86d02ea..3074c4bb2 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/util/AnnoUtil.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/annotation/util/AnnoUtil.java
@@ -3,6 +3,7 @@ package com.yomahub.liteflow.annotation.util;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.annotation.LFAliasFor;
import java.lang.annotation.Annotation;
@@ -10,15 +11,25 @@ import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* 注解工具类
+ * 此工具类带缓存
*
* @author Bryan.Zhang
*/
public class AnnoUtil {
+ private static Map annoCacheMap = new ConcurrentHashMap<>();
+
public static A getAnnotation(AnnotatedElement annotatedElement, Class annotationType) {
+ String cacheKey = StrUtil.format("{}-{}", annotatedElement, annotationType.getSimpleName());
+
+ if (annoCacheMap.containsKey(cacheKey)){
+ return (A)annoCacheMap.get(cacheKey);
+ }
+
A annotation = AnnotationUtil.getAnnotation(annotatedElement, annotationType);
if (ObjectUtil.isNull(annotation)) {
return null;
@@ -42,6 +53,8 @@ public class AnnoUtil {
}
});
+ annoCacheMap.put(cacheKey, annotation);
+
return annotation;
}
@@ -53,5 +66,4 @@ public class AnnoUtil {
return null;
}
}
-
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java
index 932cd6b62..d125e33cb 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/LiteFlowNodeBuilder.java
@@ -34,22 +34,14 @@ public class LiteFlowNodeBuilder {
return new LiteFlowNodeBuilder(NodeTypeEnum.SWITCH);
}
- public static LiteFlowNodeBuilder createIfNode() {
- return new LiteFlowNodeBuilder(NodeTypeEnum.IF);
+ public static LiteFlowNodeBuilder createBooleanNode() {
+ return new LiteFlowNodeBuilder(NodeTypeEnum.BOOLEAN);
}
public static LiteFlowNodeBuilder createForNode() {
return new LiteFlowNodeBuilder(NodeTypeEnum.FOR);
}
- public static LiteFlowNodeBuilder createWhileNode() {
- return new LiteFlowNodeBuilder(NodeTypeEnum.WHILE);
- }
-
- public static LiteFlowNodeBuilder createBreakNode() {
- return new LiteFlowNodeBuilder(NodeTypeEnum.BREAK);
- }
-
public static LiteFlowNodeBuilder createIteratorNode() {
return new LiteFlowNodeBuilder(NodeTypeEnum.ITERATOR);
}
@@ -62,22 +54,14 @@ public class LiteFlowNodeBuilder {
return new LiteFlowNodeBuilder(NodeTypeEnum.SWITCH_SCRIPT);
}
- public static LiteFlowNodeBuilder createScriptIfNode() {
- return new LiteFlowNodeBuilder(NodeTypeEnum.IF_SCRIPT);
+ public static LiteFlowNodeBuilder createScriptBooleanNode() {
+ return new LiteFlowNodeBuilder(NodeTypeEnum.BOOLEAN_SCRIPT);
}
public static LiteFlowNodeBuilder createScriptForNode() {
return new LiteFlowNodeBuilder(NodeTypeEnum.FOR_SCRIPT);
}
- public static LiteFlowNodeBuilder createScriptWhileNode() {
- return new LiteFlowNodeBuilder(NodeTypeEnum.WHILE_SCRIPT);
- }
-
- public static LiteFlowNodeBuilder createScriptBreakNode() {
- return new LiteFlowNodeBuilder(NodeTypeEnum.BREAK_SCRIPT);
- }
-
public LiteFlowNodeBuilder() {
this.node = new Node();
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java
index 0f1a65ad7..91431715d 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/LiteFlowChainELBuilder.java
@@ -21,6 +21,7 @@ import com.yomahub.liteflow.exception.ParseException;
import com.yomahub.liteflow.flow.FlowBus;
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.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
@@ -44,6 +45,11 @@ public class LiteFlowChainELBuilder {
private Chain chain;
+ /**
+ * 这是route EL的文本
+ */
+ private Executable route;
+
/**
* 这是主体的Condition //声明这个变量,而不是用chain.getConditionList的目的,是为了辅助平滑加载
* 虽然FlowBus里面的map都是CopyOnWrite类型的,但是在buildCondition的时候,为了平滑加载,所以不能事先把chain.getConditionList给设为空List
@@ -92,6 +98,7 @@ public class LiteFlowChainELBuilder {
EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MAX_WAIT_SECONDS, Object.class, new MaxWaitSecondsOperator());
EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.MAX_WAIT_MILLISECONDS, Object.class, new MaxWaitMillisecondsOperator());
EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.PARALLEL, Object.class, new ParallelOperator());
+ EXPRESS_RUNNER.addFunctionAndClassMethod(ChainConstant.RETRY, Object.class, new RetryOperator());
}
public static LiteFlowChainELBuilder createChain() {
@@ -129,6 +136,45 @@ public class LiteFlowChainELBuilder {
return this;
}
+ public LiteFlowChainELBuilder setRoute(String routeEl){
+ if (StrUtil.isBlank(routeEl)) {
+ String errMsg = StrUtil.format("You have defined the label but there is no content in the chain[{}].", chain.getChainId());
+ throw new FlowSystemException(errMsg);
+ }
+ List errorList = new ArrayList<>();
+ try {
+ DefaultContext context = new DefaultContext<>();
+
+ // 往上下文里放入所有的node,使得el表达式可以直接引用到nodeId
+ FlowBus.getNodeMap().keySet().forEach(nodeId -> context.put(nodeId, FlowBus.getNode(nodeId)));
+
+ // 解析route el成为一个executable
+ Executable routeExecutable = (Executable) EXPRESS_RUNNER.execute(routeEl, context, errorList, true, true);
+
+ if (Objects.isNull(routeExecutable)){
+ throw new QLException(StrUtil.format("parse route el fail,el:[{}]", routeEl));
+ }
+
+ // 把主要的condition加入
+ this.route = routeExecutable;
+ return this;
+ } catch (QLException e) {
+ // EL 底层会包装异常,这里是曲线处理
+ if (ObjectUtil.isNotNull(e.getCause()) && Objects.equals(e.getCause().getMessage(), DataNotFoundException.MSG)) {
+ // 构建错误信息
+ String msg = buildDataNotFoundExceptionMsg(routeEl);
+ throw new ELParseException(msg);
+ }else if (ObjectUtil.isNotNull(e.getCause())){
+ throw new ELParseException(e.getCause().getMessage());
+ }else{
+ throw new ELParseException(e.getMessage());
+ }
+ } catch (Exception e) {
+ String errMsg = StrUtil.format("parse el fail in this chain[{}];\r\n", chain.getChainId());
+ throw new ELParseException(errMsg + e.getMessage());
+ }
+ }
+
public LiteFlowChainELBuilder setEL(String elStr) {
if (StrUtil.isBlank(elStr)) {
String errMsg = StrUtil.format("no content in this chain[{}]", chain.getChainId());
@@ -196,6 +242,7 @@ public class LiteFlowChainELBuilder {
}
public void build() {
+ this.chain.setRouteItem(this.route);
this.chain.setConditionList(this.conditionList);
//暂且去掉循环依赖检测,因为有发现循环依赖检测在对大的EL进行检测的时候,会导致CPU飙升,也或许是jackson低版本的问题
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AndOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AndOperator.java
index 0e5f731ab..29d663cbe 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AndOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/AndOperator.java
@@ -16,7 +16,7 @@ import com.yomahub.liteflow.flow.element.condition.BooleanConditionTypeEnum;
public class AndOperator extends BaseOperator {
@Override
public AndOrCondition build(Object[] objects) throws Exception {
- OperatorHelper.checkObjectSizeGtTwo(objects);
+ OperatorHelper.checkObjectSizeGteTwo(objects);
AndOrCondition andOrCondition = new AndOrCondition();
andOrCondition.setBooleanConditionType(BooleanConditionTypeEnum.AND);
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java
index b3e3f0c28..8a903008c 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/MustOperator.java
@@ -19,7 +19,7 @@ public class MustOperator extends BaseOperator {
@Override
public WhenCondition build(Object[] objects) throws Exception {
- OperatorHelper.checkObjectSizeGtTwo(objects);
+ OperatorHelper.checkObjectSizeGteTwo(objects);
String errorMsg = "The caller must be WhenCondition item";
WhenCondition whenCondition = OperatorHelper.convert(objects[0], WhenCondition.class, errorMsg);
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/OrOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/OrOperator.java
index d084a7536..361ab62bb 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/OrOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/OrOperator.java
@@ -16,7 +16,7 @@ import com.yomahub.liteflow.flow.element.condition.BooleanConditionTypeEnum;
public class OrOperator extends BaseOperator {
@Override
public AndOrCondition build(Object[] objects) throws Exception {
- OperatorHelper.checkObjectSizeGtTwo(objects);
+ OperatorHelper.checkObjectSizeGteTwo(objects);
AndOrCondition andOrCondition = new AndOrCondition();
andOrCondition.setBooleanConditionType(BooleanConditionTypeEnum.OR);
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/RetryOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/RetryOperator.java
new file mode 100644
index 000000000..38f8c6b6c
--- /dev/null
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/RetryOperator.java
@@ -0,0 +1,35 @@
+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;
+import com.yomahub.liteflow.flow.element.Executable;
+import com.yomahub.liteflow.flow.element.condition.RetryCondition;
+
+/**
+ *
+ * @author Rain
+ * @since 2.12.0
+ *
+ */
+public class RetryOperator extends BaseOperator {
+ @Override
+ public Condition build(Object[] objects) throws Exception {
+ OperatorHelper.checkObjectSizeGteTwo(objects);
+ Executable executable = OperatorHelper.convert(objects[0], Executable.class);
+ Integer retryTimes = OperatorHelper.convert(objects[1], Integer.class);
+ RetryCondition retryCondition = new RetryCondition();
+ retryCondition.addExecutable(executable);
+ retryCondition.setRetryTimes(retryTimes);
+ if(objects.length > 2) {
+ Class[] forExceptions = new Class[objects.length - 2];
+ for(int i = 2; i < objects.length; i ++) {
+ String className = OperatorHelper.convert(objects[i], String.class);
+ forExceptions[i - 2] = Class.forName(className);
+ }
+ retryCondition.setRetryForExceptions(forExceptions);
+ }
+ return retryCondition;
+ }
+
+}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ToOperator.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ToOperator.java
index d38722a03..4eede8779 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ToOperator.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/ToOperator.java
@@ -15,7 +15,7 @@ public class ToOperator extends BaseOperator {
@Override
public SwitchCondition build(Object[] objects) throws Exception {
- OperatorHelper.checkObjectSizeGtTwo(objects);
+ OperatorHelper.checkObjectSizeGteTwo(objects);
String errorMsg = "The caller must be SwitchCondition item";
SwitchCondition switchCondition = OperatorHelper.convert(objects[0], SwitchCondition.class, errorMsg);
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java
index c54681a63..ee0be1f6c 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/builder/el/operator/base/OperatorHelper.java
@@ -10,8 +10,6 @@ import com.yomahub.liteflow.exception.DataNotFoundException;
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.element.condition.AndOrCondition;
-import com.yomahub.liteflow.flow.element.condition.NotCondition;
import java.util.Objects;
@@ -35,13 +33,13 @@ public class OperatorHelper {
}
/**
- * 检查参数数量,大于 2
+ * 检查参数数量,大于等于 2
* @param objects objects
* @throws QLException QLException
*/
- public static void checkObjectSizeGtTwo(Object[] objects) throws QLException {
+ public static void checkObjectSizeGteTwo(Object[] objects) throws QLException {
checkObjectSizeGtZero(objects);
- if (objects.length <= 1) {
+ if (objects.length < 2) {
throw new QLException("parameter error");
}
}
@@ -119,7 +117,7 @@ public class OperatorHelper {
if (clazz.isAssignableFrom(object.getClass())) {
if (object instanceof Node) {
Node node = (Node) object;
- return (T) node.copy();
+ return (T) node.clone();
}
else {
return (T) object;
@@ -169,12 +167,8 @@ public class OperatorHelper {
Executable item = (Executable) object;
if (item.getExecuteType().equals(ExecuteTypeEnum.NODE)){
Node node = (Node) item;
- if (!ListUtil.toList(NodeTypeEnum.IF,
- NodeTypeEnum.IF_SCRIPT,
- NodeTypeEnum.WHILE,
- NodeTypeEnum.WHILE_SCRIPT,
- NodeTypeEnum.BREAK,
- NodeTypeEnum.BREAK_SCRIPT,
+ if (!ListUtil.toList(NodeTypeEnum.BOOLEAN,
+ NodeTypeEnum.BOOLEAN_SCRIPT,
NodeTypeEnum.FALLBACK).contains(node.getType())){
throw new QLException(StrUtil.format("The node[{}] must be boolean type Node.", node.getId()));
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java b/liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java
index 105c8b755..ad64b36e5 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/common/ChainConstant.java
@@ -10,6 +10,10 @@ public interface ChainConstant {
String CHAIN = "chain";
+ String ROUTE = "route";
+
+ String BODY = "body";
+
String FLOW = "flow";
String NODES = "nodes";
@@ -96,4 +100,6 @@ public interface ChainConstant {
String EXTENDS = "extends";
+ String RETRY = "retry";
+
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBooleanComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBooleanComponent.java
new file mode 100644
index 000000000..5625fe780
--- /dev/null
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBooleanComponent.java
@@ -0,0 +1,26 @@
+package com.yomahub.liteflow.core;
+
+import com.yomahub.liteflow.slot.DataBus;
+
+/**
+ * BOOLEAN类型的抽象节点
+ *
+ * @author Bryan.Zhang
+ * @since 2.12.0
+ */
+public abstract class NodeBooleanComponent extends NodeComponent {
+
+ @Override
+ public void process() throws Exception {
+ boolean result = this.processBoolean();
+ this.getSlot().setIfResult(this.getMetaValueKey(), result);
+ }
+
+ public abstract boolean processBoolean() throws Exception;
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Boolean getItemResultMetaValue(Integer slotIndex) {
+ return DataBus.getSlot(slotIndex).getIfResult(this.getMetaValueKey());
+ }
+}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBreakComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBreakComponent.java
deleted file mode 100644
index a26bdb8cc..000000000
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeBreakComponent.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.yomahub.liteflow.core;
-
-import com.yomahub.liteflow.slot.DataBus;
-import com.yomahub.liteflow.slot.Slot;
-import com.yomahub.liteflow.core.proxy.LiteFlowProxyUtil;
-
-/**
- * 循环跳出节点逻辑抽象类
- *
- * @author Bryan.Zhang
- * @since 2.9.0
- */
-public abstract class NodeBreakComponent extends NodeComponent {
-
- @Override
- public void process() throws Exception {
- boolean breakFlag = processBreak();
- Slot slot = this.getSlot();
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- slot.setBreakResult(originalClass.getName(), breakFlag);
- }
-
- 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());
- }
-
-}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java
index 283de4216..02140db44 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeComponent.java
@@ -7,44 +7,37 @@
*/
package com.yomahub.liteflow.core;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.ttl.TransmittableThreadLocal;
-import com.yomahub.liteflow.exception.ChainEndException;
+import com.yomahub.liteflow.core.proxy.LiteFlowProxyUtil;
+import com.yomahub.liteflow.enums.CmpStepTypeEnum;
+import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.flow.element.Node;
-import com.yomahub.liteflow.flow.executor.NodeExecutor;
+import com.yomahub.liteflow.flow.entity.CmpStep;
import com.yomahub.liteflow.flow.executor.DefaultNodeExecutor;
-import com.yomahub.liteflow.enums.NodeTypeEnum;
+import com.yomahub.liteflow.flow.executor.NodeExecutor;
import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
-import com.yomahub.liteflow.spi.holder.CmpAroundAspectHolder;
-import com.yomahub.liteflow.util.JsonUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import com.yomahub.liteflow.flow.entity.CmpStep;
-import com.yomahub.liteflow.enums.CmpStepTypeEnum;
-import com.yomahub.liteflow.slot.DataBus;
-import com.yomahub.liteflow.slot.Slot;
-import com.yomahub.liteflow.flow.element.Executable;
import com.yomahub.liteflow.monitor.CompStatistics;
import com.yomahub.liteflow.monitor.MonitorBus;
+import com.yomahub.liteflow.slot.DataBus;
+import com.yomahub.liteflow.slot.Slot;
+import com.yomahub.liteflow.spi.holder.CmpAroundAspectHolder;
+import com.yomahub.liteflow.util.JsonUtil;
import java.lang.reflect.Method;
import java.util.Date;
-import java.util.Deque;
-import java.util.Map;
-import java.util.function.Predicate;
/**
* 普通组件抽象类
*
* @author Bryan.Zhang
+ * @author luo yi
*/
-public abstract class NodeComponent {
+public abstract class NodeComponent{
private final LFLog LOG = LFLoggerManager.getLogger(this.getClass());
@@ -77,16 +70,11 @@ public abstract class NodeComponent {
private final TransmittableThreadLocal refNodeTL = new TransmittableThreadLocal<>();
/**
- ******************* 以下的属性为线程附加属性******************** 线程属性是指每一个request的值都是不一样的
+ ******************* 以下的属性为线程附加属性********************
+ * 线程属性是指每一个request的值都是不一样的
* 这里NodeComponent是单例,所以要用ThreadLocal来修饰
*/
- // 当前slot的index
- private final TransmittableThreadLocal slotIndexTL = new TransmittableThreadLocal<>();
-
- // 是否结束整个流程,这个只对串行流程有效,并行流程无效
- private final TransmittableThreadLocal isEndTL = new TransmittableThreadLocal<>();
-
public NodeComponent() {
// 反射判断是否重写了rollback方法
Class> clazz = this.getClass();
@@ -237,39 +225,29 @@ public abstract class NodeComponent {
// 是否结束整个流程(不往下继续执行)
public boolean isEnd() {
- Boolean isEnd = isEndTL.get();
+ Boolean isEnd = this.refNodeTL.get().getIsEnd();
if (ObjectUtil.isNull(isEnd)) {
return false;
- }
- else {
- return isEndTL.get();
+ }else {
+ return isEnd;
}
}
// 设置是否结束整个流程
public void setIsEnd(boolean isEnd) {
- this.isEndTL.set(isEnd);
+ this.refNodeTL.get().setIsEnd(isEnd);
}
- public void removeIsEnd() {
- this.isEndTL.remove();
- }
-
- public NodeComponent setSlotIndex(Integer slotIndex) {
- this.slotIndexTL.set(slotIndex);
- return this;
+ public void setIsContinueOnError(boolean isContinueOnError) {
+ this.refNodeTL.get().setIsContinueOnErrorResult(isContinueOnError);
}
public Integer getSlotIndex() {
- return this.slotIndexTL.get();
- }
-
- public void removeSlotIndex() {
- this.slotIndexTL.remove();
+ return this.refNodeTL.get().getSlotIndex();
}
public Slot getSlot() {
- return DataBus.getSlot(this.slotIndexTL.get());
+ return DataBus.getSlot(this.getSlotIndex());
}
public T getFirstContextBean() {
@@ -280,6 +258,10 @@ public abstract class NodeComponent {
return this.getSlot().getContextBean(contextBeanClazz);
}
+ public T getContextBean(String contextName) {
+ return this.getSlot().getContextBean(contextName);
+ }
+
public String getNodeId() {
return nodeId;
}
@@ -454,4 +436,9 @@ public abstract class NodeComponent {
public T getItemResultMetaValue(Integer slotIndex){
return null;
}
+
+ protected String getMetaValueKey(){
+ Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
+ return originalClass.getName();
+ }
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeForComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeForComponent.java
index 53675e614..7f65a57e4 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeForComponent.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeForComponent.java
@@ -16,8 +16,7 @@ public abstract class NodeForComponent extends NodeComponent {
public void process() throws Exception {
int forCount = processFor();
Slot slot = this.getSlot();
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- slot.setForResult(originalClass.getName(), forCount);
+ slot.setForResult(this.getMetaValueKey(), forCount);
}
public abstract int processFor() throws Exception;
@@ -25,8 +24,7 @@ public abstract class NodeForComponent extends NodeComponent {
@Override
@SuppressWarnings("unchecked")
public Integer getItemResultMetaValue(Integer slotIndex) {
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- return DataBus.getSlot(slotIndex).getForResult(originalClass.getName());
+ return DataBus.getSlot(slotIndex).getForResult(this.getMetaValueKey());
}
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIfComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIfComponent.java
deleted file mode 100644
index 341051279..000000000
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIfComponent.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.yomahub.liteflow.core;
-
-import com.yomahub.liteflow.slot.DataBus;
-import com.yomahub.liteflow.core.proxy.LiteFlowProxyUtil;
-
-/**
- * IF节点抽象类
- *
- * @author Bryan.Zhang
- * @since 2.8.5
- */
-public abstract class NodeIfComponent extends NodeComponent {
-
- @Override
- public void process() throws Exception {
- boolean result = this.processIf();
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- this.getSlot().setIfResult(originalClass.getName(), result);
- }
-
- 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());
- }
-}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIteratorComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIteratorComponent.java
index f8aec09ea..6f5068da7 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIteratorComponent.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeIteratorComponent.java
@@ -18,8 +18,7 @@ public abstract class NodeIteratorComponent extends NodeComponent {
public void process() throws Exception {
Iterator> it = processIterator();
Slot slot = this.getSlot();
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- slot.setIteratorResult(originalClass.getName(), it);
+ slot.setIteratorResult(this.getMetaValueKey(), it);
}
public abstract Iterator> processIterator() throws Exception;
@@ -27,8 +26,7 @@ public abstract class NodeIteratorComponent extends NodeComponent {
@Override
@SuppressWarnings("unchecked")
public Iterator> getItemResultMetaValue(Integer slotIndex) {
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- return DataBus.getSlot(slotIndex).getIteratorResult(originalClass.getName());
+ return DataBus.getSlot(slotIndex).getIteratorResult(this.getMetaValueKey());
}
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeSwitchComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeSwitchComponent.java
index b24e32296..c4320a4e2 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeSwitchComponent.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeSwitchComponent.java
@@ -20,8 +20,7 @@ public abstract class NodeSwitchComponent extends NodeComponent {
@Override
public void process() throws Exception {
String nodeId = this.processSwitch();
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- this.getSlot().setSwitchResult(originalClass.getName(), nodeId);
+ this.getSlot().setSwitchResult(this.getMetaValueKey(), nodeId);
}
// 用以返回路由节点的beanId
@@ -30,8 +29,7 @@ public abstract class NodeSwitchComponent extends NodeComponent {
@Override
@SuppressWarnings("unchecked")
public String getItemResultMetaValue(Integer slotIndex) {
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- return DataBus.getSlot(slotIndex).getSwitchResult(originalClass.getName());
+ return DataBus.getSlot(slotIndex).getSwitchResult(this.getMetaValueKey());
}
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeWhileComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeWhileComponent.java
deleted file mode 100644
index 446b6587a..000000000
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/NodeWhileComponent.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.yomahub.liteflow.core;
-
-import com.yomahub.liteflow.slot.DataBus;
-import com.yomahub.liteflow.slot.Slot;
-import com.yomahub.liteflow.core.proxy.LiteFlowProxyUtil;
-
-/**
- * WHILE条件节点抽象类
- *
- * @author Bryan.Zhang
- * @since 2.9.0
- */
-public abstract class NodeWhileComponent extends NodeComponent {
-
- @Override
- public void process() throws Exception {
- boolean whileFlag = processWhile();
- Slot slot = this.getSlot();
- Class> originalClass = LiteFlowProxyUtil.getUserClass(this.getClass());
- slot.setWhileResult(originalClass.getName(), whileFlag);
- }
-
- 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());
- }
-
-}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptIfComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBooleanComponent.java
similarity index 74%
rename from liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptIfComponent.java
rename to liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBooleanComponent.java
index a55cb8ed3..995563531 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptIfComponent.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBooleanComponent.java
@@ -3,18 +3,16 @@ package com.yomahub.liteflow.core;
import com.yomahub.liteflow.script.ScriptExecuteWrap;
import com.yomahub.liteflow.script.ScriptExecutorFactory;
-import java.util.Map;
-
/**
- * 脚本IF节点
+ * 脚本BOOLEAN节点
*
* @author Bryan.Zhang
- * @since 2.8.5
+ * @since 2.12.0
*/
-public class ScriptIfComponent extends NodeIfComponent implements ScriptComponent {
+public class ScriptBooleanComponent extends NodeBooleanComponent implements ScriptComponent {
@Override
- public boolean processIf() throws Exception {
+ public boolean processBoolean() throws Exception {
ScriptExecuteWrap wrap = this.buildWrap(this);
return (boolean) ScriptExecutorFactory.loadInstance()
.getScriptExecutor(this.getRefNode().getLanguage())
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBreakComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBreakComponent.java
deleted file mode 100644
index 379993cb4..000000000
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptBreakComponent.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.yomahub.liteflow.core;
-
-import com.yomahub.liteflow.script.ScriptExecuteWrap;
-import com.yomahub.liteflow.script.ScriptExecutorFactory;
-
-import java.util.Map;
-
-/**
- * 脚本BREAK节点
- *
- * @author Bryan.Zhang
- * @since 2.9.0
- */
-public class ScriptBreakComponent extends NodeBreakComponent implements ScriptComponent {
-
- @Override
- public boolean processBreak() throws Exception {
- ScriptExecuteWrap wrap = this.buildWrap(this);
- return (boolean) ScriptExecutorFactory.loadInstance()
- .getScriptExecutor(this.getRefNode().getLanguage())
- .execute(wrap);
- }
-
- @Override
- public void loadScript(String script, String language) {
- ScriptExecutorFactory.loadInstance().getScriptExecutor(language).load(getNodeId(), script);
- }
-
-}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java
index c6fe31637..77fa7ffe6 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptComponent.java
@@ -21,10 +21,8 @@ public interface ScriptComponent {
{
put(NodeTypeEnum.SCRIPT, ScriptCommonComponent.class);
put(NodeTypeEnum.SWITCH_SCRIPT, ScriptSwitchComponent.class);
- put(NodeTypeEnum.IF_SCRIPT, ScriptIfComponent.class);
+ put(NodeTypeEnum.BOOLEAN_SCRIPT, ScriptBooleanComponent.class);
put(NodeTypeEnum.FOR_SCRIPT, ScriptForComponent.class);
- put(NodeTypeEnum.WHILE_SCRIPT, ScriptWhileComponent.class);
- put(NodeTypeEnum.BREAK_SCRIPT, ScriptBreakComponent.class);
}
};
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptWhileComponent.java b/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptWhileComponent.java
deleted file mode 100644
index ef07d31e3..000000000
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/core/ScriptWhileComponent.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.yomahub.liteflow.core;
-
-import com.yomahub.liteflow.script.ScriptExecuteWrap;
-import com.yomahub.liteflow.script.ScriptExecutorFactory;
-
-import java.util.Map;
-
-/**
- * 脚本WHILE节点
- *
- * @author Bryan.Zhang
- * @since 2.9.0
- */
-public class ScriptWhileComponent extends NodeWhileComponent implements ScriptComponent {
-
- @Override
- public boolean processWhile() throws Exception {
- ScriptExecuteWrap wrap = this.buildWrap(this);
- return (boolean) ScriptExecutorFactory.loadInstance()
- .getScriptExecutor(this.getRefNode().getLanguage())
- .execute(wrap);
- }
-
- @Override
- public void loadScript(String script, String language) {
- ScriptExecutorFactory.loadInstance().getScriptExecutor(language).load(getNodeId(), script);
- }
-
-}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/BooleanTypeEnum.java b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/BooleanTypeEnum.java
new file mode 100644
index 000000000..33ec35257
--- /dev/null
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/BooleanTypeEnum.java
@@ -0,0 +1,13 @@
+package com.yomahub.liteflow.enums;
+
+/**
+ * 布尔节点的细分TYPE
+ * 主要用于组件降级
+ *
+ * @author Bryan.Zhang
+ * @since 2.12.0
+ */
+public enum BooleanTypeEnum {
+
+ NOT_BOOL,IF,WHILE,BREAK
+}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/LiteFlowMethodEnum.java b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/LiteFlowMethodEnum.java
index be015b2a0..5b6d0034e 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/LiteFlowMethodEnum.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/LiteFlowMethodEnum.java
@@ -4,10 +4,8 @@ public enum LiteFlowMethodEnum {
PROCESS("process", true),
PROCESS_SWITCH("processSwitch", true),
- PROCESS_IF("processIf", true),
+ PROCESS_BOOLEAN("processBoolean", true),
PROCESS_FOR("processFor", true),
- PROCESS_WHILE("processWhile", true),
- PROCESS_BREAK("processBreak", true),
PROCESS_ITERATOR("processIterator", true),
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java
index 7ca1efff7..a02ae6287 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/enums/NodeTypeEnum.java
@@ -25,28 +25,20 @@ public enum NodeTypeEnum {
SWITCH("switch", "选择", false, NodeSwitchComponent.class),
- IF("if", "条件", false, NodeIfComponent.class),
+ BOOLEAN("boolean", "布尔", false, NodeBooleanComponent.class),
FOR("for", "循环次数", false, NodeForComponent.class),
- WHILE("while", "循环条件", false, NodeWhileComponent.class),
-
- BREAK("break", "循环跳出", false, NodeBreakComponent.class),
-
ITERATOR("iterator", "循环迭代", false, NodeIteratorComponent.class),
SCRIPT("script", "脚本", true, ScriptCommonComponent.class),
SWITCH_SCRIPT("switch_script", "选择脚本", true, ScriptSwitchComponent.class),
- IF_SCRIPT("if_script", "条件脚本", true, ScriptIfComponent.class),
+ BOOLEAN_SCRIPT("boolean_script", "布尔脚本", true, ScriptBooleanComponent.class),
FOR_SCRIPT("for_script", "循环次数脚本", true, ScriptForComponent.class),
- WHILE_SCRIPT("while_script", "循环条件脚本", true, ScriptWhileComponent.class),
-
- BREAK_SCRIPT("break_script", "循环跳出脚本", true, ScriptBreakComponent.class),
-
FALLBACK("fallback", "降级", false, null);
private static final LFLog LOG = LFLoggerManager.getLogger(NodeTypeEnum.class);
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java
index c7ea30335..34a11d3a7 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/FlowBus.java
@@ -16,11 +16,13 @@ import com.yomahub.liteflow.core.ComponentInitializer;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.core.ScriptComponent;
import com.yomahub.liteflow.core.proxy.DeclWarpBean;
+import com.yomahub.liteflow.enums.BooleanTypeEnum;
import com.yomahub.liteflow.enums.FlowParserTypeEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.ComponentCannotRegisterException;
import com.yomahub.liteflow.exception.NullNodeTypeException;
import com.yomahub.liteflow.flow.element.Chain;
+import com.yomahub.liteflow.flow.element.Condition;
import com.yomahub.liteflow.flow.element.Node;
import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
@@ -40,7 +42,9 @@ import com.yomahub.liteflow.core.proxy.LiteFlowProxyUtil;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* 流程元数据类
@@ -56,7 +60,7 @@ public class FlowBus {
private static final Map nodeMap;
- private static final Map fallbackNodeMap;
+ private static final Map fallbackNodeMap;
private static AtomicBoolean initStat = new AtomicBoolean(false);
@@ -241,6 +245,14 @@ public class FlowBus {
return nodeMap.get(nodeId);
}
+ // 获取某一个 chainId 下的所有 nodeId
+ public static List getNodesByChainId(String chainId) {
+ Chain chain = getChain(chainId);
+ return chain.getConditionList().stream().flatMap(
+ (Function>) condition -> condition.getAllNodeInCondition().stream()
+ ).collect(Collectors.toList());
+ }
+
public static Map getNodeMap() {
return nodeMap;
}
@@ -250,7 +262,12 @@ public class FlowBus {
}
public static Node getFallBackNode(NodeTypeEnum nodeType) {
- return fallbackNodeMap.get(nodeType);
+ return getFallBackNode(nodeType, BooleanTypeEnum.NOT_BOOL);
+ }
+
+ public static Node getFallBackNode(NodeTypeEnum nodeType, BooleanTypeEnum booleanTypeEnum){
+ String key = StrUtil.format("{}_{}", nodeType.name(), booleanTypeEnum.name());
+ return fallbackNodeMap.get(key);
}
public static void cleanCache() {
@@ -297,6 +314,11 @@ public class FlowBus {
Arrays.stream(chainIds).forEach(FlowBus::removeChain);
}
+ // 移除节点
+ public static boolean removeNode(String nodeId) {
+ return nodeMap.remove(nodeId) != null;
+ }
+
// 判断是否是降级组件,如果是则添加到 fallbackNodeMap
private static void addFallbackNode(Node node) {
NodeComponent nodeComponent = node.getInstance();
@@ -306,7 +328,35 @@ public class FlowBus {
}
NodeTypeEnum nodeType = node.getType();
- fallbackNodeMap.put(nodeType, node);
+ String key = StrUtil.format("{}_{}", nodeType.name(), fallbackCmp.value().name());
+ fallbackNodeMap.put(key, node);
+ }
+
+ // 重新加载脚本
+ public static void reloadScript(String nodeId, String script) {
+ Node node = getNode(nodeId);
+ if (node == null || !node.getType().isScript()) {
+ return;
+ }
+ // 更新脚本
+ node.setScript(script);
+ ScriptExecutorFactory.loadInstance()
+ .getScriptExecutor(node.getLanguage())
+ .load(nodeId, script);
+ }
+
+ // 卸载脚本节点
+ public static boolean unloadScriptNode(String nodeId) {
+ Node node = getNode(nodeId);
+ if (node == null || !node.getType().isScript()) {
+ return false;
+ }
+ // 卸载脚本
+ ScriptExecutorFactory.loadInstance()
+ .getScriptExecutor(node.getLanguage())
+ .unLoad(nodeId);
+ // 移除脚本
+ return removeNode(nodeId);
}
public static void clearStat(){
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java
index c2645a299..51e1ddc28 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/LiteflowResponse.java
@@ -101,6 +101,10 @@ public class LiteflowResponse {
return this.getSlot().getContextBean(contextBeanClazz);
}
+ public T getContextBean(String contextName) {
+ return this.getSlot().getContextBean(contextName);
+ }
+
public Map> getExecuteSteps() {
Map> map = new LinkedHashMap<>();
this.getSlot().getExecuteSteps().forEach(cmpStep -> {
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java
index 16cc12546..04cada75d 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Chain.java
@@ -30,6 +30,8 @@ public class Chain implements Executable{
private String chainId;
+ private Executable routeItem;
+
private List conditionList = new ArrayList<>();
public Chain(String chainName) {
@@ -133,4 +135,12 @@ public class Chain implements Executable{
public String getTag() {
return null;
}
+
+ public Executable getRouteItem() {
+ return routeItem;
+ }
+
+ public void setRouteItem(Executable routeItem) {
+ this.routeItem = routeItem;
+ }
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java
index 0d4eec6a7..667b78be8 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Condition.java
@@ -22,6 +22,11 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Condition的抽象类
@@ -103,6 +108,24 @@ public abstract class Condition implements Executable{
}
}
+ public List getAllNodeInCondition(){
+ List executableList = this.executableGroup.entrySet().stream().flatMap(
+ (Function>, Stream>) entry -> entry.getValue().stream()
+ ).collect(Collectors.toList());
+
+ List resultList = new ArrayList<>();
+
+ executableList.stream().forEach(executable -> {
+ if (executable instanceof Condition){
+ resultList.addAll(((Condition)executable).getAllNodeInCondition());
+ }else if(executable instanceof Node){
+ resultList.add((Node)executable);
+ }
+ });
+
+ return resultList;
+ }
+
public void setExecutableList(List executableList) {
this.executableGroup.put(ConditionKey.DEFAULT_KEY, executableList);
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNode.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNode.java
index 966f37a61..f6302b915 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNode.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/FallbackNode.java
@@ -2,6 +2,8 @@ package com.yomahub.liteflow.flow.element;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ObjectUtil;
+import com.yomahub.liteflow.core.NodeComponent;
+import com.yomahub.liteflow.enums.BooleanTypeEnum;
import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import com.yomahub.liteflow.exception.FallbackCmpNotFoundException;
@@ -64,7 +66,7 @@ public class FallbackNode extends Node {
this.getCurrChainId()));
}
// 使用 node 的副本
- this.fallbackNode = node.copy();
+ this.fallbackNode = node.clone();
}
private Node findFallbackNode(Condition condition) {
@@ -88,7 +90,8 @@ public class FallbackNode extends Node {
return findNodeInIterator((IteratorCondition) condition);
case TYPE_NOT_OPT:
case TYPE_AND_OR_OPT:
- return FlowBus.getFallBackNode(NodeTypeEnum.IF);
+ //组件降级用在与并或中,只能用在IF表达式中
+ return FlowBus.getFallBackNode(NodeTypeEnum.BOOLEAN, BooleanTypeEnum.IF);
default:
return null;
}
@@ -98,7 +101,7 @@ public class FallbackNode extends Node {
Executable ifItem = ifCondition.getIfItem();
if (ifItem == this) {
// 需要条件组件
- return FlowBus.getFallBackNode(NodeTypeEnum.IF);
+ return FlowBus.getFallBackNode(NodeTypeEnum.BOOLEAN, BooleanTypeEnum.IF);
}
// 需要普通组件
@@ -126,7 +129,7 @@ public class FallbackNode extends Node {
private Node findNodeInWhile(WhileCondition whileCondition) {
Executable whileItem = whileCondition.getWhileItem();
if (whileItem == this) {
- return FlowBus.getFallBackNode(NodeTypeEnum.WHILE);
+ return FlowBus.getFallBackNode(NodeTypeEnum.BOOLEAN, BooleanTypeEnum.WHILE);
}
return findNodeInLoop(whileCondition);
@@ -144,7 +147,7 @@ public class FallbackNode extends Node {
private Node findNodeInLoop(LoopCondition loopCondition) {
Executable breakItem = loopCondition.getExecutableOne(ConditionKey.BREAK_KEY);
if (breakItem == this) {
- return FlowBus.getFallBackNode(NodeTypeEnum.BREAK);
+ return FlowBus.getFallBackNode(NodeTypeEnum.BOOLEAN, BooleanTypeEnum.BREAK);
}
return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
@@ -162,13 +165,21 @@ public class FallbackNode extends Node {
return this.fallbackNode.isAccess(slotIndex);
}
+ @Override
+ public NodeComponent getInstance() {
+ if (fallbackNode == null){
+ return null;
+ }
+ return fallbackNode.getInstance();
+ }
+
@Override
public String getId() {
return this.fallbackNode == null ? null : this.fallbackNode.getId();
}
@Override
- public Node copy() {
+ public Node clone() {
// 代理节点不复制
return this;
}
diff --git a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java
index 269a4dd62..683bfd8dd 100644
--- a/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java
+++ b/liteflow-core/src/main/java/com/yomahub/liteflow/flow/element/Node.java
@@ -21,8 +21,6 @@ import com.yomahub.liteflow.flow.executor.NodeExecutor;
import com.yomahub.liteflow.flow.executor.NodeExecutorHelper;
import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
-import com.yomahub.liteflow.property.LiteflowConfig;
-import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.slot.DataBus;
import com.yomahub.liteflow.slot.Slot;
@@ -30,6 +28,7 @@ import com.yomahub.liteflow.slot.Slot;
* Node节点,实现可执行器 Node节点并不是单例的,每构建一次都会copy出一个新的实例
*
* @author Bryan.Zhang
+ * @author luo yi
*/
public class Node implements Executable, Cloneable, Rollbackable{
@@ -57,10 +56,24 @@ public class Node implements Executable, Cloneable, Rollbackable{
private String currChainId;
+ // node 的 isAccess 结果,主要用于 WhenCondition 的提前 isAccess 判断,避免 isAccess 方法重复执行
+ private TransmittableThreadLocal accessResult = new TransmittableThreadLocal<>();
+
+ // 循环下标
private TransmittableThreadLocal loopIndexTL = new TransmittableThreadLocal<>();
+ // 迭代对象
private TransmittableThreadLocal