feature #I5CW7I 【版本特性】构造全新的EL规则表达式

This commit is contained in:
everywhere.z
2022-06-17 19:02:18 +08:00
parent ccc7660beb
commit 5a21adad6d
2 changed files with 164 additions and 4 deletions

View File

@@ -5,10 +5,13 @@ package com.yomahub.liteflow.enums;
* @since 2.5.0
*/
public enum FlowParserTypeEnum {
TYPE_XML("xml","xml"),
TYPE_YML("yml","yml"),
TYPE_JSON("json","json")
;
TYPE_XML("xml", "xml"),
TYPE_YML("yml", "yml"),
TYPE_JSON("json", "json"),
TYPE_EL_XML("el_xml", "el_xml"),
TYPE_EL_JSON("el_json", "el_json"),
TYPE_EL_YML("el_yml", "el_yml")
;
private String type;
private String name;

View File

@@ -0,0 +1,157 @@
package com.yomahub.liteflow.parser.el;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yomahub.liteflow.builder.LiteFlowChainBuilder;
import com.yomahub.liteflow.builder.prop.ChainPropBean;
import com.yomahub.liteflow.builder.prop.NodePropBean;
import com.yomahub.liteflow.enums.ConditionTypeEnum;
import com.yomahub.liteflow.exception.ChainDuplicateException;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.parser.BaseFlowParser;
import com.yomahub.liteflow.parser.XmlFlowParser;
import com.yomahub.liteflow.spi.holder.ContextCmpInitHolder;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import static com.yomahub.liteflow.common.ChainConstant.*;
import static com.yomahub.liteflow.common.ChainConstant.THREAD_EXECUTOR_CLASS;
/**
* EL表达引擎Xml形式的解析抽象引擎
* @author Bryan.Zhang
* @since 2.8.0
*/
public abstract class ELXmlFlowParser extends BaseFlowParser {
private final Logger LOG = LoggerFactory.getLogger(XmlFlowParser.class);
private final Set<String> CHAIN_NAME_SET = new CopyOnWriteArraySet<>();
public void parse(String content) throws Exception {
parse(ListUtil.toList(content));
}
@Override
public void parse(List<String> contentList) throws Exception {
if (CollectionUtil.isEmpty(contentList)) {
return;
}
List<Document> documentList = ListUtil.toList();
for (String content : contentList) {
Document document = DocumentHelper.parseText(content);
documentList.add(document);
}
parseDocument(documentList);
}
//xml形式的主要解析过程
public void parseDocument(List<Document> documentList) throws Exception {
//在相应的环境下进行节点的初始化工作
//在spring体系下会获得spring扫描后的节点接入元数据
//在非spring体系下是一个空实现等于不做此步骤
ContextCmpInitHolder.loadContextCmpInit().initCmp();
//先在元数据里放上chain
//先放有一个好处可以在parse的时候先映射到FlowBus的chainMap然后再去解析
//这样就不用去像之前的版本那样回归调用
//同时也解决了不能循环依赖的问题
documentList.forEach(document -> {
// 解析chain节点
List<Element> chainList = document.getRootElement().elements(CHAIN);
//先在元数据里放上chain
chainList.forEach(e -> {
//校验加载的 chainName 是否有重复的
//TODO 这里是否有个问题当混合格式加载的时候2个同名的Chain在不同的文件里就不行了
String chainName = e.attributeValue(NAME);
if (!CHAIN_NAME_SET.add(chainName)) {
throw new ChainDuplicateException(String.format("[chain name duplicate] chainName=%s", chainName));
}
FlowBus.addChain(chainName);
});
});
// 清空
CHAIN_NAME_SET.clear();
for (Document document : documentList) {
Element rootElement = document.getRootElement();
Element nodesElement = rootElement.element(NODES);
// 当存在<nodes>节点定义时解析node节点
if (ObjectUtil.isNotNull(nodesElement)) {
List<Element> nodeList = nodesElement.elements(NODE);
String id, name, clazz, type, script, file;
for (Element e : nodeList) {
id = e.attributeValue(ID);
name = e.attributeValue(NAME);
clazz = e.attributeValue(_CLASS);
type = e.attributeValue(TYPE);
script = e.getTextTrim();
file = e.attributeValue(FILE);
// 构建 node
NodePropBean nodePropBean = new NodePropBean()
.setId(id)
.setName(name)
.setClazz(clazz)
.setScript(script)
.setType(type)
.setFile(file);
buildNode(nodePropBean);
}
}
//解析每一个chain
List<Element> chainList = rootElement.elements(CHAIN);
chainList.forEach(this::parseOneChain);
}
}
/**
* 解析一个chain的过程
*/
private void parseOneChain(Element e) {
String condValueStr;
String group;
String errorResume;
String any;
String threadExecutorClass;
ConditionTypeEnum conditionType;
//构建chainBuilder
String chainName = e.attributeValue(NAME);
LiteFlowChainBuilder chainBuilder = LiteFlowChainBuilder.createChain().setChainName(chainName);
for (Iterator<Element> it = e.elementIterator(); it.hasNext(); ) {
Element condE = it.next();
conditionType = ConditionTypeEnum.getEnumByCode(condE.getName());
condValueStr = condE.attributeValue(VALUE);
errorResume = condE.attributeValue(ERROR_RESUME);
group = condE.attributeValue(GROUP);
any = condE.attributeValue(ANY);
threadExecutorClass = condE.attributeValue(THREAD_EXECUTOR_CLASS);
ChainPropBean chainPropBean = new ChainPropBean()
.setCondValueStr(condValueStr)
.setGroup(group)
.setErrorResume(errorResume)
.setAny(any)
.setThreadExecutorClass(threadExecutorClass)
.setConditionType(conditionType);
// 构建 chain
buildChain(chainPropBean, chainBuilder);
}
}
}