diff --git a/liteflow-el-builder/pom.xml b/liteflow-el-builder/pom.xml
new file mode 100644
index 000000000..4b5fa9fe6
--- /dev/null
+++ b/liteflow-el-builder/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+ jar
+ liteflow-el-builder
+ liteflow el builder
+
+
+ com.yomahub
+ liteflow
+ ${revision}
+ ../pom.xml
+
+
+
+
+ com.yomahub
+ liteflow-core
+ ${revision}
+
+
+ cn.hutool
+ hutool-core
+
+
+
\ No newline at end of file
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/AndELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/AndELWrapper.java
new file mode 100644
index 000000000..d0bd6e217
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/AndELWrapper.java
@@ -0,0 +1,99 @@
+package com.yomahub.liteflow.builder.el;
+
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 与或非表达式中的 与表达式
+ * 参数允许任意数量 参数必须返回true或false
+ *
+ * 使用and()方法加入新的表达式
+ * 支持设置 id tag data maxWaitSeconds 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class AndELWrapper extends ELWrapper{
+
+ public AndELWrapper(ELWrapper ... elWrappers){
+ this.addWrapper(elWrappers);
+ }
+
+ public AndELWrapper and(Object ... object){
+ ELWrapper[] wrapper = ELBus.convertToLogicOpt(object);
+ this.addWrapper(wrapper);
+ return this;
+ }
+
+ @Override
+ public AndELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public AndELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public AndELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public AndELWrapper data(String dataName, String jsonString) {
+ // 校验字符串符合Json格式
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public AndELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ protected AndELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ // 根据depth是否为null,决定输出是否格式化
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ processWrapperTabs(sb, depth);
+ sb.append("AND(");
+ processWrapperNewLine(sb, depth);
+ // 处理子表达式的输出并串接
+ for (int i = 0; i < this.getElWrapperList().size(); i++) {
+ if (i > 0){
+ sb.append(",");
+ processWrapperNewLine(sb, depth);
+ }
+ sb.append(this.getElWrapperList().get(i).toEL(sonDepth, paramContext));
+ }
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+
+ // 设置共有属性
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/CatchELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/CatchELWrapper.java
new file mode 100644
index 000000000..11a9b5226
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/CatchELWrapper.java
@@ -0,0 +1,103 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 捕获异常表达式
+ * Catch(a).do(b)
+ * catch()和do()只允许单个参数
+ * a,b非与或非表达式
+ *
+ * 支持设置 id tag data maxWaitSeconds 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class CatchELWrapper extends ELWrapper{
+
+ public CatchELWrapper(ELWrapper elWrapper){
+ this.addWrapper(elWrapper);
+ }
+
+ public CatchELWrapper doOpt(Object object){
+ ELWrapper elWrapper = ELBus.convertToNonLogicOpt(object);
+ this.addWrapper(elWrapper);
+ return this;
+ }
+
+ @Override
+ public CatchELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public CatchELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public CatchELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public CatchELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public CatchELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public CatchELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ // 处理 CATCH() 语句的输出
+ processWrapperTabs(sb, depth);
+ sb.append("CATCH(");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getElWrapperList().get(0).toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+
+ // 处理 DO()语句输出
+ if(this.getElWrapperList().size() > 1){
+ sb.append(".DO(");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getElWrapperList().get(1).toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+ }
+
+ // 处理共有属性输出
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ELBus.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ELBus.java
new file mode 100644
index 000000000..ee537de00
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ELBus.java
@@ -0,0 +1,316 @@
+package com.yomahub.liteflow.builder.el;
+
+import java.util.Arrays;
+
+/**
+ * ELBus
+ * 构建EL表达式的入口类
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class ELBus {
+
+ public static final String TAB = "\t";
+
+ /**
+ * 创建 then 串行组件
+ * 参数为ELWrapper
+ * @param elWrappers
+ * @return
+ */
+ public static ThenELWrapper then(ELWrapper ... elWrappers){
+ checkNotBooleanArgs(elWrappers);
+ return new ThenELWrapper(elWrappers);
+ }
+
+ public static ThenELWrapper then(Object ... objects){
+ ELWrapper[] elWrappers = convertToNonLogicOpt(objects);
+ return new ThenELWrapper(elWrappers);
+ }
+
+ /**
+ * 创建 when 并行组件
+ * @param elWrappers
+ * @return
+ */
+ public static WhenELWrapper when(ELWrapper ... elWrappers){
+ checkNotBooleanArgs(elWrappers);
+ return new WhenELWrapper(elWrappers);
+ }
+
+ public static WhenELWrapper when(Object ... objects){
+ ELWrapper[] elWrappers = convertToNonLogicOpt(objects);
+ return new WhenELWrapper(elWrappers);
+ }
+
+ /**
+ * 创建 if 条件判断表达式
+ * @param ifELWrapper
+ * @param trueELWrapper
+ * @param falseELWrapper
+ * @return
+ */
+ public static IfELWrapper ifOpt(NodeELWrapper ifELWrapper, Object trueELWrapper, Object falseELWrapper){
+ return new IfELWrapper(ifELWrapper, convertToNonLogicOpt(trueELWrapper), convertToNonLogicOpt(falseELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(String ifELWrapper, Object trueELWrapper, Object falseELWrapper){
+ return new IfELWrapper((NodeELWrapper) convertToLogicOpt(ifELWrapper), convertToNonLogicOpt(trueELWrapper), convertToNonLogicOpt(falseELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(AndELWrapper ifELWrapper, Object trueELWrapper, Object falseELWrapper){
+ return new IfELWrapper(ifELWrapper, convertToNonLogicOpt(trueELWrapper), convertToNonLogicOpt(falseELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(OrELWrapper ifELWrapper, Object trueELWrapper, Object falseELWrapper){
+ return new IfELWrapper(ifELWrapper, convertToNonLogicOpt(trueELWrapper), convertToNonLogicOpt(falseELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(NotELWrapper ifELWrapper, Object trueELWrapper, Object falseELWrapper){
+ return new IfELWrapper(ifELWrapper, convertToNonLogicOpt(trueELWrapper), convertToNonLogicOpt(falseELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(NodeELWrapper ifELWrapper, Object trueELWrapper){
+ return new IfELWrapper(ifELWrapper, convertToNonLogicOpt(trueELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(String ifELWrapper, Object trueELWrapper){
+ return new IfELWrapper((NodeELWrapper) convertToLogicOpt(ifELWrapper), convertToNonLogicOpt(trueELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(AndELWrapper ifELWrapper, Object trueELWrapper){
+ return new IfELWrapper(ifELWrapper, convertToNonLogicOpt(trueELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(OrELWrapper ifELWrapper, Object trueELWrapper){
+ return new IfELWrapper(ifELWrapper, convertToNonLogicOpt(trueELWrapper));
+ }
+
+ public static IfELWrapper ifOpt(NotELWrapper ifELWrapper, Object trueELWrapper){
+ return new IfELWrapper(ifELWrapper, convertToNonLogicOpt(trueELWrapper));
+ }
+
+ /**
+ * 创建 node 单节点表达式
+ * @param nodeId
+ * @return
+ */
+ public static NodeELWrapper node(String nodeId){
+ return new NodeELWrapper(nodeId);
+ }
+
+ /**
+ * 创建 switch 选择表达式
+ * @param nodeELWrapper
+ * @return
+ */
+ public static SwitchELWrapper switchOpt(NodeELWrapper nodeELWrapper){
+ return new SwitchELWrapper(nodeELWrapper);
+ }
+
+ public static SwitchELWrapper switchOpt(String nodeELWrapper){
+ return new SwitchELWrapper(convert(nodeELWrapper));
+ }
+
+ /**
+ * 创建 for 次数循环表达式
+ * @param loopNumber
+ * @return
+ */
+ public static ForELWrapper forOpt(Integer loopNumber){
+ return new ForELWrapper(loopNumber, "FOR");
+ }
+
+ public static ForELWrapper forOpt(NodeELWrapper nodeELWrapper){
+ return new ForELWrapper(nodeELWrapper, "FOR");
+ }
+
+ public static ForELWrapper forOpt(String nodeELWrapper){
+ return new ForELWrapper(convert(nodeELWrapper), "FOR");
+ }
+
+ /**
+ * 创建 while 条件循环表达式
+ * @param nodeELWrapper
+ * @return
+ */
+ public static WhileELWrapper whileOpt(NodeELWrapper nodeELWrapper){
+ return new WhileELWrapper(nodeELWrapper, "WHILE");
+ }
+
+ public static WhileELWrapper whileOpt(String nodeELWrapper){
+ return new WhileELWrapper(convert(nodeELWrapper), "WHILE");
+ }
+
+ public static WhileELWrapper whileOpt(AndELWrapper nodeELWrapper){
+ return new WhileELWrapper(nodeELWrapper, "WHILE");
+ }
+
+ public static WhileELWrapper whileOpt(OrELWrapper nodeELWrapper){
+ return new WhileELWrapper(nodeELWrapper, "WHILE");
+ }
+
+ public static WhileELWrapper whileOpt(NotELWrapper nodeELWrapper){
+ return new WhileELWrapper(nodeELWrapper, "WHILE");
+ }
+
+ /**
+ * 创建迭代循环表达式
+ * @param nodeELWrapper
+ * @return
+ */
+ public static IteratorELWrapper iteratorOpt(NodeELWrapper nodeELWrapper){
+ return new IteratorELWrapper(nodeELWrapper, "ITERATOR");
+ }
+
+ public static IteratorELWrapper iteratorOpt(String nodeELWrapper){
+ return new IteratorELWrapper(convert(nodeELWrapper), "ITERATOR");
+ }
+
+ /**
+ * 创建捕获异常表达式
+ * @param object
+ * @return
+ */
+ public static CatchELWrapper catchException(Object object){
+ return new CatchELWrapper(convertToNonLogicOpt(object));
+ }
+
+ /**
+ * 创建与表达式
+ * @param objects
+ * @return
+ */
+ public static AndELWrapper and(Object ... objects){
+ ELWrapper[] elWrappers = convertToLogicOpt(objects);
+ return new AndELWrapper(elWrappers);
+ }
+
+ /**
+ * 创建或表达式
+ * @param objects
+ * @return
+ */
+ public static OrELWrapper or(Object ... objects){
+ ELWrapper[] elWrappers = convertToLogicOpt(objects);
+ return new OrELWrapper(elWrappers);
+ }
+
+ /**
+ * 创建非表达式
+ * @param notElWrapper
+ * @return
+ */
+ public static NotELWrapper not(NodeELWrapper notElWrapper){
+ return new NotELWrapper(notElWrapper);
+ }
+
+ public static NotELWrapper not(String notElWrapper){
+ return new NotELWrapper(convert(notElWrapper));
+ }
+
+ public static NotELWrapper not(AndELWrapper notElWrapper){
+ return new NotELWrapper(notElWrapper);
+ }
+
+ public static NotELWrapper not(OrELWrapper notElWrapper){
+ return new NotELWrapper(notElWrapper);
+ }
+
+ public static NotELWrapper not(NotELWrapper notElWrapper){
+ return new NotELWrapper(notElWrapper);
+ }
+
+ /**
+ * 参数转换并校验参数是否为ELWrapper类型或者String类型
+ * @param objects
+ * @return
+ */
+ public static ELWrapper[] convert(Object... objects){
+ return Arrays.stream(objects).map(o -> {
+ if (o instanceof String) {
+ return new NodeELWrapper(o.toString());
+ } else if (o instanceof ELWrapper) {
+ return (ELWrapper) o;
+ } else {
+ throw new RuntimeException("param is error");
+ }
+ }).toArray(ELWrapper[]::new);
+ }
+
+ public static ELWrapper convert(Object object){
+ if (object instanceof String) {
+ return new NodeELWrapper(object.toString());
+ } else if (object instanceof ELWrapper) {
+ return (ELWrapper) object;
+ } else {
+ throw new RuntimeException("param is error");
+ }
+ }
+
+ /**
+ * 参数校验 只包含与或非的组件
+ * @param objects
+ * @return
+ */
+ public static ELWrapper[] convertToLogicOpt(Object... objects){
+ ELWrapper[] elWrappers = convert(objects);
+ checkBooleanArgs(elWrappers);
+ return elWrappers;
+ }
+
+ public static ELWrapper convertToLogicOpt(Object object){
+ ELWrapper elWrapper = convert(object);
+ checkBooleanArgs(elWrapper);
+ return elWrapper;
+ }
+
+ /**
+ * 参数校验 不包含与或非表达式的组件
+ * @param objects
+ * @return
+ */
+ public static ELWrapper[] convertToNonLogicOpt(Object ... objects){
+ ELWrapper[] elWrappers = convert(objects);
+ checkNotBooleanArgs(elWrappers);
+ return elWrappers;
+ }
+
+ public static ELWrapper convertToNonLogicOpt(Object object){
+ ELWrapper elWrapper = convert(object);
+ checkNotBooleanArgs(elWrapper);
+ return elWrapper;
+ }
+
+ /**
+ * 检查参数都不返回boolean值
+ * @param elWrappers
+ */
+ public static void checkNotBooleanArgs(ELWrapper ... elWrappers) {
+ for(ELWrapper elWrapper : elWrappers){
+ if(elWrapper instanceof AndELWrapper){
+ throw new RuntimeException("param is error");
+ } else if(elWrapper instanceof OrELWrapper){
+ throw new RuntimeException("param is error");
+ } else if(elWrapper instanceof NotELWrapper){
+ throw new RuntimeException("param is error");
+ }
+ }
+ }
+
+ /**
+ * 检查参数是否都能返回boolean值
+ * @param elWrappers
+ */
+ public static void checkBooleanArgs(ELWrapper ... elWrappers) {
+ for(ELWrapper elWrapper : elWrappers){
+ if(!(elWrapper instanceof AndELWrapper)
+ && !(elWrapper instanceof OrELWrapper)
+ && !(elWrapper instanceof NotELWrapper)
+ && !(elWrapper instanceof NodeELWrapper)){
+ throw new RuntimeException("param is error");
+ }
+ }
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ELWrapper.java
new file mode 100644
index 000000000..eb0ec0fda
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ELWrapper.java
@@ -0,0 +1,206 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ELWrapper是所有组件的抽象父类
+ * 定义所有EL表达式的公有变量 tag、id、data、maxWaitSeconds 以及 子表达式列表 ELWrapperList
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public abstract class ELWrapper {
+
+ private final List elWrapperList = new ArrayList<>();
+
+ private String tag;
+ private String id;
+ private String dataName;
+ private String data;
+ private Integer maxWaitSeconds;
+
+ protected void addWrapper(ELWrapper wrapper){
+ this.elWrapperList.add(wrapper);
+ }
+
+ protected void addWrapper(ELWrapper ... wrappers){
+ this.elWrapperList.addAll(Arrays.asList(wrappers));
+ }
+
+ protected void addWrapper(ELWrapper wrapper, int index){
+ this.elWrapperList.add(index, wrapper);
+ }
+
+ protected void setWrapper(ELWrapper wrapper, int index){
+ this.elWrapperList.set(index, wrapper);
+ }
+
+ protected ELWrapper getFirstWrapper(){
+ return this.elWrapperList.get(0);
+ }
+
+ protected List getElWrapperList(){
+ return this.elWrapperList;
+ }
+
+ protected void setTag(String tag){
+ this.tag = tag;
+ }
+
+ protected String getTag(){
+ return this.tag;
+ }
+
+ protected void setId(String id){
+ this.id = id;
+ }
+
+ protected String getId(){
+ return this.id;
+ }
+
+ protected void setData(String data){
+ this.data = data;
+ }
+
+ protected String getData(){
+ return this.data;
+ }
+
+ protected void setDataName(String dataName){
+ this.dataName = dataName;
+ }
+
+ protected String getDataName(){
+ return this.dataName;
+ }
+
+ protected void setMaxWaitSeconds(Integer maxWaitSeconds){
+ this.maxWaitSeconds = maxWaitSeconds;
+ }
+
+ protected Integer getMaxWaitSeconds(){
+ return this.maxWaitSeconds;
+ }
+
+ protected abstract ELWrapper tag(String tag);
+
+ protected abstract ELWrapper id(String id);
+
+ /**
+ * 设置data属性,参数为
+ * @param dataName
+ * @param object JavaBean
+ * @return
+ */
+ protected abstract ELWrapper data(String dataName, Object object);
+
+ /**
+ * 设置data属性,参数为
+ * @param dataName
+ * @param jsonString json格式字符串
+ * @return
+ */
+ protected abstract ELWrapper data(String dataName, String jsonString);
+
+ /**
+ * 设置data属性,参数为
+ * @param dataName
+ * @param jsonMap Map映射
+ * @return
+ */
+ protected abstract ELWrapper data(String dataName, Map jsonMap);
+
+ protected ELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ /**
+ * 输出EL表达式的默认方法
+ * 非格式化输出EL表达式
+ *
+ * @return {@link String}
+ */
+ public String toEL(){
+ StringBuilder paramContext = new StringBuilder();
+ String ELContext = toEL(null, paramContext);
+ return paramContext.append(ELContext).toString();
+ }
+
+ /**
+ * 是否格式化输出树形结构的规则表达式
+ *
+ * @param format 格式
+ * @return {@link String}
+ */
+ public String toEL(boolean format){
+ StringBuilder paramContext = new StringBuilder();
+ String ELContext;
+ if(!format){
+ ELContext = toEL(null, paramContext);
+ } else {
+ ELContext = toEL(0, paramContext);
+ }
+ return paramContext.append(ELContext).toString();
+ }
+
+ /**
+ * 格式化输出EL表达式
+ * @param depth 深度
+ * @param paramContext 参数输出内容,用于输出data属性
+ * @return
+ */
+ protected abstract String toEL(Integer depth, StringBuilder paramContext);
+
+ /**
+ * 处理EL表达式的属性
+ *
+ * @param elContext EL 输出内容
+ * @param paramContext 参数 输出内容
+ */
+ protected void processWrapperProperty(StringBuilder elContext, StringBuilder paramContext){
+ if(this.getId() != null){
+ elContext.append(StrUtil.format(".id(\"{}\")", this.getId()));
+ }
+ if(this.getTag() != null){
+ elContext.append(StrUtil.format(".tag(\"{}\")", this.getTag()));
+ }
+ if(this.getData() != null){
+ elContext.append(StrUtil.format(".data({})", this.getDataName()));
+ paramContext.append(StrUtil.format("{} = '{}';\n", this.getDataName(), this.getData()));
+ }
+ if(this.getMaxWaitSeconds() != null){
+ elContext.append(StrUtil.format(".maxWaitSeconds({})", String.valueOf(this.getMaxWaitSeconds())));
+ }
+ }
+
+ /**
+ * 处理格式化输出 EL表达式换行符
+ *
+ * @param elContext EL 上下文
+ * @param depth 深度
+ */
+ protected void processWrapperNewLine(StringBuilder elContext, Integer depth){
+ if(depth != null){
+ elContext.append("\n");
+ }
+ }
+
+ /**
+ * 处理格式化输出 EL表达式制表符
+ *
+ * @param elContext EL 上下文
+ * @param depth 深度
+ */
+ protected void processWrapperTabs(StringBuilder elContext, Integer depth){
+ if(depth != null) {
+ elContext.append(StrUtil.repeat(ELBus.TAB, depth));
+ }
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/FinallyELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/FinallyELWrapper.java
new file mode 100644
index 000000000..b23a1f564
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/FinallyELWrapper.java
@@ -0,0 +1,115 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 后置表达式
+ * 只能在THEN组件中调用
+ * 参数数量不限,类型不为与或非表达式
+ * 支持设置 tag、id、data 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class FinallyELWrapper extends ELWrapper{
+ public FinallyELWrapper(Object ... objects){
+ super.addWrapper(ELBus.convertToNonLogicOpt(objects));
+ }
+
+ @Override
+ public FinallyELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public FinallyELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public FinallyELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public FinallyELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public FinallyELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ /**
+ * 后置组件无法设置maxWaitSeconds属性,重载用protected修饰
+ * @param maxWaitSeconds
+ * @return
+ */
+ @Override
+ protected FinallyELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ processWrapperTabs(sb, depth);
+ sb.append("FINALLY(");
+ processWrapperNewLine(sb, depth);
+ // 处理子表达式输出
+ for (int i = 0; i < this.getElWrapperList().size(); i++) {
+ sb.append(this.getElWrapperList().get(i).toEL(sonDepth, paramContext));
+ if (i != this.getElWrapperList().size() - 1) {
+ sb.append(",");
+ processWrapperNewLine(sb, depth);
+ }
+ }
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+
+ // 处理共用属性
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+
+ /**
+ * FINALLY不允许maxWaitSeconds属性,重载父类
+ *
+ * @param elContext EL 上下文
+ * @param paramContext 参数上下文
+ */
+ @Override
+ protected void processWrapperProperty(StringBuilder elContext, StringBuilder paramContext){
+ if(this.getId() != null){
+ elContext.append(StrUtil.format(".id(\"{}\")", this.getId()));
+ }
+ if(this.getTag() != null){
+ elContext.append(StrUtil.format(".tag(\"{}\")", this.getTag()));
+ }
+ if(this.getData() != null){
+ elContext.append(StrUtil.format(".data({})", this.getDataName()));
+ paramContext.append(StrUtil.format("{} = '{}'\n", this.getDataName(), this.getData()));
+ }
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ForELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ForELWrapper.java
new file mode 100644
index 000000000..210540263
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ForELWrapper.java
@@ -0,0 +1,89 @@
+package com.yomahub.liteflow.builder.el;
+
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 次数循环表达式
+ * FOR只允许一个参数 参数为 Integer 或 返回循环次数的 EL表达式
+ * DO只允许一个参数 参数类型不为与或非表达式
+ * 支持调用break方法,参数为与或非表达式或返回true false的单节点
+ *
+ * 支持设置 id tag data maxWaitSeconds 以及 parallel 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class ForELWrapper extends LoopELWrapper{
+
+ public ForELWrapper(Integer loopNumber, String loopFunction){
+ super(loopNumber, loopFunction);
+ }
+
+ public ForELWrapper(ELWrapper elWrapper, String loopFunction){
+ super(elWrapper, loopFunction);
+ }
+
+ @Override
+ public ForELWrapper doOpt(Object object){
+ ELWrapper elWrapper = ELBus.convertToNonLogicOpt(object);
+ super.addWrapper(elWrapper, 1);
+ return this;
+ }
+
+ public ForELWrapper breakOpt(Object object){
+ ELWrapper elWrapper = ELBus.convertToLogicOpt(object);
+ super.addWrapper(elWrapper, 2);
+ return this;
+ }
+
+ public ForELWrapper parallel(boolean parallel){
+ setParallel(parallel);
+ return this;
+ }
+
+ @Override
+ public ForELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public ForELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public ForELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public ForELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public ForELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public ForELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/IfELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/IfELWrapper.java
new file mode 100644
index 000000000..f5bfbd0a8
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/IfELWrapper.java
@@ -0,0 +1,333 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 条件表达式
+ * 按照调用方法IF(a,b,c) IF(a,b).else(c) IF(a,b).ELIF(c,d)对应输出
+ * 支持设置 id tag data maxWaitSeconds 属性
+ * 支持二元或三元函数初始化
+ * 支持调用 else elif 方法
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class IfELWrapper extends ELWrapper{
+
+ /**
+ * 定义当前条件组件的输出格式
+ */
+ private static final int IF_FORMAT = 1;
+ private static final int IF_ELSE_FORMAT = 2;
+ private static final int ELIF_FORMAT = 3;
+
+ private int format;
+
+ /**
+ * 单节点作为判断条件
+ *
+ * @param ifWrapper 如果包装器
+ * @param trueWrapper 真正包装器
+ * @param falseWrapper 假包装器
+ */
+ public IfELWrapper(NodeELWrapper ifWrapper, ELWrapper trueWrapper, ELWrapper falseWrapper) {
+ this.setIfWrapper(ifWrapper);
+ this.setTrueWrapper(trueWrapper);
+ this.setFalseWrapper(falseWrapper);
+ this.format = IF_FORMAT;
+ }
+
+ /**
+ * 如果缠绕器
+ *
+ * @param ifWrapper 如果包装器
+ * @param trueWrapper 真正包装器
+ */
+ public IfELWrapper(NodeELWrapper ifWrapper, ELWrapper trueWrapper) {
+ this.setIfWrapper(ifWrapper);
+ this.setTrueWrapper(trueWrapper);
+ this.format = IF_ELSE_FORMAT;
+ }
+
+ /**
+ * 与节点作为判断条件
+ *
+ * @param andELWrapper 和缠绕器
+ * @param trueWrapper
+ * @param falseWrapper
+ */
+ public IfELWrapper(AndELWrapper andELWrapper, ELWrapper trueWrapper, ELWrapper falseWrapper) {
+ this.setIfWrapper(andELWrapper);
+ this.setTrueWrapper(trueWrapper);
+ this.setFalseWrapper(falseWrapper);
+ this.format = IF_FORMAT;
+ }
+
+ public IfELWrapper(AndELWrapper andELWrapper, ELWrapper trueWrapper){
+ this.setIfWrapper(andELWrapper);
+ this.setTrueWrapper(trueWrapper);
+ this.format = IF_ELSE_FORMAT;
+ }
+
+ /**
+ * 如果缠绕器
+ * 或节点作为判断条件
+ *
+ * @param andELWrapper 和缠绕器
+ * @param trueWrapper 真正包装器
+ * @param falseWrapper 假包装器
+ */
+ public IfELWrapper(OrELWrapper andELWrapper, ELWrapper trueWrapper, ELWrapper falseWrapper) {
+ this.setIfWrapper(andELWrapper);
+ this.setTrueWrapper(trueWrapper);
+ this.setFalseWrapper(falseWrapper);
+ this.format = IF_FORMAT;
+ }
+
+ public IfELWrapper(OrELWrapper andELWrapper, ELWrapper trueWrapper){
+ this.setIfWrapper(andELWrapper);
+ this.setTrueWrapper(trueWrapper);
+ this.format = IF_ELSE_FORMAT;
+ }
+
+ /**
+ * 非节点作为判断条件
+ * @param andELWrapper
+ * @param trueWrapper
+ * @param falseWrapper
+ */
+ public IfELWrapper(NotELWrapper andELWrapper, ELWrapper trueWrapper, ELWrapper falseWrapper) {
+ this.setIfWrapper(andELWrapper);
+ this.setTrueWrapper(trueWrapper);
+ this.setFalseWrapper(falseWrapper);
+ this.format = IF_FORMAT;
+ }
+
+ public IfELWrapper(NotELWrapper andELWrapper, ELWrapper trueWrapper){
+ this.setIfWrapper(andELWrapper);
+ this.setTrueWrapper(trueWrapper);
+ this.format = IF_ELSE_FORMAT;
+ }
+
+ /**
+ * else语句
+ * 设置最深层次条件表达式的 false分支的 表达式
+ *
+ * @param falseObject false分支
+ * @return {@link IfELWrapper}
+ */
+ public IfELWrapper elseOpt(Object falseObject){
+ ELWrapper falseWrapper = ELBus.convertToNonLogicOpt(falseObject);
+ // 找到最深层的if组件
+ ELWrapper prev = this;
+ ELWrapper succ = this;
+ // 设置最深层if组件false组件
+ while(prev instanceof IfELWrapper){
+ succ = prev;
+ prev = prev.getElWrapperList().size() >= 3 ? prev.getElWrapperList().get(2) : null;
+ }
+ ((IfELWrapper) succ).setFalseWrapper(falseWrapper);
+ return this;
+ }
+
+ /**
+ * elif语句
+ * 设置最深层次条件表达式的 判断表达式 和 true分支的 表达式
+ *
+ * @param ifObject 判断组件
+ * @param trueObject true分支
+ * @return {@link IfELWrapper}
+ */
+ public IfELWrapper elIfOpt(Object ifObject, Object trueObject) {
+ // 包装判断表达式和true分支组件
+ ELWrapper ifWrapper = ELBus.convertToLogicOpt(ifObject);
+ ELWrapper trueWrapper = ELBus.convertToNonLogicOpt(trueObject);
+ IfELWrapper elIfWrapper;
+ if(ifWrapper instanceof NodeELWrapper){
+ elIfWrapper = new IfELWrapper((NodeELWrapper) ifWrapper, trueWrapper);
+ } else if (ifWrapper instanceof AndELWrapper){
+ elIfWrapper = new IfELWrapper((AndELWrapper) ifWrapper, trueWrapper);
+ } else if (ifWrapper instanceof OrELWrapper){
+ elIfWrapper = new IfELWrapper((OrELWrapper) ifWrapper, trueWrapper);
+ } else if (ifWrapper instanceof NotELWrapper){
+ elIfWrapper = new IfELWrapper((NotELWrapper) ifWrapper, trueWrapper);
+ } else {
+ throw new RuntimeException("param error!");
+ }
+ elIfWrapper.setFormat(ELIF_FORMAT);
+ // 找到最深层的if组件
+ ELWrapper prev = this;
+ ELWrapper succ = this;
+ // 设置最深层的false分支为新建的条件表达式
+ while(prev instanceof IfELWrapper){
+ succ = prev;
+ prev = prev.getElWrapperList().size() >= 3 ? prev.getElWrapperList().get(2) : null;
+ }
+ ((IfELWrapper) succ).elseOpt(elIfWrapper);
+ return this;
+ }
+
+ private void setIfWrapper(ELWrapper ifWrapper){
+ this.addWrapper(ifWrapper, 0);
+ }
+
+ private ELWrapper getIfWrapper(){
+ return this.getElWrapperList().get(0);
+ }
+
+ private void setTrueWrapper(ELWrapper trueWrapper){
+ this.addWrapper(trueWrapper, 1);
+ }
+
+ private ELWrapper getTrueWrapper(){
+ return this.getElWrapperList().get(1);
+ }
+
+ private void setFalseWrapper(ELWrapper falseWrapper){
+ this.addWrapper(falseWrapper, 2);
+ }
+
+ protected void setFormat(int formatCode){
+ this.format = formatCode;
+ }
+
+ protected int getFormat(){
+ return this.format;
+ }
+
+ private ELWrapper getFalseWrapper(){
+ try{
+ return this.getElWrapperList().get(2);
+ }catch (Exception e){
+ return null;
+ }
+ }
+
+ @Override
+ public IfELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public IfELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public IfELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public IfELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public IfELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public IfELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ // 根据format不同分别按不同的格式输出
+ processWrapperTabs(sb, depth);
+ switch (this.format){
+ // IF(a,b,c) 三元表达式输出格式
+ case IF_FORMAT:
+ sb.append("IF(");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getIfWrapper().toEL(sonDepth, paramContext)).append(",");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getTrueWrapper().toEL(sonDepth, paramContext)).append(",");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getFalseWrapper().toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+ break;
+ // IF(a,b).ELSE(c) 二元表达式输出格式
+ case IF_ELSE_FORMAT:
+ sb.append("IF(");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getIfWrapper().toEL(sonDepth, paramContext)).append(",");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getTrueWrapper().toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+ processElseOutPut(depth, sonDepth, sb, paramContext);
+ break;
+ // IF(a,b).ELIF(c) ELIF输出格式
+ case ELIF_FORMAT:
+ // elif 树形结构输出
+ sb.append(".ELIF(");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getIfWrapper().toEL(sonDepth, paramContext)).append(",");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getTrueWrapper().toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+ processElseOutPut(depth, sonDepth, sb, paramContext);
+ break;
+ default:
+ break;
+ }
+
+ // 设置共有属性
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+
+ /**
+ * if(a,b) 和 elif(a,b) 的 else 处理方法相同
+ * 抽象出处理ELSE输出方法
+ *
+ * @param depth 深度
+ * @param sonDepth 儿子深度
+ * @param elContext EL 上下文
+ * @param paramContext 参数上下文
+ */
+ private void processElseOutPut(Integer depth, Integer sonDepth, StringBuilder elContext, StringBuilder paramContext){
+ if (ObjectUtil.isNotNull(this.getFalseWrapper())){
+ // 如果 使用ELIF 定义子表达式,则放到子表达式中处理
+ if(this.getFalseWrapper() instanceof IfELWrapper && ((IfELWrapper) this.getFalseWrapper()).getFormat() == ELIF_FORMAT){
+ elContext.append(this.getFalseWrapper().toEL(depth, paramContext));
+ } else {
+ // 如果使用 ELSE 处理 false分支表达式,则本层处理表达式输出
+ elContext.append(".ELSE(");
+ processWrapperNewLine(elContext, depth);
+ elContext.append(this.getFalseWrapper().toEL(sonDepth, paramContext));
+ processWrapperNewLine(elContext, depth);
+ processWrapperTabs(elContext, depth);
+ elContext.append(")");
+ }
+ }
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/IteratorELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/IteratorELWrapper.java
new file mode 100644
index 000000000..5ab3efa42
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/IteratorELWrapper.java
@@ -0,0 +1,77 @@
+package com.yomahub.liteflow.builder.el;
+
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 迭代循环表达式
+ * ITERATOR只允许一个参数 参数为 EL表达式
+ * DO只允许一个参数 参数类型不为与或非表达式
+ *
+ * 支持设置 id tag data maxWaitSeconds 以及 parallel 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class IteratorELWrapper extends LoopELWrapper{
+ public IteratorELWrapper(ELWrapper elWrapper, String loopFunction){
+ super(elWrapper, loopFunction);
+ }
+
+ public IteratorELWrapper parallel(boolean parallel){
+ setParallel(parallel);
+ return this;
+ }
+
+ @Override
+ public IteratorELWrapper doOpt(Object object){
+ ELWrapper elWrapper = ELBus.convertToNonLogicOpt(object);
+ super.addWrapper(elWrapper, 1);
+ return this;
+ }
+
+ @Override
+ public IteratorELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public IteratorELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public IteratorELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public IteratorELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public IteratorELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public IteratorELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/LoopELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/LoopELWrapper.java
new file mode 100644
index 000000000..3095eba1a
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/LoopELWrapper.java
@@ -0,0 +1,137 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * FOR、WHILE、ITERATOR循环表达式的公共抽象父类
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public abstract class LoopELWrapper extends ELWrapper{
+
+ protected Integer loopNumber;
+
+ /**
+ * 以loopFunction变量进行区分FOR、WHILE、ITERATOR
+ */
+ protected String loopFunction;
+
+ protected boolean parallel;
+
+ public LoopELWrapper(Integer loopNumber, String loopFunction){
+ this.loopNumber = loopNumber;
+ this.loopFunction = loopFunction;
+ this.addWrapper(null, 0);
+ }
+
+ public LoopELWrapper(ELWrapper elWrapper, String loopFunction){
+ this.loopFunction = loopFunction;
+ this.addWrapper(elWrapper, 0);
+ }
+
+ public LoopELWrapper doOpt(Object object){
+ ELWrapper elWrapper = ELBus.convertToNonLogicOpt(object);
+ this.addWrapper(elWrapper, 1);
+ return this;
+ }
+
+ protected void setParallel(boolean parallel){
+ this.parallel = parallel;
+ }
+
+ @Override
+ public LoopELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public LoopELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public LoopELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public LoopELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public LoopELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public LoopELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ // 设置循坏组件的类型以及循环节点
+ processWrapperTabs(sb, depth);
+ sb.append(loopFunction).append("(");
+ if(loopNumber != null){
+ sb.append(loopNumber.toString());
+ } else {
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getElWrapperList().get(0).toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ }
+ sb.append(")");
+
+ // 循环独有的并行语义
+ if(this.parallel){
+ sb.append(".parallel(true)");
+ }
+
+ // 设置循环组件输出
+ if(this.getElWrapperList().size() > 1) {
+ sb.append(".DO(");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getElWrapperList().get(1).toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+ }
+
+ // 设置退出循环组件输出
+ if(this.getElWrapperList().size() > 2){
+ sb.append(".BREAK(");
+ processWrapperNewLine(sb, depth);
+ sb.append(this.getElWrapperList().get(2).toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+ }
+
+ // 设置共有属性
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/NodeELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/NodeELWrapper.java
new file mode 100644
index 000000000..aefd9a003
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/NodeELWrapper.java
@@ -0,0 +1,122 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 单节点表达式
+ * 单节点也应以为一种表达式
+ * 支持设置 tag data maxWaitSeconds 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class NodeELWrapper extends ELWrapper {
+
+ private String nodeId;
+
+ private String tag;
+
+ public NodeELWrapper(String nodeId) {
+ this.nodeId = nodeId;
+ this.setNodeWrapper(this);
+ }
+
+ private void setNodeWrapper(ELWrapper elWrapper){
+ this.addWrapper(elWrapper, 0);
+ }
+
+ private NodeELWrapper getNodeWrapper(){
+ return (NodeELWrapper) this.getFirstWrapper();
+ }
+
+ protected String getNodeId() {
+ return nodeId;
+ }
+
+ protected void setNodeId(String nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ @Override
+ public NodeELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ /**
+ * 单节点不允许定义 id,重载为protected修饰
+ * @param id
+ * @return
+ */
+ @Override
+ protected NodeELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public NodeELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public NodeELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public NodeELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public NodeELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ NodeELWrapper nodeELWrapper = this.getNodeWrapper();
+ StringBuilder sb = new StringBuilder();
+ processWrapperTabs(sb, depth);
+ sb.append(StrUtil.format("node(\"{}\")", nodeELWrapper.getNodeId()));
+
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+
+ /**
+ * Node的公共属性不包括id,对父类方法重载。
+ *
+ * @param elContext EL 上下文
+ * @param paramContext 参数上下文
+ */
+ @Override
+ protected void processWrapperProperty(StringBuilder elContext, StringBuilder paramContext){
+ if(this.getTag() != null){
+ elContext.append(StrUtil.format(".tag(\"{}\")", this.getTag()));
+ }
+ if(this.getData() != null){
+ elContext.append(StrUtil.format(".data({})", this.getDataName()));
+ paramContext.append(StrUtil.format("{} = '{}'\n", this.getDataName(), this.getData()));
+ }
+ if(this.getMaxWaitSeconds() != null){
+ elContext.append(StrUtil.format(".maxWaitSeconds({})", String.valueOf(this.getMaxWaitSeconds())));
+ }
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/NotELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/NotELWrapper.java
new file mode 100644
index 000000000..58229a784
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/NotELWrapper.java
@@ -0,0 +1,84 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 与或非表达式中的 非表达式
+ * 参数只允许一个 参数必须返回true或false
+ *
+ * 支持设置 id tag data maxWaitSeconds 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class NotELWrapper extends ELWrapper{
+ public NotELWrapper(ELWrapper elWrapper){
+ this.addWrapper(elWrapper);
+ }
+
+ @Override
+ public NotELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public NotELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public NotELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public NotELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public NotELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public NotELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ processWrapperTabs(sb, depth);
+ sb.append("NOT(");
+ processWrapperNewLine(sb, depth);
+ // 处理子表达式输出
+ sb.append(this.getElWrapperList().get(0).toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+
+ // 设置公共属性
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/OrELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/OrELWrapper.java
new file mode 100644
index 000000000..c7dbb89c1
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/OrELWrapper.java
@@ -0,0 +1,98 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 与或非表达式中的 或表达式
+ * 参数允许任意数量 参数必须返回true或false
+ *
+ * 使用or()方法加入新的表达式
+ * 支持设置 id tag data maxWaitSeconds 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class OrELWrapper extends ELWrapper{
+
+ public OrELWrapper(ELWrapper ... elWrappers){
+ this.addWrapper(elWrappers);
+ }
+
+ public OrELWrapper or(Object ... object){
+ ELWrapper[] elWrapper = ELBus.convertToLogicOpt(object);
+ this.addWrapper(elWrapper);
+ return this;
+ }
+
+ @Override
+ public OrELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public OrELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public OrELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public OrELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public OrELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public OrELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ processWrapperTabs(sb, depth);
+ sb.append("OR(");
+ processWrapperNewLine(sb, depth);
+ // 处理子表达式输出
+ for (int i = 0; i < this.getElWrapperList().size(); i++) {
+ if (i > 0){
+ sb.append(",");
+ processWrapperNewLine(sb, depth);
+ }
+ sb.append(this.getElWrapperList().get(i).toEL(sonDepth, paramContext));
+ }
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+
+ // 处理公共属性输出
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/PreELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/PreELWrapper.java
new file mode 100644
index 000000000..781c38c66
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/PreELWrapper.java
@@ -0,0 +1,90 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 前置表达式
+ * 只能在THEN组件中调用
+ * 参数数量不限,类型不为与或非表达式
+ * 支持设置 tag、id、data、maxWaitSeconds 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class PreELWrapper extends ELWrapper{
+ public PreELWrapper(Object ... objects){
+ super.addWrapper(ELBus.convert(objects));
+ }
+
+ @Override
+ public PreELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public PreELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public PreELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public PreELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public PreELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public PreELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ processWrapperTabs(sb, depth);
+ sb.append("PRE(");
+ processWrapperNewLine(sb, depth);
+ // 处理子表达式输出
+ for (int i = 0; i < this.getElWrapperList().size(); i++) {
+ sb.append(this.getElWrapperList().get(i).toEL(sonDepth, paramContext));
+ if (i != this.getElWrapperList().size() - 1) {
+ sb.append(",");
+ processWrapperNewLine(sb, depth);
+ }
+ }
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+
+ // 处理公共属性输出
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/SwitchELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/SwitchELWrapper.java
new file mode 100644
index 000000000..c9f03d840
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/SwitchELWrapper.java
@@ -0,0 +1,121 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 选择组件
+ * SWITCH(a).TO(b,c,d...).default(x)
+ * SWITCH只允许单个参数,类型为非与或非表达式
+ * TO允许任意个参数,类型为非与或非表达式
+ * DEFAULT只允许单个参数,类型为非与或非表达式
+ *
+ * 支持定义 id tag data maxWaitSeconds 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class SwitchELWrapper extends ELWrapper{
+ /**
+ * default语句的表达式
+ */
+ private ELWrapper defaultELWrapper;
+
+ public SwitchELWrapper(ELWrapper elWrapper){
+ this.addWrapper(elWrapper, 0);
+ }
+
+ public SwitchELWrapper to(Object... objects){
+ ELWrapper[] elWrappers = ELBus.convertToNonLogicOpt(objects);
+ this.addWrapper(elWrappers);
+ return this;
+ }
+
+ public SwitchELWrapper defaultOpt(Object object){
+ defaultELWrapper = ELBus.convertToNonLogicOpt(object);
+ return this;
+ }
+
+ @Override
+ public SwitchELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public SwitchELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public SwitchELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public SwitchELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public SwitchELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public SwitchELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ processWrapperTabs(sb, depth);
+ sb.append(StrUtil.format("SWITCH({})", this.getFirstWrapper().toEL(null, paramContext)));
+ // 处理子表达式输出
+ if(this.getElWrapperList().size() > 1) {
+ sb.append(".TO(");
+ processWrapperNewLine(sb, depth);
+ for (int i = 1; i < this.getElWrapperList().size(); i++) {
+ sb.append(this.getElWrapperList().get(i).toEL(sonDepth, paramContext));
+ if (i != this.getElWrapperList().size() - 1) {
+ sb.append(",");
+ processWrapperNewLine(sb, depth);
+ }
+ }
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+ }
+ // default可以不存在
+ if(defaultELWrapper != null){
+ sb.append(".DEFAULT(");
+ processWrapperNewLine(sb, depth);
+ sb.append(defaultELWrapper.toEL(sonDepth, paramContext));
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+ }
+
+ // 处理表达式的共有属性
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ThenELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ThenELWrapper.java
new file mode 100644
index 000000000..89aa8409f
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/ThenELWrapper.java
@@ -0,0 +1,149 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 串行组件
+ * 允许调用PRE、FINALLY任意次
+ * 参数数量任意,参数类型为非与或非表达式
+ *
+ * 支持定义 id tag data maxWaitSeconds属性
+ *
+ * @author gezuao
+ * @date 2023/10/10
+ * @since 2.11.1
+ */
+public class ThenELWrapper extends ELWrapper {
+ private final List preELWrapperList;
+ private final List finallyELWrapperList;
+
+ public ThenELWrapper(ELWrapper ... elWrappers) {
+ preELWrapperList = new ArrayList<>();
+ finallyELWrapperList = new ArrayList<>();
+ this.addWrapper(elWrappers);
+ }
+
+ public ThenELWrapper then(Object ... objects){
+ ELWrapper[] elWrappers = ELBus.convertToNonLogicOpt(objects);
+ // 校验与或非表达式
+ this.addWrapper(elWrappers);
+ return this;
+ }
+
+ protected void addPreELWrapper(PreELWrapper preELWrapper){
+ this.preELWrapperList.add(preELWrapper);
+ }
+
+ protected void addFinallyELWrapper(FinallyELWrapper finallyELWrapper){
+ this.finallyELWrapperList.add(finallyELWrapper);
+ }
+
+ /**
+ * 定义子前置组件
+ * @param objects
+ * @return
+ */
+ public ThenELWrapper pre(Object ... objects){
+ addPreELWrapper(new PreELWrapper(objects));
+ return this;
+ }
+
+ /**
+ * 定义子后置组件
+ * @param objects
+ * @return
+ */
+ public ThenELWrapper finallyOpt(Object ... objects){
+ addFinallyELWrapper(new FinallyELWrapper(objects));
+ return this;
+ }
+
+ @Override
+ public ThenELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public ThenELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ // data关键字的约束:允许以Bean、jsonString、map类型输入数据,必须包含dataName参数。
+ @Override
+ public ThenELWrapper data(String dataName, Object javaBean) {
+ setData(JsonUtil.toJsonString(javaBean));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public ThenELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public ThenELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public ThenELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ processWrapperTabs(sb, depth);
+ sb.append("THEN(");
+ processWrapperNewLine(sb, depth);
+
+ // 处理前置组件输出
+ for (PreELWrapper preELWrapper : this.preELWrapperList) {
+ sb.append(StrUtil.format("{},", preELWrapper.toEL(sonDepth, paramContext)));
+ processWrapperNewLine(sb, depth);
+ }
+ // 处理子表达式输出
+ for (int i = 0; i < this.getElWrapperList().size(); i++) {
+ if (i > 0){
+ sb.append(",");
+ processWrapperNewLine(sb, depth);
+ }
+ sb.append(this.getElWrapperList().get(i).toEL(sonDepth, paramContext));
+ }
+ // 处理后置组件输出
+ for (FinallyELWrapper finallyELWrapper : this.finallyELWrapperList) {
+ sb.append(",");
+ processWrapperNewLine(sb, depth);
+ sb.append(finallyELWrapper.toEL(sonDepth, paramContext));
+ }
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+
+ // 处理公共属性输出
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+
+
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhenELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhenELWrapper.java
new file mode 100644
index 000000000..7994e80f6
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhenELWrapper.java
@@ -0,0 +1,154 @@
+package com.yomahub.liteflow.builder.el;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.*;
+
+/**
+ * 并行组件
+ * 参数数量任意
+ * 参数类型非与或非表达式
+ *
+ * 支持定义 id tag data maxWaitSeconds 属性
+ * 支持调用 any ignoreError customThreadExecutor mustExecuteList 并行组件特有方法
+ * any 和 must语义冲突,不支持同时定义
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class WhenELWrapper extends ELWrapper {
+
+ private boolean any;
+ private boolean ignoreError;
+ private String customThreadExecutor;
+ private final List mustExecuteList;
+
+ public WhenELWrapper(ELWrapper ... elWrappers) {
+ this.addWrapper(elWrappers);
+ this.mustExecuteList = new ArrayList<>();
+ }
+
+ public WhenELWrapper when(Object ... objects){
+ ELWrapper[] elWrappers = ELBus.convertToNonLogicOpt(objects);
+ // 校验与或非表达式
+ this.addWrapper(elWrappers);
+ return this;
+ }
+
+ public WhenELWrapper any(boolean any) {
+ this.any = any;
+ return this;
+ }
+
+ public WhenELWrapper ignoreError(boolean ignoreError) {
+ this.ignoreError = ignoreError;
+ return this;
+ }
+
+ public WhenELWrapper customThreadExecutor(String customThreadExecutor){
+ this.customThreadExecutor = customThreadExecutor;
+ return this;
+ }
+
+ public WhenELWrapper must(String ... mustExecuteWrappers){
+ this.mustExecuteList.addAll(Arrays.asList(mustExecuteWrappers));
+ return this;
+ }
+
+ @Override
+ public WhenELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public WhenELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public WhenELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public WhenELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public WhenELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public WhenELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+
+ @Override
+ protected String toEL(Integer depth, StringBuilder paramContext) {
+ Integer sonDepth = depth == null ? null : depth + 1;
+ StringBuilder sb = new StringBuilder();
+
+ processWrapperTabs(sb, depth);
+ sb.append("WHEN(");
+ processWrapperNewLine(sb, depth);
+ // 处理子表达式输出
+ for (int i = 0; i < this.getElWrapperList().size(); i++) {
+ if (i > 0){
+ sb.append(",");
+ processWrapperNewLine(sb, depth);
+ }
+ sb.append(this.getElWrapperList().get(i).toEL(sonDepth, paramContext));
+ }
+ processWrapperNewLine(sb, depth);
+ processWrapperTabs(sb, depth);
+ sb.append(")");
+
+ // WHEN的私有语义输出
+ if (this.any){
+ sb.append(".any(true)");
+ }
+ if(this.ignoreError){
+ sb.append(".ignoreError(true)");
+ }
+ if(StrUtil.isNotBlank(customThreadExecutor)){
+ sb.append(StrUtil.format(".threadPool(\"{}\")", customThreadExecutor));
+ }
+ if(CollectionUtil.isNotEmpty(mustExecuteList)){
+ // 校验must 语义与 any语义冲突
+ if (this.any){
+ throw new IllegalArgumentException("'.must()' and '.any()' can use in when component at the same time!");
+ }
+ // 处理must子表达式输出
+ sb.append(".must(");
+ for(int i = 0; i < mustExecuteList.size(); i++){
+ if(i > 0){
+ sb.append(", ");
+ }
+ sb.append(StrUtil.format("\"{}\"", mustExecuteList.get(i)));
+ }
+ sb.append(")");
+ }
+
+ // 处理公共属性输出
+ processWrapperProperty(sb, paramContext);
+ return sb.toString();
+ }
+}
diff --git a/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhileELWrapper.java b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhileELWrapper.java
new file mode 100644
index 000000000..e90b13a0d
--- /dev/null
+++ b/liteflow-el-builder/src/main/java/com/yomahub/liteflow/builder/el/WhileELWrapper.java
@@ -0,0 +1,84 @@
+package com.yomahub.liteflow.builder.el;
+
+import com.yomahub.liteflow.util.JsonUtil;
+
+import java.util.Map;
+
+/**
+ * 条件循环表达式
+ * WHILE只允许一个参数 参数为 返回布尔值的EL表达式
+ * DO只允许一个参数 参数类型不为与或非表达式
+ * 支持调用break方法,参数为与或非表达式或返回true false的单节点
+ *
+ * 支持设置 id tag data maxWaitSeconds 以及 parallel 属性
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+public class WhileELWrapper extends LoopELWrapper{
+ public WhileELWrapper(ELWrapper elWrapper, String loopFunction){
+ super(elWrapper, loopFunction);
+ }
+
+ public WhileELWrapper parallel(boolean parallel){
+ setParallel(parallel);
+ return this;
+ }
+
+ @Override
+ public WhileELWrapper doOpt(Object object){
+ ELWrapper elWrapper = ELBus.convertToNonLogicOpt(object);
+ super.addWrapper(elWrapper, 1);
+ return this;
+ }
+
+ public WhileELWrapper breakOpt(Object object){
+ ELWrapper elWrapper = ELBus.convertToLogicOpt(object);
+ super.addWrapper(elWrapper, 2);
+ return this;
+ }
+
+ @Override
+ public WhileELWrapper tag(String tag) {
+ this.setTag(tag);
+ return this;
+ }
+
+ @Override
+ public WhileELWrapper id(String id) {
+ this.setId(id);
+ return this;
+ }
+
+ @Override
+ public WhileELWrapper data(String dataName, Object object) {
+ setData(JsonUtil.toJsonString(object));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public WhileELWrapper data(String dataName, String jsonString) {
+ try {
+ JsonUtil.parseObject(jsonString);
+ } catch (Exception e){
+ throw new RuntimeException("字符串不符合Json格式!");
+ }
+ setData(jsonString);
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public WhileELWrapper data(String dataName, Map jsonMap) {
+ setData(JsonUtil.toJsonString(jsonMap));
+ setDataName(dataName);
+ return this;
+ }
+
+ @Override
+ public WhileELWrapper maxWaitSeconds(Integer maxWaitSeconds){
+ setMaxWaitSeconds(maxWaitSeconds);
+ return this;
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/pom.xml b/liteflow-testcase-el/liteflow-testcase-el-builder/pom.xml
new file mode 100644
index 000000000..466807454
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/pom.xml
@@ -0,0 +1,56 @@
+
+
+
+ liteflow-testcase-el
+ com.yomahub
+ ${revision}
+ ../pom.xml
+
+ 4.0.0
+
+ liteflow-testcase-el-builder
+
+
+
+ com.yomahub
+ liteflow-spring-boot-starter
+ ${revision}
+
+
+ com.yomahub
+ liteflow-el-builder
+ ${revision}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+ org.aspectj
+ aspectjweaver
+ test
+
+
+ org.apache.curator
+ curator-test
+ test
+
+
+ com.101tec
+ zkclient
+ test
+
+
+ org.apache.curator
+ curator-framework
+
+
+ org.apache.curator
+ curator-recipes
+
+
+
+
\ No newline at end of file
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/BaseTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/BaseTest.java
new file mode 100644
index 000000000..6f5819b99
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/BaseTest.java
@@ -0,0 +1,23 @@
+package com.yomahub.liteflow.test;
+
+import com.yomahub.liteflow.core.FlowInitHook;
+import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner;
+import com.yomahub.liteflow.spring.ComponentScanner;
+import com.yomahub.liteflow.thread.ExecutorHelper;
+import org.junit.jupiter.api.AfterAll;
+
+public class BaseTest {
+
+ @AfterAll
+ public static void cleanScanCache() {
+ ComponentScanner.cleanCache();
+ FlowBus.cleanCache();
+ ExecutorHelper.loadInstance().clearExecutorServiceMap();
+ SpiFactoryCleaner.clean();
+ LiteflowConfigGetter.clean();
+ FlowInitHook.cleanHook();
+ }
+
+}
\ No newline at end of file
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/CatchELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/CatchELBuilderTest.java
new file mode 100644
index 000000000..cd6e1f7cd
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/CatchELBuilderTest.java
@@ -0,0 +1,119 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 捕获异常组件测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = CatchELBuilderTest.class)
+@EnableAutoConfiguration
+public class CatchELBuilderTest extends BaseTest {
+ // catch捕获异常调用测试
+ @Test
+ public void testCatch1(){
+ String actualStr = "CATCH(THEN(node(\"a\"),node(\"b\"))).DO(node(\"c\"))";
+ Assertions.assertEquals(ELBus.catchException(ELBus.then("a", "b")).doOpt("c").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testCatch2(){
+ String actualStr = "CATCH(\n\tTHEN(\n\t\tnode(\"a\"),\n\t\tnode(\"b\")\n\t)\n).DO(\n\tnode(\"c\")\n)";
+ Assertions.assertEquals(ELBus.catchException(ELBus.then("a", "b")).doOpt("c").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 属性设置测试
+ @Test
+ public void testCatch3(){
+ String actualStr = "CATCH(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).id(\"this is a id\").tag(\"this is a tag\").maxWaitSeconds(3)";
+ Assertions.assertEquals(ELBus.catchException("a").doOpt(ELBus.then("b", "c")).id("this is a id").tag("this is a tag").maxWaitSeconds(3).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testCatch4(){
+ String actualStr = "CATCH(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).id(\"this is a id\").tag(\"this is a tag\").maxWaitSeconds(3)";
+ Assertions.assertEquals(ELBus.catchException("a").doOpt(ELBus.then("b", "c")).id("this is a id").tag("this is a tag").maxWaitSeconds(3).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // data 设置 jsonStr
+ @Test
+ public void testCatch5(){
+ String actualStr = "catchData = '{\"name\":\"zhangsan\",\"age\":18}';\nCATCH(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(catchData)";
+ Assertions.assertEquals(ELBus.catchException("a").doOpt(ELBus.then("b", "c")).data("catchData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testCatch6(){
+ String actualStr = "catchData = '{\"name\":\"zhangsan\",\"age\":18}';\nCATCH(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(catchData)";
+ Assertions.assertEquals(ELBus.catchException("a").doOpt(ELBus.then("b", "c")).data("catchData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // data 设置 map
+ @Test
+ public void testCatch7(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "catchData = '{\"name\":\"zhangsan\",\"age\":18}';\nCATCH(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(catchData)";
+ Assertions.assertEquals(ELBus.catchException("a").doOpt(ELBus.then("b", "c")).data("catchData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testCatch8(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "catchData = '{\"name\":\"zhangsan\",\"age\":18}';\nCATCH(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(catchData)";
+ Assertions.assertEquals(ELBus.catchException("a").doOpt(ELBus.then("b", "c")).data("catchData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ private static class ParamClass{
+ private String name;
+ private Integer age;
+ public String getName(){
+ return name;
+ }
+ public Integer getAge(){
+ return age;
+ }
+ }
+ // data 设置 bean
+ @Test
+ public void testCatch9(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "catchData = '{\"name\":\"zhangsan\",\"age\":18}';\nCATCH(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(catchData)";
+ Assertions.assertEquals(ELBus.catchException("a").doOpt(ELBus.then("b", "c")).data("catchData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testCatch10(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "catchData = '{\"name\":\"zhangsan\",\"age\":18}';\nCATCH(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(catchData)";
+ Assertions.assertEquals(ELBus.catchException("a").doOpt(ELBus.then("b", "c")).data("catchData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/ComplexELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/ComplexELBuilderTest.java
new file mode 100644
index 000000000..bcfc824db
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/ComplexELBuilderTest.java
@@ -0,0 +1,120 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.builder.el.ThenELWrapper;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+/**
+ * 复杂编排例子测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = ComplexELBuilderTest.class)
+@EnableAutoConfiguration
+public class ComplexELBuilderTest extends BaseTest {
+ /*
+ 复杂编排例子1
+ THEN(
+ A,
+ WHEN(
+ THEN(B, C),
+ THEN(D, E, F),
+ THEN(
+ SWITCH(G).to(
+ THEN(H, I, WHEN(J, K)).id("t1"),
+ THEN(L, M).id("t2")
+ ),
+ N
+ )
+ ),
+ Z
+ );
+ */
+ @Test
+ public void testComplexEL1() {
+ ThenELWrapper complexEl1 = ELBus.then(
+ ELBus.node("A"),
+ ELBus.when(
+ ELBus.then("B", "C"),
+ ELBus.then(ELBus.node("D")).then("E").then("F"),
+ ELBus.then(
+ ELBus.switchOpt("G").to(
+ ELBus.then("H", ELBus.node("I"), ELBus.when("J").when("K")).id("t1"),
+ ELBus.then("L", "M").id("t2")
+ ),
+ "N"
+ )
+ ),
+ "Z"
+ );
+ String actualStr = "THEN(node(\"A\"),WHEN(THEN(node(\"B\"),node(\"C\")),THEN(node(\"D\"),node(\"E\"),node(\"F\")),THEN(SWITCH(node(\"G\")).TO(THEN(node(\"H\"),node(\"I\"),WHEN(node(\"J\"),node(\"K\"))).id(\"t1\"),THEN(node(\"L\"),node(\"M\")).id(\"t2\")),node(\"N\"))),node(\"Z\"))";
+ Assertions.assertEquals(complexEl1.toEL(),
+ actualStr);
+ System.out.println(actualStr);
+
+ actualStr = "THEN(\n\tnode(\"A\"),\n\tWHEN(\n\t\tTHEN(\n\t\t\tnode(\"B\"),\n\t\t\tnode(\"C\")\n\t\t),\n\t\tTHEN(\n\t\t\tnode(\"D\"),\n\t\t\tnode(\"E\"),\n\t\t\tnode(\"F\")\n\t\t),\n\t\tTHEN(\n\t\t\tSWITCH(node(\"G\")).TO(\n\t\t\t\tTHEN(\n\t\t\t\t\tnode(\"H\"),\n\t\t\t\t\tnode(\"I\"),\n\t\t\t\t\tWHEN(\n\t\t\t\t\t\tnode(\"J\"),\n\t\t\t\t\t\tnode(\"K\")\n\t\t\t\t\t)\n\t\t\t\t).id(\"t1\"),\n\t\t\t\tTHEN(\n\t\t\t\t\tnode(\"L\"),\n\t\t\t\t\tnode(\"M\")\n\t\t\t\t).id(\"t2\")\n\t\t\t),\n\t\t\tnode(\"N\")\n\t\t)\n\t),\n\tnode(\"Z\")\n)";
+ Assertions.assertEquals(complexEl1.toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+
+ }
+
+ /*
+ 复杂编排例子2
+ THEN(
+ A,
+ SWITCH(B).to(
+ THEN(D, E, F).id("t1"),
+ THEN(
+ C,
+ WHEN(
+ THEN(
+ SWITCH(G).to(THEN(H, I).id("t2"), J),
+ K
+ ),
+ THEN(L, M)
+ )
+ ).id("t3")
+ ),
+ Z
+ );
+ */
+ @Test
+ public void testComplexEl2(){
+ ThenELWrapper complexEl2 = ELBus.then(
+ ELBus.node("A"),
+ ELBus.switchOpt(ELBus.node("B")).to(
+ ELBus.then("D","E").then(ELBus.node("F")).id("t1"),
+ ELBus.then(
+ ELBus.node("C"),
+ ELBus.when(
+ ELBus.then(
+ ELBus.switchOpt("G").to(
+ ELBus.then("H", "I").id("t2"),
+ "J"
+ ),
+ "K"
+ ),
+ ELBus.then("L", "M")
+ )
+ ).id("t3")
+ ),
+ ELBus.node("Z")
+ );
+ String actualStr = "THEN(node(\"A\"),SWITCH(node(\"B\")).TO(THEN(node(\"D\"),node(\"E\"),node(\"F\")).id(\"t1\"),THEN(node(\"C\"),WHEN(THEN(SWITCH(node(\"G\")).TO(THEN(node(\"H\"),node(\"I\")).id(\"t2\"),node(\"J\")),node(\"K\")),THEN(node(\"L\"),node(\"M\")))).id(\"t3\")),node(\"Z\"))";
+ Assertions.assertEquals(complexEl2.toEL(),
+ actualStr);
+ System.out.println(actualStr);
+
+ actualStr = "THEN(\n\tnode(\"A\"),\n\tSWITCH(node(\"B\")).TO(\n\t\tTHEN(\n\t\t\tnode(\"D\"),\n\t\t\tnode(\"E\"),\n\t\t\tnode(\"F\")\n\t\t).id(\"t1\"),\n\t\tTHEN(\n\t\t\tnode(\"C\"),\n\t\t\tWHEN(\n\t\t\t\tTHEN(\n\t\t\t\t\tSWITCH(node(\"G\")).TO(\n\t\t\t\t\t\tTHEN(\n\t\t\t\t\t\t\tnode(\"H\"),\n\t\t\t\t\t\t\tnode(\"I\")\n\t\t\t\t\t\t).id(\"t2\"),\n\t\t\t\t\t\tnode(\"J\")\n\t\t\t\t\t),\n\t\t\t\t\tnode(\"K\")\n\t\t\t\t),\n\t\t\t\tTHEN(\n\t\t\t\t\tnode(\"L\"),\n\t\t\t\t\tnode(\"M\")\n\t\t\t\t)\n\t\t\t)\n\t\t).id(\"t3\")\n\t),\n\tnode(\"Z\")\n)";
+ Assertions.assertEquals(complexEl2.toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/IfELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/IfELBuilderTest.java
new file mode 100644
index 000000000..e457fd1c4
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/IfELBuilderTest.java
@@ -0,0 +1,285 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 条件组件测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = IfELBuilderTest.class)
+@EnableAutoConfiguration
+public class IfELBuilderTest extends BaseTest {
+ // if三元函数测试
+ @Test
+ public void testIf1(){
+ String actualStr = "IF(node(\"a\"),THEN(node(\"c\"),node(\"d\")),WHEN(node(\"e\"),node(\"f\")))";
+ Assertions.assertEquals(ELBus.ifOpt("a", ELBus.then("c", "d"), ELBus.when("e", "f")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testIf2(){
+ String actualStr = "IF(\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"c\"),\n\t\tnode(\"d\")\n\t),\n\tWHEN(\n\t\tnode(\"e\"),\n\t\tnode(\"f\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.node("a"), ELBus.then("c", "d"), ELBus.when("e", "f")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // If二元函数测试
+ @Test
+ public void testIf3(){
+ String actualStr = "IF(node(\"a\"),THEN(node(\"b\"),node(\"c\"))).ELSE(WHEN(node(\"c\"),node(\"d\")))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.node("a"), ELBus.then("b", "c")).elseOpt(ELBus.when("c", "d")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testIf4(){
+ String actualStr = "IF(\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).ELSE(\n\tWHEN(\n\t\tnode(\"c\"),\n\t\tnode(\"d\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.ifOpt("a", ELBus.then("b", "c")).elseOpt(ELBus.when("c", "d")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // ELIF调用测试
+ @Test
+ public void testIf5(){
+ String actualStr = "IF(node(\"a\"),node(\"b\")).ELIF(node(\"f1\"),node(\"c\")).ELIF(node(\"f2\"),node(\"d\")).ELSE(node(\"e\"))";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b").elIfOpt("f1", "c").elIfOpt("f2","d").elseOpt("e").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testIf6(){
+ String actualStr = "IF(\n\tnode(\"a\"),\n\tnode(\"b\")\n).ELIF(\n\tnode(\"f1\"),\n\tnode(\"c\")\n).ELIF(\n\tnode(\"f2\"),\n\tnode(\"d\")\n).ELSE(\n\tnode(\"e\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b").elIfOpt("f1", "c").elIfOpt("f2","d").elseOpt("e").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // IF嵌套调用测试
+ @Test
+ public void testIf7(){
+ String actualStr = "IF(node(\"a\"),node(\"b\"),IF(node(\"c\"),node(\"d\")).ELSE(node(\"e\")))";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", ELBus.ifOpt("c", "d").elseOpt("e")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testIf8(){
+ String actualStr = "IF(\n\tnode(\"a\"),\n\tnode(\"b\"),\n\tIF(\n\t\tnode(\"c\"),\n\t\tnode(\"d\")\n\t).ELSE(\n\t\tnode(\"e\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", ELBus.ifOpt("c", "d").elseOpt("e")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // IF嵌套调用测试
+ @Test
+ public void testIf9(){
+ String actualStr = "IF(node(\"a\"),node(\"b\")).ELSE(IF(node(\"c\"),node(\"d\"),node(\"e\")))";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b").elseOpt(ELBus.ifOpt("c", "d", "e")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testIf10(){
+ String actualStr = "IF(\n\tnode(\"a\"),\n\tnode(\"b\")\n).ELSE(\n\tIF(\n\t\tnode(\"c\"),\n\t\tnode(\"d\"),\n\t\tnode(\"e\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b").elseOpt(ELBus.ifOpt("c", "d", "e")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 与表达式输出测试
+ @Test
+ public void testIf11(){
+ String actualStr = "IF(AND(node(\"a\"),node(\"b\"),node(\"c\")),node(\"d\"),node(\"e\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.and("a", "b", "c"), "d", "e").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(AND(node(\"a\"),node(\"b\"),node(\"c\")),node(\"d\")).ELSE(node(\"e\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.and("a", "b", "c"), "d").elseOpt("e").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(AND(node(\"a\"),node(\"b\"),node(\"c\")),node(\"d\")).ELIF(AND(node(\"f1\"),node(\"f2\")),node(\"e\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.and("a", "b", "c"), "d").elIfOpt(ELBus.and("f1", "f2"), "e").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testIf12(){
+ String actualStr = "IF(\n\tAND(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\"),\n\tnode(\"e\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.and("a", "b", "c"), "d", "e").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(\n\tAND(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n).ELSE(\n\tnode(\"e\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.and("a", "b", "c"), "d").elseOpt("e").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(\n\tAND(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n).ELIF(\n\tAND(\n\t\tnode(\"f1\"),\n\t\tnode(\"f2\")\n\t),\n\tnode(\"e\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.and("a", "b", "c"), "d").elIfOpt(ELBus.and("f1", "f2"), "e").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 或表达式测试
+ @Test
+ public void testIf13(){
+ String actualStr = "IF(OR(node(\"a\"),node(\"b\"),node(\"c\")),node(\"d\"),node(\"e\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.or("a", "b", "c"), "d", "e").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(OR(node(\"a\"),node(\"b\"),node(\"c\")),node(\"d\")).ELSE(node(\"e\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.or("a", "b", "c"), "d").elseOpt("e").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(OR(node(\"a\"),node(\"b\"),node(\"c\")),node(\"d\")).ELIF(OR(node(\"f1\"),node(\"f2\")),node(\"e\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.or("a", "b", "c"), "d").elIfOpt(ELBus.or("f1", "f2"), "e").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testIf14(){
+ String actualStr = "IF(\n\tOR(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\"),\n\tnode(\"e\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.or("a", "b", "c"), "d", "e").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(\n\tOR(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n).ELSE(\n\tnode(\"e\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.or("a", "b", "c"), "d").elseOpt("e").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(\n\tOR(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n).ELIF(\n\tOR(\n\t\tnode(\"f1\"),\n\t\tnode(\"f2\")\n\t),\n\tnode(\"e\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.or("a", "b", "c"), "d").elIfOpt(ELBus.or("f1", "f2"), "e").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 非表达式测试
+ @Test
+ public void testIf15(){
+ String actualStr = "IF(NOT(node(\"a\")),node(\"b\"),node(\"c\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.not("a"), "b", "c").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(NOT(node(\"a\")),node(\"b\")).ELSE(node(\"c\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.not("a"), "b").elseOpt("c").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(NOT(node(\"a\")),node(\"b\")).ELIF(NOT(node(\"f\")),node(\"c\"))";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.not("a"), "b").elIfOpt(ELBus.not("f"), "c").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testIf16(){
+ String actualStr = "IF(\n\tNOT(\n\t\tnode(\"a\")\n\t),\n\tnode(\"b\"),\n\tnode(\"c\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.not("a"), "b", "c").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(\n\tNOT(\n\t\tnode(\"a\")\n\t),\n\tnode(\"b\")\n).ELSE(\n\tnode(\"c\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.not("a"), "b").elseOpt("c").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "IF(\n\tNOT(\n\t\tnode(\"a\")\n\t),\n\tnode(\"b\")\n).ELIF(\n\tNOT(\n\t\tnode(\"f\")\n\t),\n\tnode(\"c\")\n)";
+ Assertions.assertEquals(ELBus.ifOpt(ELBus.not("a"), "b").elIfOpt(ELBus.not("f"), "c").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 属性测试
+ @Test
+ public void testIf17(){
+ String actualStr = "IF(node(\"a\"),node(\"b\"),node(\"c\")).id(\"this is a id\").tag(\"this is a tag\").maxWaitSeconds(6)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", "c").id("this is a id").tag("this is a tag").maxWaitSeconds(6).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出
+ @Test
+ public void testIf18(){
+ String actualStr = "IF(\n\tnode(\"a\"),\n\tnode(\"b\"),\n\tnode(\"c\")\n).id(\"this is a id\").tag(\"this is a tag\").maxWaitSeconds(6)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", "c").id("this is a id").tag("this is a tag").maxWaitSeconds(6).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // data map 测试
+ @Test
+ public void testIf19(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "ifData = '{\"name\":\"zhangsan\",\"age\":18}';\nIF(node(\"a\"),node(\"b\"),node(\"c\")).data(ifData)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", "c").data("ifData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出
+ @Test
+ public void testIf20(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "ifData = '{\"name\":\"zhangsan\",\"age\":18}';\nIF(\n\tnode(\"a\"),\n\tnode(\"b\"),\n\tnode(\"c\")\n).data(ifData)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", "c").data("ifData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // data JsonStr 测试
+ @Test
+ public void testIf21(){
+ String actualStr = "ifData = '{\"name\":\"zhangsan\",\"age\":18}';\nIF(node(\"a\"),node(\"b\"),node(\"c\")).data(ifData)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", "c").data("ifData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出
+ @Test
+ public void testIf22(){
+ String actualStr = "ifData = '{\"name\":\"zhangsan\",\"age\":18}';\nIF(\n\tnode(\"a\"),\n\tnode(\"b\"),\n\tnode(\"c\")\n).data(ifData)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", "c").data("ifData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ private static class ParamClass{
+ private String name;
+ private Integer age;
+ public String getName(){
+ return name;
+ }
+ public Integer getAge(){
+ return age;
+ }
+ }
+ // data Bean 测试
+ @Test
+ public void testIf23(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "ifData = '{\"name\":\"zhangsan\",\"age\":18}';\nIF(node(\"a\"),node(\"b\"),node(\"c\")).data(ifData)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", "c").data("ifData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出
+ @Test
+ public void testIf24(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "ifData = '{\"name\":\"zhangsan\",\"age\":18}';\nIF(\n\tnode(\"a\"),\n\tnode(\"b\"),\n\tnode(\"c\")\n).data(ifData)";
+ Assertions.assertEquals(ELBus.ifOpt("a", "b", "c").data("ifData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/LogicELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/LogicELBuilderTest.java
new file mode 100644
index 000000000..f38b22873
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/LogicELBuilderTest.java
@@ -0,0 +1,171 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 与或非表达式测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = LogicELBuilderTest.class)
+@EnableAutoConfiguration
+public class LogicELBuilderTest extends BaseTest {
+ // 与或非表达式调用 测试
+ @Test
+ public void testlogic1(){
+ String actualStr = "AND(node(\"a\"),OR(node(\"b\"),node(\"c\")),NOT(node(\"d\")))";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c"), ELBus.not("d")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testlogic2(){
+ String actualStr = "AND(\n\tnode(\"a\"),\n\tOR(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tNOT(\n\t\tnode(\"d\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c"), ELBus.not("d")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ @Test
+ public void testlogic3(){
+ String actualStr = "AND(node(\"a\"),OR(node(\"b\"),node(\"c\")),NOT(node(\"d\")))";
+ Assertions.assertEquals(ELBus.and("a").and(ELBus.or("b").or("c")).and(ELBus.not("d")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ @Test
+ public void testlogic4(){
+ String actualStr = "AND(\n\tnode(\"a\"),\n\tOR(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tNOT(\n\t\tnode(\"d\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.and("a").and(ELBus.or("b").or("c")).and(ELBus.not("d")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 属性设置
+ @Test
+ public void testlogic5(){
+ String actualStr = "AND(node(\"a\"),OR(node(\"b\"),node(\"c\")).id(\"this is a id\").maxWaitSeconds(4),NOT(node(\"d\")).tag(\"this is a tag\"))";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c").id("this is a id").maxWaitSeconds(4), ELBus.not("d").tag("this is a tag")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testlogic6(){
+ String actualStr = "AND(\n\tnode(\"a\"),\n\tOR(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\").maxWaitSeconds(4),\n\tNOT(\n\t\tnode(\"d\")\n\t).tag(\"this is a tag\")\n)";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c").id("this is a id").maxWaitSeconds(4), ELBus.not("d").tag("this is a tag")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testlogic7(){
+ String actualStr = "andData = '{\"name\":\"zhangsan\",\"age\":18}';\nAND(node(\"a\"),OR(node(\"b\"),node(\"c\")),NOT(node(\"d\"))).data(andData)";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c"), ELBus.not("d")).data("andData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testlogic8(){
+ String actualStr = "andData = '{\"name\":\"zhangsan\",\"age\":18}';\nAND(\n\tnode(\"a\"),\n\tOR(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tNOT(\n\t\tnode(\"d\")\n\t)\n).data(andData)";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c"), ELBus.not("d")).data("andData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testlogic9(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "orData = '{\"name\":\"zhangsan\",\"age\":18}';\nAND(node(\"a\"),OR(node(\"b\"),node(\"c\")),NOT(node(\"d\"))).data(orData)";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c"), ELBus.not("d")).data("orData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testlogic10(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "orData = '{\"name\":\"zhangsan\",\"age\":18}';\nAND(\n\tnode(\"a\"),\n\tOR(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tNOT(\n\t\tnode(\"d\")\n\t)\n).data(orData)";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c"), ELBus.not("d")).data("orData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ private static class ParamClass{
+ private String name;
+ private Integer age;
+ public String getName(){
+ return name;
+ }
+ public Integer getAge(){
+ return age;
+ }
+ }
+ @Test
+ public void testlogic11(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "notData = '{\"name\":\"zhangsan\",\"age\":18}';\nAND(node(\"a\"),OR(node(\"b\"),node(\"c\")),NOT(node(\"d\")).data(notData))";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c"), ELBus.not("d").data("notData", name2Value)).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testlogic12(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "notData = '{\"name\":\"zhangsan\",\"age\":18}';\nAND(\n\tnode(\"a\"),\n\tOR(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tNOT(\n\t\tnode(\"d\")\n\t).data(notData)\n)";
+ Assertions.assertEquals(ELBus.and("a", ELBus.or("b", "c"), ELBus.not("d").data("notData", name2Value)).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // NOT调用方法补充测试
+ @Test
+ public void testLogic13(){
+ String actualStr = "NOT(node(\"a\"))";
+ Assertions.assertEquals(ELBus.not(ELBus.node("a")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "NOT(AND(node(\"a\"),node(\"b\"),node(\"c\")))";
+ Assertions.assertEquals(ELBus.not(ELBus.and("a", "b", "c")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "NOT(OR(node(\"a\"),node(\"b\"),node(\"c\")))";
+ Assertions.assertEquals(ELBus.not(ELBus.or("a", "b", "c")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "NOT(NOT(node(\"a\")))";
+ Assertions.assertEquals(ELBus.not(ELBus.not(ELBus.node("a"))).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testLogic14(){
+ String actualStr = "NOT(\n\tnode(\"a\")\n)";
+ Assertions.assertEquals(ELBus.not(ELBus.node("a")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "NOT(\n\tAND(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.not(ELBus.and("a", "b", "c")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "NOT(\n\tOR(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.not(ELBus.or("a", "b", "c")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "NOT(\n\tNOT(\n\t\tnode(\"a\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.not(ELBus.not(ELBus.node("a"))).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/LoopELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/LoopELBuilderTest.java
new file mode 100644
index 000000000..9bb06c5e6
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/LoopELBuilderTest.java
@@ -0,0 +1,278 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 循环组件测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = LoopELBuilderTest.class)
+@EnableAutoConfiguration
+public class LoopELBuilderTest extends BaseTest {
+ // for 限定次数循环
+ @Test
+ public void testLoop1(){
+ String actualStr = "FOR(3).DO(THEN(node(\"a\"),node(\"b\"),node(\"c\"))).BREAK(node(\"d\"))";
+ Assertions.assertEquals(ELBus.forOpt(3).doOpt(ELBus.then("a", "b", "c")).breakOpt("d").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出
+ @Test
+ public void testLoop2(){
+ String actualStr = "FOR(3).DO(\n\tTHEN(\n\t\tnode(\"a\"),\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).BREAK(\n\tnode(\"d\")\n)";
+ Assertions.assertEquals(ELBus.forOpt(3).doOpt(ELBus.then("a", "b", "c")).breakOpt("d").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // for 单节点循环测试
+ @Test
+ public void testLoop3(){
+ String actualStr = "FOR(node(\"a\")).DO(WHEN(node(\"b\"),node(\"c\"),node(\"d\"))).BREAK(AND(node(\"e\"),node(\"f\")))";
+ Assertions.assertEquals(ELBus.forOpt("a").doOpt(ELBus.when("b", "c", "d")).breakOpt(ELBus.and("e", "f")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testLoop4(){
+ String actualStr = "FOR(\n\tnode(\"a\")\n).DO(\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\"),\n\t\tnode(\"d\")\n\t)\n).BREAK(\n\tAND(\n\t\tnode(\"e\"),\n\t\tnode(\"f\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.forOpt(ELBus.node("a")).doOpt(ELBus.when("b", "c", "d")).breakOpt(ELBus.and("e", "f")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // parallel语句测试
+ @Test
+ public void testLoop5(){
+ String actualStr = "FOR(node(\"a\")).parallel(true).DO(WHEN(node(\"b\"),node(\"c\"),node(\"d\"))).BREAK(node(\"e\"))";
+ Assertions.assertEquals(ELBus.forOpt("a").doOpt(ELBus.when("b", "c", "d")).breakOpt("e").parallel(true).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testLoop6(){
+ String actualStr = "FOR(\n\tnode(\"a\")\n).parallel(true).DO(\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\"),\n\t\tnode(\"d\")\n\t)\n).BREAK(\n\tnode(\"e\")\n)";
+ Assertions.assertEquals(ELBus.forOpt("a").doOpt(ELBus.when("b", "c", "d")).breakOpt("e").parallel(true).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 属性测试
+ @Test
+ public void testLoop7(){
+ String actualStr = "forData = '{\"name\":\"zhangsan\",\"age\":18}';\nFOR(node(\"a\")).DO(WHEN(node(\"b\"),node(\"c\"),node(\"d\"))).BREAK(node(\"e\")).id(\"this is a id\").tag(\"this is a tag\").data(forData).maxWaitSeconds(3)";
+ Assertions.assertEquals(ELBus.forOpt("a").doOpt(ELBus.when("b", "c", "d")).breakOpt("e").id("this is a id").tag("this is a tag").maxWaitSeconds(3).data("forData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testLoop8(){
+ String actualStr = "forData = '{\"name\":\"zhangsan\",\"age\":18}';\nFOR(\n\tnode(\"a\")\n).DO(\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\"),\n\t\tnode(\"d\")\n\t)\n).BREAK(\n\tnode(\"e\")\n).id(\"this is a id\").tag(\"this is a tag\").data(forData).maxWaitSeconds(3)";
+ Assertions.assertEquals(ELBus.forOpt(ELBus.node("a")).doOpt(ELBus.when("b", "c", "d")).breakOpt("e").id("this is a id").tag("this is a tag").maxWaitSeconds(3).data("forData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // while调用测试
+ @Test
+ public void testLoop9(){
+ String actualStr = "WHILE(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).BREAK(node(\"f\"))";
+ Assertions.assertEquals(ELBus.whileOpt("a").doOpt(ELBus.then("b", "c")).breakOpt("f").toEL(),
+ actualStr);
+ Assertions.assertEquals(ELBus.whileOpt(ELBus.node("a")).doOpt(ELBus.then("b", "c")).breakOpt("f").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "WHILE(AND(node(\"a\"),node(\"b\"))).DO(node(\"c\")).BREAK(node(\"d\"))";
+ Assertions.assertEquals(ELBus.whileOpt(ELBus.and("a", "b")).doOpt("c").breakOpt("d").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "WHILE(OR(node(\"a\"),node(\"b\"))).DO(node(\"c\")).BREAK(node(\"d\"))";
+ Assertions.assertEquals(ELBus.whileOpt(ELBus.or("a", "b")).doOpt("c").breakOpt("d").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "WHILE(NOT(node(\"a\"))).DO(node(\"c\")).BREAK(node(\"d\"))";
+ Assertions.assertEquals(ELBus.whileOpt(ELBus.not("a")).doOpt("c").breakOpt("d").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testLoop10(){
+ String actualStr = "WHILE(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).BREAK(\n\tnode(\"f\")\n)";
+ Assertions.assertEquals(ELBus.whileOpt("a").doOpt(ELBus.then("b", "c")).breakOpt("f").toEL(true),
+ actualStr);
+ Assertions.assertEquals(ELBus.whileOpt(ELBus.node("a")).doOpt(ELBus.then("b", "c")).breakOpt("f").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "WHILE(\n\tAND(\n\t\tnode(\"a\"),\n\t\tnode(\"b\")\n\t)\n).DO(\n\tnode(\"c\")\n).BREAK(\n\tnode(\"d\")\n)";
+ Assertions.assertEquals(ELBus.whileOpt(ELBus.and("a", "b")).doOpt("c").breakOpt("d").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "WHILE(\n\tOR(\n\t\tnode(\"a\"),\n\t\tnode(\"b\")\n\t)\n).DO(\n\tnode(\"c\")\n).BREAK(\n\tnode(\"d\")\n)";
+ Assertions.assertEquals(ELBus.whileOpt(ELBus.or("a", "b")).doOpt("c").breakOpt("d").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "WHILE(\n\tNOT(\n\t\tnode(\"a\")\n\t)\n).DO(\n\tnode(\"c\")\n).BREAK(\n\tnode(\"d\")\n)";
+ Assertions.assertEquals(ELBus.whileOpt(ELBus.not("a")).doOpt("c").breakOpt("d").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // while属性调用测试
+ @Test
+ public void testLoop11(){
+ String actualStr = "whileData = '{\"name\":\"zhangsan\",\"age\":18}';\nWHILE(node(\"a\")).parallel(true).DO(THEN(node(\"b\"),node(\"c\"))).BREAK(node(\"d\")).id(\"this is a ig\").tag(\"this is a tag\").data(whileData).maxWaitSeconds(3)";
+ Assertions.assertEquals(ELBus.whileOpt("a").doOpt(ELBus.then("b", "c")).breakOpt("d").id("this is a ig").tag("this is a tag").maxWaitSeconds(3).parallel(true).data("whileData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testLoop12(){
+ String actualStr = "whileData = '{\"name\":\"zhangsan\",\"age\":18}';\nWHILE(\n\tnode(\"a\")\n).parallel(true).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).BREAK(\n\tnode(\"d\")\n).id(\"this is a ig\").tag(\"this is a tag\").data(whileData).maxWaitSeconds(3)";
+ Assertions.assertEquals(ELBus.whileOpt("a").doOpt(ELBus.then("b", "c")).breakOpt("d").id("this is a ig").tag("this is a tag").maxWaitSeconds(3).parallel(true).data("whileData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // Iterator 调用测试
+ @Test
+ public void testLoop13(){
+ String actualStr = "ITERATOR(node(\"a\")).DO(WHEN(node(\"b\"),node(\"c\")))";
+ Assertions.assertEquals(ELBus.iteratorOpt("a").doOpt(ELBus.when("b", "c")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "ITERATOR(node(\"a\")).DO(WHEN(node(\"b\"),node(\"c\")))";
+ Assertions.assertEquals(ELBus.iteratorOpt(ELBus.node("a")).doOpt(ELBus.when("b", "c")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testLoop14(){
+ String actualStr = "ITERATOR(\n\tnode(\"a\")\n).DO(\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.iteratorOpt("a").doOpt(ELBus.when("b", "c")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "ITERATOR(\n\tnode(\"a\")\n).DO(\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.iteratorOpt(ELBus.node("a")).doOpt(ELBus.when("b", "c")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // iterator 属性测试
+ @Test
+ public void testLoop15(){
+ String actualStr = "iteratorData = '{\"name\":\"zhangsan\",\"age\":18}';\nITERATOR(node(\"a\")).parallel(true).DO(THEN(node(\"b\"),node(\"c\"))).id(\"this is a ig\").tag(\"this is a tag\").data(iteratorData).maxWaitSeconds(3)";
+ Assertions.assertEquals(ELBus.iteratorOpt("a").doOpt(ELBus.then("b", "c")).id("this is a ig").tag("this is a tag").maxWaitSeconds(3).parallel(true).data("iteratorData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testLoop16(){
+ String actualStr = "iteratorData = '{\"name\":\"zhangsan\",\"age\":18}';\nITERATOR(\n\tnode(\"a\")\n).parallel(true).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).id(\"this is a ig\").tag(\"this is a tag\").data(iteratorData).maxWaitSeconds(3)";
+ Assertions.assertEquals(ELBus.iteratorOpt("a").doOpt(ELBus.then("b", "c")).id("this is a ig").tag("this is a tag").maxWaitSeconds(3).parallel(true).data("iteratorData", "{\"name\":\"zhangsan\",\"age\":18}").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // data Map 参数 测试
+ @Test
+ public void testLoop17(){
+ Map name2Value = new HashMap<>();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "forData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "FOR(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(forData)";
+ Assertions.assertEquals(ELBus.forOpt("a").doOpt(ELBus.then("b", "c")).data("forData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "whileData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "WHILE(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(whileData)";
+ Assertions.assertEquals(ELBus.whileOpt("a").doOpt(ELBus.then("b", "c")).data("whileData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "iteratorData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "ITERATOR(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(iteratorData)";
+ Assertions.assertEquals(ELBus.iteratorOpt("a").doOpt(ELBus.then("b", "c")).data("iteratorData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ @Test
+ public void testLoop18(){
+ Map name2Value = new HashMap<>();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "forData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "FOR(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(forData)";
+ Assertions.assertEquals(ELBus.forOpt("a").doOpt(ELBus.then("b", "c")).data("forData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "whileData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "WHILE(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(whileData)";
+ Assertions.assertEquals(ELBus.whileOpt("a").doOpt(ELBus.then("b", "c")).data("whileData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "iteratorData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "ITERATOR(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(iteratorData)";
+ Assertions.assertEquals(ELBus.iteratorOpt("a").doOpt(ELBus.then("b", "c")).data("iteratorData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ private static class ParamClass{
+ private String name;
+ private Integer age;
+ public String getName(){
+ return name;
+ }
+ public Integer getAge(){
+ return age;
+ }
+ }
+ // data JavaBean参数 测试
+ @Test
+ public void testLoop19(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.age = 18;
+ name2Value.name = "zhangsan";
+ String actualStr = "forData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "FOR(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(forData)";
+ Assertions.assertEquals(ELBus.forOpt("a").doOpt(ELBus.then("b", "c")).data("forData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "whileData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "WHILE(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(whileData)";
+ Assertions.assertEquals(ELBus.whileOpt("a").doOpt(ELBus.then("b", "c")).data("whileData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "iteratorData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "ITERATOR(node(\"a\")).DO(THEN(node(\"b\"),node(\"c\"))).data(iteratorData)";
+ Assertions.assertEquals(ELBus.iteratorOpt("a").doOpt(ELBus.then("b", "c")).data("iteratorData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ @Test
+ public void testLoop20(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.age = 18;
+ name2Value.name = "zhangsan";
+ String actualStr = "forData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "FOR(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(forData)";
+ Assertions.assertEquals(ELBus.forOpt("a").doOpt(ELBus.then("b", "c")).data("forData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "whileData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "WHILE(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(whileData)";
+ Assertions.assertEquals(ELBus.whileOpt("a").doOpt(ELBus.then("b", "c")).data("whileData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ actualStr = "iteratorData = '{\"name\":\"zhangsan\",\"age\":18}';\n" +
+ "ITERATOR(\n\tnode(\"a\")\n).DO(\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t)\n).data(iteratorData)";
+ Assertions.assertEquals(ELBus.iteratorOpt("a").doOpt(ELBus.then("b", "c")).data("iteratorData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/NodeELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/NodeELBuilderTest.java
new file mode 100644
index 000000000..dd0244a33
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/NodeELBuilderTest.java
@@ -0,0 +1,101 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.builder.el.NodeELWrapper;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 单节点组件测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = NodeELBuilderTest.class)
+@EnableAutoConfiguration
+public class NodeELBuilderTest extends BaseTest {
+ @Test
+ public void testNodeEL1(){
+ String jsonStr = "{\"name\":\"zhangsan\",\"age\":18}";
+ String actualStr = "nodeData = '{\"name\":\"zhangsan\",\"age\":18}'\n" +
+ "node(\"a\").tag(\"node a tag\").data(nodeData).maxWaitSeconds(4)";
+ NodeELWrapper node = ELBus.node("a").maxWaitSeconds(4).tag("node a tag").data("nodeData", jsonStr);
+ Assertions.assertEquals(node.toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testNodeEL2(){
+ String jsonStr = "{\"name\":\"zhangsan\",\"age\":18}";
+ String actualStr = "nodeData = '{\"name\":\"zhangsan\",\"age\":18}'\n" +
+ "node(\"a\").tag(\"node a tag\").data(nodeData).maxWaitSeconds(4)";
+ NodeELWrapper node = ELBus.node("a").maxWaitSeconds(4).tag("node a tag").data("nodeData", jsonStr);
+ Assertions.assertEquals(node.toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testNodeEL3(){
+ Map name2Value = new HashMap<>();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "nodeData = '{\"name\":\"zhangsan\",\"age\":18}'\n" +
+ "node(\"a\").tag(\"node a tag\").data(nodeData).maxWaitSeconds(4)";
+ NodeELWrapper node = ELBus.node("a").maxWaitSeconds(4).tag("node a tag").data("nodeData", name2Value);
+ Assertions.assertEquals(node.toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testNodeEL4(){
+ Map name2Value = new HashMap<>();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "nodeData = '{\"name\":\"zhangsan\",\"age\":18}'\n" +
+ "node(\"a\").tag(\"node a tag\").data(nodeData).maxWaitSeconds(4)";
+ NodeELWrapper node = ELBus.node("a").maxWaitSeconds(4).tag("node a tag").data("nodeData", name2Value);
+ Assertions.assertEquals(node.toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ private static class ParamClass{
+ private String name;
+ private Integer age;
+ public String getName(){
+ return name;
+ }
+ public Integer getAge(){
+ return age;
+ }
+ }
+ @Test
+ public void testNodeEL5(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.age = 18;
+ name2Value.name = "zhangsan";
+ String actualStr = "nodeData = '{\"name\":\"zhangsan\",\"age\":18}'\n" +
+ "node(\"a\").tag(\"node a tag\").data(nodeData).maxWaitSeconds(4)";
+ NodeELWrapper node = ELBus.node("a").maxWaitSeconds(4).tag("node a tag").data("nodeData", name2Value);
+ Assertions.assertEquals(node.toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ @Test
+ public void testNodeEL6(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.age = 18;
+ name2Value.name = "zhangsan";
+ String actualStr = "nodeData = '{\"name\":\"zhangsan\",\"age\":18}'\n" +
+ "node(\"a\").tag(\"node a tag\").data(nodeData).maxWaitSeconds(4)";
+ NodeELWrapper node = ELBus.node("a").maxWaitSeconds(4).tag("node a tag").data("nodeData", name2Value);
+ Assertions.assertEquals(node.toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/SwitchELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/SwitchELBuilderTest.java
new file mode 100644
index 000000000..34091c68d
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/SwitchELBuilderTest.java
@@ -0,0 +1,151 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.test.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 选择组件测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = SwitchELBuilderTest.class)
+@EnableAutoConfiguration
+public class SwitchELBuilderTest extends BaseTest {
+
+ // Switch调用方法测试
+ @Test
+ public void testSwitch1(){
+ String actualStr = "SWITCH(node(\"a\")).TO(node(\"b\"),node(\"c\"),node(\"d\")).DEFAULT(node(\"f\"))";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").defaultOpt("f").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ // 格式化输出测试
+ @Test
+ public void testSwitch2(){
+ String actualStr = "SWITCH(node(\"a\")).TO(\n\tnode(\"b\"),\n\tnode(\"c\"),\n\tnode(\"d\")\n).DEFAULT(\n\tnode(\"f\")\n)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").defaultOpt("f").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ // switch和THEN when嵌套调用测试
+ @Test
+ public void testSwitch3(){
+ String actualStr = "SWITCH(node(\"a\")).TO(node(\"b\"),THEN(node(\"c\"),node(\"d\")),WHEN(node(\"e\"),node(\"f\"))).DEFAULT(THEN(node(\"g\"),node(\"h\")))";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", ELBus.then("c", "d"), ELBus.when("e", "f")).defaultOpt(ELBus.then("g", "h")).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ // 格式化输出测试
+ @Test
+ public void testSwitch4(){
+ String actualStr = "SWITCH(node(\"a\")).TO(\n\tnode(\"b\"),\n\tTHEN(\n\t\tnode(\"c\"),\n\t\tnode(\"d\")\n\t),\n\tWHEN(\n\t\tnode(\"e\"),\n\t\tnode(\"f\")\n\t)\n).DEFAULT(\n\tTHEN(\n\t\tnode(\"g\"),\n\t\tnode(\"h\")\n\t)\n)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", ELBus.then("c", "d"), ELBus.when("e", "f")).defaultOpt(ELBus.then("g", "h")).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ // 属性设置测试
+ @Test
+ public void testSwitch5(){
+ String actualStr = "SWITCH(node(\"a\")).TO(node(\"b\"),node(\"c\"),node(\"d\")).id(\"this is a id\").tag(\"this is a tag\").maxWaitSeconds(5)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").id("this is a id").tag("this is a tag").maxWaitSeconds(5).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ // 格式化输出测试
+ @Test
+ public void testSwitch6(){
+ String actualStr = "SWITCH(node(\"a\")).TO(\n\tnode(\"b\"),\n\tnode(\"c\"),\n\tnode(\"d\")\n).id(\"this is a id\").tag(\"this is a tag\").maxWaitSeconds(5)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").id("this is a id").tag("this is a tag").maxWaitSeconds(5).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ // data属性测试
+ @Test
+ public void testSwitch7(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "switchData = '{\"name\":\"zhangsan\",\"age\":18}';\nSWITCH(node(\"a\")).TO(node(\"b\"),node(\"c\"),node(\"d\")).data(switchData)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").data("switchData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ @Test
+ public void testSwitch8(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "switchData = '{\"name\":\"zhangsan\",\"age\":18}';\nSWITCH(node(\"a\")).TO(\n\tnode(\"b\"),\n\tnode(\"c\"),\n\tnode(\"d\")\n).data(switchData)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").data("switchData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ @Test
+ public void testSwitch9(){
+ String jsonStr = "{\"name\":\"zhangsan\",\"age\":18}";
+ String actualStr = "switchData = '{\"name\":\"zhangsan\",\"age\":18}';\nSWITCH(node(\"a\")).TO(node(\"b\"),node(\"c\"),node(\"d\")).data(switchData)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").data("switchData", jsonStr).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ @Test
+ public void testSwitch10(){
+ String jsonStr = "{\"name\":\"zhangsan\",\"age\":18}";
+ String actualStr = "switchData = '{\"name\":\"zhangsan\",\"age\":18}';\nSWITCH(node(\"a\")).TO(\n\tnode(\"b\"),\n\tnode(\"c\"),\n\tnode(\"d\")\n).data(switchData)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").data("switchData", jsonStr).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ private static class ParamClass{
+ private String name;
+ private Integer age;
+ public String getName(){
+ return name;
+ }
+ public Integer getAge(){
+ return age;
+ }
+ }
+
+ @Test
+ public void testSwitch11(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "switchData = '{\"name\":\"zhangsan\",\"age\":18}';\nSWITCH(node(\"a\")).TO(node(\"b\"),node(\"c\"),node(\"d\")).data(switchData)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").data("switchData", name2Value).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+ @Test
+ public void testSwitch12(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "switchData = '{\"name\":\"zhangsan\",\"age\":18}';\nSWITCH(node(\"a\")).TO(\n\tnode(\"b\"),\n\tnode(\"c\"),\n\tnode(\"d\")\n).data(switchData)";
+ Assertions.assertEquals(ELBus.switchOpt("a").to("b", "c", "d").data("switchData", name2Value).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/ThenELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/ThenELBuilderTest.java
new file mode 100644
index 000000000..ae9446189
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/ThenELBuilderTest.java
@@ -0,0 +1,189 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.util.JsonUtil;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 串行组件测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = ThenELBuilderTest.class)
+@EnableAutoConfiguration
+public class ThenELBuilderTest extends BaseTest {
+
+ // then组件测试
+ @Test
+ public void testThen1(){
+ Assertions.assertEquals(ELBus.then("a", "b").toEL(), "THEN(node(\"a\"),node(\"b\"))");
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen2(){
+ Assertions.assertEquals(ELBus.then("a", "b").toEL(true),
+ "THEN(\n\tnode(\"a\")," +
+ "\n\tnode(\"b\")\n)");
+ System.out.println("THEN(\n\tnode(\"a\")," +
+ "\n\tnode(\"b\")\n)");
+ }
+ // then组件then方法调用测试
+ @Test
+ public void testThen3(){
+ Assertions.assertEquals(ELBus.then("a", "b").then("c").toEL(),
+ "THEN(node(\"a\"),node(\"b\"),node(\"c\"))");
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen4(){
+ Assertions.assertEquals(ELBus.then("a", "b").then("c").toEL(true),
+ "THEN(\n\tnode(\"a\"),\n\tnode(\"b\")," +
+ "\n\tnode(\"c\")\n)");
+ System.out.println("THEN(\n\tnode(\"a\"),\n\tnode(\"b\")," +
+ "\n\tnode(\"c\")\n)");
+ }
+ // then组件嵌套调用测试
+ @Test
+ public void testThen5(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c")).then("d").toEL(),
+ "THEN(node(\"a\"),THEN(node(\"b\"),node(\"c\")),node(\"d\"))");
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen6(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c")).then("d").toEL(true),
+ "THEN(\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n)");
+ System.out.println("THEN(\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n)");
+ }
+ // pre组件测试
+ @Test
+ public void testThen7(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c")).then("d").pre("p").pre("pp").toEL(),
+ "THEN(PRE(node(\"p\")),PRE(node(\"pp\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")),node(\"d\"))");
+ System.out.println("THEN(PRE(node(\"p\")),PRE(node(\"pp\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")),node(\"d\"))");
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen8(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c")).then("d").pre("p").pre("pp").toEL(true),
+ "THEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tPRE(\n\t\tnode(\"pp\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n)");
+ System.out.println("THEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tPRE(\n\t\tnode(\"pp\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n)");
+ }
+ // pre finally 格式测试
+ @Test
+ public void testThen9(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c")).then("d").pre("p").finallyOpt("f").toEL(),
+ "THEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")),node(\"d\"),FINALLY(node(\"f\")))");
+ System.out.println("THEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")),node(\"d\"),FINALLY(node(\"f\")))");
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen10(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c")).then("d").pre("p").finallyOpt("f").toEL(true),
+ "THEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n)");
+ System.out.println("THEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n)");
+ }
+ // 属性设置测试
+ @Test
+ public void testThen11(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c").id("this is a id")).tag("this is a tag").then("d").pre("p").finallyOpt("f").toEL(),
+ "THEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\"),FINALLY(node(\"f\"))).tag(\"this is a tag\")");
+ System.out.println("THEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\"),FINALLY(node(\"f\"))).tag(\"this is a tag\")");
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen12(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c").id("this is a id")).tag("this is a tag").then("d").pre("p").finallyOpt("f").toEL(true),
+ "THEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n).tag(\"this is a tag\")");
+ System.out.println("THEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n).tag(\"this is a tag\")");
+ }
+ // data属性测试
+ @Test
+ public void testThen13(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ System.out.println(JsonUtil.toJsonString(name2Value));
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c").id("this is a id")).tag("this is a tag").then("d").data("thenData", name2Value).pre("p").finallyOpt("f").toEL(),
+ "thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\"),FINALLY(node(\"f\"))).tag(\"this is a tag\").data(thenData)");
+ System.out.println("thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\"),FINALLY(node(\"f\"))).tag(\"this is a tag\").data(thenData)");
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen14(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c").id("this is a id")).tag("this is a tag").then("d").data("thenData", name2Value).pre("p").finallyOpt("f").toEL(true),
+ "thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n).tag(\"this is a tag\").data(thenData)");
+ System.out.println("thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n).tag(\"this is a tag\").data(thenData)");
+ }
+ // data属性测试 Json字符串赋值data
+ @Test
+ public void testThen15(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c").id("this is a id")).tag("this is a tag").then("d").data("thenData", "{\"name\":\"zhangsan\",\"age\":18}").pre("p").finallyOpt("f").toEL(),
+ "thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\"),FINALLY(node(\"f\"))).tag(\"this is a tag\").data(thenData)");
+ System.out.println("thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\"),FINALLY(node(\"f\"))).tag(\"this is a tag\").data(thenData)");
+ }
+ // 格式化输出测试 Json字符串赋值data
+ @Test
+ public void testThen16(){
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c").id("this is a id")).tag("this is a tag").then("d").data("thenData", "{\"name\":\"zhangsan\",\"age\":18}").pre("p").finallyOpt("f").toEL(true),
+ "thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n).tag(\"this is a tag\").data(thenData)");
+ System.out.println("thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n).tag(\"this is a tag\").data(thenData)");
+ }
+ private static class ParamClass{
+ private String name;
+ private Integer age;
+ public String getName(){
+ return name;
+ }
+ public Integer getAge(){
+ return age;
+ }
+ }
+ // data属性测试
+ @Test
+ public void testThen17(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c").id("this is a id")).tag("this is a tag").then("d").data("thenData", name2Value).pre("p").finallyOpt("f").toEL(),
+ "thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\"),FINALLY(node(\"f\"))).tag(\"this is a tag\").data(thenData)");
+ System.out.println("thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(PRE(node(\"p\")),node(\"a\"),THEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\"),FINALLY(node(\"f\"))).tag(\"this is a tag\").data(thenData)");
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen18(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ Assertions.assertEquals(ELBus.then("a", ELBus.then("b").then("c").id("this is a id")).tag("this is a tag").then("d").data("thenData", name2Value).pre("p").finallyOpt("f").toEL(true),
+ "thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n).tag(\"this is a tag\").data(thenData)");
+ System.out.println("thenData = '{\"name\":\"zhangsan\",\"age\":18}';\nTHEN(\n\tPRE(\n\t\tnode(\"p\")\n\t),\n\tnode(\"a\"),\n\tTHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\"),\n\tFINALLY(\n\t\tnode(\"f\")\n\t)\n).tag(\"this is a tag\").data(thenData)");
+ }
+ // maxWaitSecond测试
+ @Test
+ public void testThen19(){
+ String actualStr = "THEN(node(\"a\"),node(\"b\")).maxWaitSeconds(5)";
+ Assertions.assertEquals(ELBus.then("a").then("b").maxWaitSeconds(5).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testThen20(){
+ String actualStr = "THEN(\n\tnode(\"a\"),\n\tnode(\"b\")\n).maxWaitSeconds(5)";
+ Assertions.assertEquals(ELBus.then("a").then("b").maxWaitSeconds(5).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/WhenELBuilderTest.java b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/WhenELBuilderTest.java
new file mode 100644
index 000000000..574769737
--- /dev/null
+++ b/liteflow-testcase-el/liteflow-testcase-el-builder/src/test/java/com/yomahub/liteflow/test/builder/WhenELBuilderTest.java
@@ -0,0 +1,186 @@
+package com.yomahub.liteflow.test.builder;
+
+import com.yomahub.liteflow.builder.el.ELBus;
+import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.util.JsonUtil;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 并行组件测试
+ *
+ * @author gezuao
+ * @since 2.11.1
+ */
+@SpringBootTest(classes = WhenELBuilderTest.class)
+@EnableAutoConfiguration
+public class WhenELBuilderTest extends BaseTest {
+ // then组件测试
+ @Test
+ public void testWhen1(){
+ String actualStr = "WHEN(node(\"a\"),node(\"b\"))";
+ Assertions.assertEquals(ELBus.when("a", "b").toEL(), actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testWhen2(){
+ String actualStr = "WHEN(\n\tnode(\"a\"),\n\tnode(\"b\")\n)";
+ Assertions.assertEquals(ELBus.when("a", "b").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // then组件then方法调用测试
+ @Test
+ public void testWhen3(){
+ String actualStr = "WHEN(node(\"a\"),node(\"b\"),node(\"c\"))";
+ Assertions.assertEquals(ELBus.when("a", "b").when("c").toEL(),
+ actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testWhen4(){
+ String actualStr = "WHEN(\n\tnode(\"a\"),\n\tnode(\"b\"),\n\tnode(\"c\")\n)";
+ Assertions.assertEquals(ELBus.when("a", "b").when("c").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // then组件嵌套调用测试
+ @Test
+ public void testWhen5(){
+ String actualStr = "WHEN(node(\"a\"),WHEN(node(\"b\"),node(\"c\")),node(\"d\"))";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c")).when("d").toEL(),
+ actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testWhen6(){
+ String actualStr = "WHEN(\n\tnode(\"a\"),\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t),\n\tnode(\"d\")\n)";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c")).when("d").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // WHEN特有属性测试 any ignoreError customThreadExecutor must
+ @Test
+ public void testWhen7(){
+ String actualStr = "WHEN(node(\"a\"),node(\"b\"),WHEN(node(\"c\"),node(\"d\")).any(true).threadPool(\"WhenELBuilderTest.customThreadPool\").id(\"node1\")).ignoreError(true).must(\"a\", \"task1\", \"node1\")";
+ Assertions.assertEquals(ELBus.when("a", "b",ELBus.when("c").when("d").customThreadExecutor("WhenELBuilderTest.customThreadPool").id("node1").any(true)).ignoreError(true).must("a", "task1", "node1").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testWhen8(){
+ String actualStr = "WHEN(\n\tnode(\"a\"),\n\tnode(\"b\"),\n\tWHEN(\n\t\tnode(\"c\"),\n\t\tnode(\"d\")\n\t).any(true).threadPool(\"WhenELBuilderTest.customThreadPool\").id(\"node1\")\n).ignoreError(true).must(\"a\", \"task1\", \"node1\")";
+ Assertions.assertEquals(ELBus.when("a", "b",ELBus.when("c").when("d").customThreadExecutor("WhenELBuilderTest.customThreadPool").id("node1").any(true)).ignoreError(true).must("a", "task1", "node1").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // maxWaitSeconds 属性测试
+ @Test
+ public void testWhen9(){
+ String actualStr = "WHEN(node(\"a\"),node(\"b\")).maxWaitSeconds(5)";
+ Assertions.assertEquals(ELBus.when("a", "b").maxWaitSeconds(5).toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testWhen10(){
+ String actualStr = "WHEN(\n\tnode(\"a\"),\n\tnode(\"b\")\n).maxWaitSeconds(5)";
+ Assertions.assertEquals(ELBus.when("a", "b").maxWaitSeconds(5).toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 属性设置测试
+ @Test
+ public void testWhen11(){
+ String actualStr = "WHEN(node(\"a\"),WHEN(node(\"b\"),node(\"c\")).id(\"this is a id\"),node(\"d\")).tag(\"this is a tag\")";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c").id("this is a id")).when("d").tag("this is a tag").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testWhen12(){
+ String actualStr = "WHEN(\n\tnode(\"a\"),\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\"),\n\tnode(\"d\")\n).tag(\"this is a tag\")";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c").id("this is a id")).when("d").tag("this is a tag").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // data属性测试
+ @Test
+ public void testWhen13(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ System.out.println(JsonUtil.toJsonString(name2Value));
+ String actualStr = "whenData = '{\"name\":\"zhangsan\",\"age\":18}';\nWHEN(node(\"a\"),WHEN(node(\"b\"),node(\"c\")).id(\"this is a id\").data(whenData),node(\"d\")).tag(\"this is a tag\")";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c").data("whenData", name2Value).id("this is a id")).when("d").tag("this is a tag").toEL(false),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testWhen14(){
+ Map name2Value = new HashMap();
+ name2Value.put("name", "zhangsan");
+ name2Value.put("age", 18);
+ String actualStr = "whenData = '{\"name\":\"zhangsan\",\"age\":18}';\nWHEN(\n\tnode(\"a\"),\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\").data(whenData),\n\tnode(\"d\")\n).tag(\"this is a tag\")";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c").data("whenData", name2Value).id("this is a id")).when("d").tag("this is a tag").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // data属性测试 Json字符串赋值data
+ @Test
+ public void testWhen15(){
+ String actualStr = "whenData = '{\"name\":\"zhangsan\",\"age\":18}';\nWHEN(node(\"a\"),WHEN(node(\"b\"),node(\"c\")).id(\"this is a id\").data(whenData),node(\"d\")).tag(\"this is a tag\")";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c").data("whenData", "{\"name\":\"zhangsan\",\"age\":18}").id("this is a id")).when("d").tag("this is a tag").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试 Json字符串赋值data
+ @Test
+ public void testWhen16(){
+ String actualStr = "whenData = '{\"name\":\"zhangsan\",\"age\":18}';\nWHEN(\n\tnode(\"a\"),\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\").data(whenData),\n\tnode(\"d\")\n).tag(\"this is a tag\")";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c").data("whenData", "{\"name\":\"zhangsan\",\"age\":18}").id("this is a id")).when("d").tag("this is a tag").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ private static class ParamClass{
+ private String name;
+ private Integer age;
+ public String getName(){
+ return name;
+ }
+ public Integer getAge(){
+ return age;
+ }
+ }
+ // data属性测试
+ @Test
+ public void testWhen17(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "whenData = '{\"name\":\"zhangsan\",\"age\":18}';\nWHEN(node(\"a\"),WHEN(node(\"b\"),node(\"c\")).id(\"this is a id\").data(whenData),node(\"d\")).tag(\"this is a tag\")";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c").data("whenData", name2Value).id("this is a id")).when("d").tag("this is a tag").toEL(),
+ actualStr);
+ System.out.println(actualStr);
+ }
+ // 格式化输出测试
+ @Test
+ public void testWhen18(){
+ ParamClass name2Value = new ParamClass();
+ name2Value.name = "zhangsan";
+ name2Value.age = 18;
+ String actualStr = "whenData = '{\"name\":\"zhangsan\",\"age\":18}';\nWHEN(\n\tnode(\"a\"),\n\tWHEN(\n\t\tnode(\"b\"),\n\t\tnode(\"c\")\n\t).id(\"this is a id\").data(whenData),\n\tnode(\"d\")\n).tag(\"this is a tag\")";
+ Assertions.assertEquals(ELBus.when("a", ELBus.when("b").when("c").data("whenData", name2Value).id("this is a id")).when("d").tag("this is a tag").toEL(true),
+ actualStr);
+ System.out.println(actualStr);
+ }
+}
diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java
index fd619cdf2..ba135a619 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java
+++ b/liteflow-testcase-el/liteflow-testcase-el-declare-multi-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclMultiSpringbootTest.java
@@ -1,6 +1,7 @@
package com.yomahub.liteflow.test.absoluteConfigPath;
import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.core.FlowExecutor;
@@ -64,7 +65,7 @@ public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest {
@BeforeAll
public static void createFiles() {
- rootDir = Objects.requireNonNull(AbsoluteConfigPathELDeclMultiSpringbootTest.class.getResource("/")).getPath();
+ rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
String path1 = StrUtil.format("{}/sub/a", rootDir);
String path2 = StrUtil.format("{}/sub/b", rootDir);
diff --git a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java
index 1acd5c5f3..ae2393aed 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java
+++ b/liteflow-testcase-el/liteflow-testcase-el-declare-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELDeclSpringbootTest.java
@@ -1,6 +1,7 @@
package com.yomahub.liteflow.test.absoluteConfigPath;
import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.core.FlowExecutor;
@@ -8,6 +9,8 @@ import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.test.BaseTest;
+import com.yomahub.liteflow.util.PathMatchUtil;
+import org.apache.commons.collections.ListUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@@ -64,7 +67,7 @@ public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest {
@BeforeAll
public static void createFiles() {
- rootDir = Objects.requireNonNull(AbsoluteConfigPathELDeclSpringbootTest.class.getResource("/")).getPath();
+ rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
String path1 = StrUtil.format("{}/sub/a", rootDir);
String path2 = StrUtil.format("{}/sub/b", rootDir);
diff --git a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java
index 1cd83da4a..06e206679 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java
+++ b/liteflow-testcase-el/liteflow-testcase-el-nospring/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathTest.java
@@ -1,6 +1,7 @@
package com.yomahub.liteflow.test.absoluteConfigPath;
import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.core.FlowExecutor;
@@ -51,7 +52,7 @@ public class AbsoluteConfigPathTest extends BaseTest {
@BeforeAll
public static void createFiles() {
- rootDir = Objects.requireNonNull(AbsoluteConfigPathTest.class.getResource("/")).getPath();
+ rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
String path1 = StrUtil.format("{}/sub/a", rootDir);
String path2 = StrUtil.format("{}/sub/b", rootDir);
diff --git a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java
index 923126e18..62812c80b 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java
+++ b/liteflow-testcase-el/liteflow-testcase-el-solon/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java
@@ -1,6 +1,7 @@
package com.yomahub.liteflow.test.absoluteConfigPath;
import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.core.FlowExecutor;
@@ -57,7 +58,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest {
@BeforeAll
public static void createFiles() {
- rootDir = Objects.requireNonNull(AbsoluteConfigPathELSpringbootTest.class.getResource("/")).getPath();
+ rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
String path1 = StrUtil.format("{}/sub/a", rootDir);
String path2 = StrUtil.format("{}/sub/b", rootDir);
diff --git a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java
index f036c48a5..674e77f35 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java
+++ b/liteflow-testcase-el/liteflow-testcase-el-springboot/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringbootTest.java
@@ -1,6 +1,7 @@
package com.yomahub.liteflow.test.absoluteConfigPath;
import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.core.FlowExecutor;
@@ -61,7 +62,7 @@ public class AbsoluteConfigPathELSpringbootTest extends BaseTest {
@BeforeAll
public static void createFiles() {
- rootDir = Objects.requireNonNull(AbsoluteConfigPathELSpringbootTest.class.getResource("/")).getPath();
+ rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
String path1 = StrUtil.format("{}/sub/a", rootDir);
String path2 = StrUtil.format("{}/sub/b", rootDir);
diff --git a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java
index 50aa12094..f44acb08a 100644
--- a/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java
+++ b/liteflow-testcase-el/liteflow-testcase-el-springnative/src/test/java/com/yomahub/liteflow/test/absoluteConfigPath/AbsoluteConfigPathELSpringTest.java
@@ -1,6 +1,7 @@
package com.yomahub.liteflow.test.absoluteConfigPath;
import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.core.FlowExecutor;
@@ -56,7 +57,7 @@ public class AbsoluteConfigPathELSpringTest extends BaseTest {
@BeforeAll
public static void createFiles() {
- rootDir = Objects.requireNonNull(AbsoluteConfigPathELSpringTest.class.getResource("/")).getPath();
+ rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
String path1 = StrUtil.format("{}/sub/a", rootDir);
String path2 = StrUtil.format("{}/sub/b", rootDir);
diff --git a/liteflow-testcase-el/pom.xml b/liteflow-testcase-el/pom.xml
index 3aacdd528..c61bacebb 100644
--- a/liteflow-testcase-el/pom.xml
+++ b/liteflow-testcase-el/pom.xml
@@ -37,6 +37,7 @@
liteflow-testcase-el-script-aviator-springboot
liteflow-testcase-el-sql-springboot-dynamic
liteflow-testcase-el-script-java-springboot
+ liteflow-testcase-el-builder
diff --git a/pom.xml b/pom.xml
index 22fa42648..c736ec756 100644
--- a/pom.xml
+++ b/pom.xml
@@ -425,6 +425,7 @@
liteflow-spring
liteflow-solon-plugin
liteflow-testcase-el
+ liteflow-el-builder