mirror of
https://gitee.com/dromara/liteFlow.git
synced 2026-05-14 12:12:08 +08:00
enhancement #ID8XF9 对QLExpress4的支持
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
package com.yomahub.liteflow.builder.el;
|
package com.yomahub.liteflow.builder.el;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
|
||||||
import cn.hutool.core.util.CharUtil;
|
import cn.hutool.core.util.CharUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
@@ -15,7 +14,7 @@ import com.alibaba.qlexpress4.exception.QLException;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.yomahub.liteflow.builder.el.operator.*;
|
|
||||||
import com.yomahub.liteflow.common.ChainConstant;
|
import com.yomahub.liteflow.common.ChainConstant;
|
||||||
import com.yomahub.liteflow.common.entity.ValidationResp;
|
import com.yomahub.liteflow.common.entity.ValidationResp;
|
||||||
import com.yomahub.liteflow.enums.ParseModeEnum;
|
import com.yomahub.liteflow.enums.ParseModeEnum;
|
||||||
@@ -37,9 +36,9 @@ import com.yomahub.liteflow.util.ElRegexUtil;
|
|||||||
import com.yomahub.liteflow.util.QlExpressUtils;
|
import com.yomahub.liteflow.util.QlExpressUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +72,7 @@ public class LiteFlowChainELBuilder {
|
|||||||
/**
|
/**
|
||||||
* EL解析引擎
|
* EL解析引擎
|
||||||
*/
|
*/
|
||||||
private final static Express4Runner EXPRESS_RUNNER = QlExpressUtils.getInstance();
|
private final static Express4Runner EXPRESS_RUNNER = QlExpressUtils.getELExpressRunner();
|
||||||
|
|
||||||
public static LiteFlowChainELBuilder createChain() {
|
public static LiteFlowChainELBuilder createChain() {
|
||||||
return new LiteFlowChainELBuilder();
|
return new LiteFlowChainELBuilder();
|
||||||
@@ -290,25 +289,15 @@ public class LiteFlowChainELBuilder {
|
|||||||
String msg = String.format("[node/chain is not exist or node/chain not register]\n EL: %s",
|
String msg = String.format("[node/chain is not exist or node/chain not register]\n EL: %s",
|
||||||
StrUtil.trim(elStr));
|
StrUtil.trim(elStr));
|
||||||
try {
|
try {
|
||||||
// QLExpress4 暂时不支持 getInstructionSetFromLocalCache 方法
|
// 使用 QLExpress4 的 getOutVarNames 方法获取脚本中使用的所有外部变量
|
||||||
// 这里简化处理,直接返回基本错误信息
|
Set<String> outVarNames = EXPRESS_RUNNER.getOutVarNames(elStr);
|
||||||
// TODO: 等待 QLExpress4 提供相应的 API 后再完善此功能
|
if (CollUtil.isEmpty(outVarNames)) {
|
||||||
return msg;
|
|
||||||
|
|
||||||
/* 旧版本的代码,等待 QLExpress4 支持后再启用
|
|
||||||
InstructionSet parseResult = EXPRESS_RUNNER.getInstructionSetFromLocalCache(elStr);
|
|
||||||
if (parseResult == null) {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] outAttrNames = parseResult.getOutAttrNames();
|
|
||||||
if (ArrayUtil.isEmpty(outAttrNames)) {
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> chainIds = CollUtil.map(FlowBus.getChainMap().values(), Chain::getChainId, true);
|
List<String> chainIds = CollUtil.map(FlowBus.getChainMap().values(), Chain::getChainId, true);
|
||||||
List<String> nodeIds = CollUtil.map(FlowBus.getNodeMap().values(), Node::getId, true);
|
List<String> nodeIds = CollUtil.map(FlowBus.getNodeMap().values(), Node::getId, true);
|
||||||
for (String attrName : outAttrNames) {
|
for (String attrName : outVarNames) {
|
||||||
if (!chainIds.contains(attrName) && !nodeIds.contains(attrName)) {
|
if (!chainIds.contains(attrName) && !nodeIds.contains(attrName)) {
|
||||||
msg = String.format(
|
msg = String.format(
|
||||||
"[%s] is not exist or [%s] is not registered, you need to define a node or chain with id [%s] and register it \n EL: ",
|
"[%s] is not exist or [%s] is not registered, you need to define a node or chain with id [%s] and register it \n EL: ",
|
||||||
@@ -332,13 +321,12 @@ public class LiteFlowChainELBuilder {
|
|||||||
// 还有一种特殊情况,就是 EL 表达式中的节点使用 node("a")
|
// 还有一种特殊情况,就是 EL 表达式中的节点使用 node("a")
|
||||||
int nodeIndex = sourceEl.indexOf(String.format("node(\"%s\")", attrName));
|
int nodeIndex = sourceEl.indexOf(String.format("node(\"%s\")", attrName));
|
||||||
if (nodeIndex != -1) {
|
if (nodeIndex != -1) {
|
||||||
// 需要加上 "EL: " 的长度 4,再加上 “node("” 长度 6,再加上 "^" 的长度 1,indexOf 从 0
|
// 需要加上 "EL: " 的长度 4,再加上 "node("" 长度 6,再加上 "^" 的长度 1,indexOf 从 0
|
||||||
// 开始,所以还需要加 1
|
// 开始,所以还需要加 1
|
||||||
return msg + sourceEl + "\n" + StrUtil.fill("^", CharUtil.SPACE, commaLeftIndex + 12, true);
|
return msg + sourceEl + "\n" + StrUtil.fill("^", CharUtil.SPACE, commaLeftIndex + 12, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
@@ -373,12 +361,8 @@ public class LiteFlowChainELBuilder {
|
|||||||
// 只有当PARSE_ONE_ON_FIRST_EXEC时才会执行这个方法
|
// 只有当PARSE_ONE_ON_FIRST_EXEC时才会执行这个方法
|
||||||
// 那么会有一种级联的情况:这个EL中含有其他的chain,如果这时候不先解析其他chain,就到导致诸如循环场景无法设置index或者obj的情况
|
// 那么会有一种级联的情况:这个EL中含有其他的chain,如果这时候不先解析其他chain,就到导致诸如循环场景无法设置index或者obj的情况
|
||||||
// 所以这里要判断表达式里有没有其他的chain,如果有,进行先行解析
|
// 所以这里要判断表达式里有没有其他的chain,如果有,进行先行解析
|
||||||
|
Set<String> itemSet = EXPRESS_RUNNER.getOutVarNames(chain.getEl());
|
||||||
// TODO: QLExpress4 暂时没有 getOutVarNames 方法,这里先注释掉级联解析逻辑
|
itemSet.stream().forEach(item -> {
|
||||||
// 等待 QLExpress4 提供相应的 API 后再恢复
|
|
||||||
/*
|
|
||||||
String[] itemArray = EXPRESS_RUNNER.getOutVarNames(chain.getEl());
|
|
||||||
Arrays.stream(itemArray).forEach(item -> {
|
|
||||||
if (FlowBus.containChain(item) && !chain.getChainId().equals(item)) {
|
if (FlowBus.containChain(item) && !chain.getChainId().equals(item)) {
|
||||||
Chain itemChain = FlowBus.getChain(item);
|
Chain itemChain = FlowBus.getChain(item);
|
||||||
if (!itemChain.isCompiled()){
|
if (!itemChain.isCompiled()){
|
||||||
@@ -386,7 +370,6 @@ public class LiteFlowChainELBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
|
||||||
// 解析el成为一个Condition
|
// 解析el成为一个Condition
|
||||||
// 为什么这里只是一个Condition,而不是一个List<Condition>呢
|
// 为什么这里只是一个Condition,而不是一个List<Condition>呢
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import java.util.stream.IntStream;
|
|||||||
*/
|
*/
|
||||||
public class LiteflowContextRegexMatcher {
|
public class LiteflowContextRegexMatcher {
|
||||||
|
|
||||||
private static final Express4Runner expressRunner = new Express4Runner(InitOptions.DEFAULT_OPTIONS);
|
private static final Express4Runner expressRunner = QlExpressUtils.getContextSearchExpressRunner();
|
||||||
|
|
||||||
public static Object searchContext(List<Tuple> contextList, String regPattern){
|
public static Object searchContext(List<Tuple> contextList, String regPattern){
|
||||||
// 把上下文数据转换成map形式的,key为别名,value为上下文
|
// 把上下文数据转换成map形式的,key为别名,value为上下文
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.yomahub.liteflow.util;
|
|||||||
|
|
||||||
import com.alibaba.qlexpress4.Express4Runner;
|
import com.alibaba.qlexpress4.Express4Runner;
|
||||||
import com.alibaba.qlexpress4.InitOptions;
|
import com.alibaba.qlexpress4.InitOptions;
|
||||||
|
import com.alibaba.qlexpress4.security.QLSecurityStrategy;
|
||||||
import com.yomahub.liteflow.builder.el.operator.*;
|
import com.yomahub.liteflow.builder.el.operator.*;
|
||||||
import com.yomahub.liteflow.common.ChainConstant;
|
import com.yomahub.liteflow.common.ChainConstant;
|
||||||
|
|
||||||
@@ -18,6 +19,11 @@ public class QlExpressUtils {
|
|||||||
*/
|
*/
|
||||||
private final static Express4Runner EXPRESS_RUNNER = new Express4Runner(InitOptions.DEFAULT_OPTIONS);
|
private final static Express4Runner EXPRESS_RUNNER = new Express4Runner(InitOptions.DEFAULT_OPTIONS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上下文搜索解析引擎
|
||||||
|
*/
|
||||||
|
private final static Express4Runner CONTEXT_SEARCH_EXPRESS_RUNNER = new Express4Runner(InitOptions.builder().securityStrategy(QLSecurityStrategy.open()).build());
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// 初始化QLExpress的Runner
|
// 初始化QLExpress的Runner
|
||||||
EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.THEN, new ThenOperator());
|
EXPRESS_RUNNER.addVarArgsFunction(ChainConstant.THEN, new ThenOperator());
|
||||||
@@ -63,10 +69,17 @@ public class QlExpressUtils {
|
|||||||
/**
|
/**
|
||||||
* 获取QLExpress的实例
|
* 获取QLExpress的实例
|
||||||
*/
|
*/
|
||||||
public static Express4Runner getInstance() {
|
public static Express4Runner getELExpressRunner() {
|
||||||
return EXPRESS_RUNNER;
|
return EXPRESS_RUNNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上下文搜索的QLExpress实例
|
||||||
|
*/
|
||||||
|
public static Express4Runner getContextSearchExpressRunner() {
|
||||||
|
return CONTEXT_SEARCH_EXPRESS_RUNNER;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查变量名是否符合 变量命名规则
|
* 检查变量名是否符合 变量命名规则
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
|
|||||||
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
|
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
|
||||||
import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil;
|
import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil;
|
||||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
@@ -56,7 +55,7 @@ public class ScriptRead extends AbstractSqlRead<ScriptVO> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String buildQuerySql() {
|
public String buildQuerySql() {
|
||||||
if (StringUtils.isNotBlank(super.config.getScriptCustomSql())) {
|
if (StrUtil.isNotBlank(super.config.getScriptCustomSql())) {
|
||||||
return super.config.getScriptCustomSql();
|
return super.config.getScriptCustomSql();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +71,7 @@ public class ScriptRead extends AbstractSqlRead<ScriptVO> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String buildQuerySql(String scriptNodeId) {
|
public String buildQuerySql(String scriptNodeId) {
|
||||||
if (StringUtils.isNotBlank(super.config.getScriptCustomSql())) {
|
if (StrUtil.isNotBlank(super.config.getScriptCustomSql())) {
|
||||||
return super.config.getScriptCustomSql();
|
return super.config.getScriptCustomSql();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import com.yomahub.liteflow.parser.sql.read.SqlReadFactory;
|
|||||||
import com.yomahub.liteflow.parser.sql.read.vo.ChainVO;
|
import com.yomahub.liteflow.parser.sql.read.vo.ChainVO;
|
||||||
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
|
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
|
||||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -116,7 +115,7 @@ public class JDBCHelper {
|
|||||||
String language = scriptVO.getLanguage();
|
String language = scriptVO.getLanguage();
|
||||||
String elData = scriptVO.getScript();
|
String elData = scriptVO.getScript();
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(scriptVO.getLanguage())) {
|
if (StrUtil.isNotBlank(scriptVO.getLanguage())) {
|
||||||
scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, language, elData));
|
scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, language, elData));
|
||||||
} else {
|
} else {
|
||||||
scriptList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, elData));
|
scriptList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, elData));
|
||||||
|
|||||||
Reference in New Issue
Block a user