bug #I5YEHG 脚本的加载有先后顺序问题

This commit is contained in:
everywhere.z
2022-11-02 14:30:43 +08:00
parent a6094a0ce5
commit 3a2fcb56b8
8 changed files with 145 additions and 56 deletions

View File

@@ -35,7 +35,8 @@ public abstract class BaseJsonFlowParser implements FlowParser {
JsonNode flowJsonNode = JsonUtil.parseObject(content);
jsonObjectList.add(flowJsonNode);
}
ParserHelper.parseJsonNode(jsonObjectList, CHAIN_NAME_SET, this::parseOneChain);
ParserHelper.parseNodeJson(jsonObjectList);
ParserHelper.parseChainJson(jsonObjectList, CHAIN_NAME_SET, this::parseOneChain);
}
/**

View File

@@ -36,8 +36,8 @@ public abstract class BaseXmlFlowParser implements FlowParser {
documentList.add(document);
}
Consumer<Element> parseOneChainConsumer = this::parseOneChain;
ParserHelper.parseDocument(documentList, CHAIN_NAME_SET, parseOneChainConsumer);
ParserHelper.parseNodeDocument(documentList);
ParserHelper.parseChainDocument(documentList, CHAIN_NAME_SET, this::parseOneChain);
}
/**

View File

@@ -39,7 +39,8 @@ public abstract class BaseYmlFlowParser implements FlowParser {
}
Consumer<JsonNode> parseOneChainConsumer = this::parseOneChain;
ParserHelper.parseJsonNode(jsonObjectList, CHAIN_NAME_SET,parseOneChainConsumer);
ParserHelper.parseNodeJson(jsonObjectList);
ParserHelper.parseChainJson(jsonObjectList, CHAIN_NAME_SET, parseOneChainConsumer);
}
protected JsonNode convertToJson(String yamlString) {

View File

@@ -87,35 +87,9 @@ public class ParserHelper {
/**
* xml 形式的主要解析过程
*
* @param documentList documentList
* @param chainNameSet 用于去重
* @param parseOneChainConsumer parseOneChain 函数
*/
public static void parseDocument(List<Document> documentList, Set<String> chainNameSet, Consumer<Element> parseOneChainConsumer) {
//先在元数据里放上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 (!chainNameSet.add(chainName)) {
throw new ChainDuplicateException(String.format("[chain name duplicate] chainName=%s", chainName));
}
FlowBus.addChain(chainName);
});
});
// 清空
chainNameSet.clear();
public static void parseNodeDocument(List<Document> documentList) {
for (Document document : documentList) {
Element rootElement = document.getRootElement();
Element nodesElement = rootElement.element(NODES);
@@ -143,37 +117,42 @@ public class ParserHelper {
ParserHelper.buildNode(nodePropBean);
}
}
}
}
//解析每一个chain
public static void parseChainDocument(List<Document> documentList, Set<String> chainNameSet, Consumer<Element> parseOneChainConsumer){
//先在元数据里放上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 (!chainNameSet.add(chainName)) {
throw new ChainDuplicateException(String.format("[chain name duplicate] chainName=%s", chainName));
}
FlowBus.addChain(chainName);
});
});
// 清空
chainNameSet.clear();
//解析每一个chain
for (Document document : documentList) {
Element rootElement = document.getRootElement();
List<Element> chainList = rootElement.elements(CHAIN);
chainList.forEach(parseOneChainConsumer);
}
}
public static void parseJsonNode(List<JsonNode> flowJsonObjectList, Set<String> chainNameSet, Consumer<JsonNode> parseOneChainConsumer) {
//先在元数据里放上chain
//先放有一个好处可以在parse的时候先映射到FlowBus的chainMap然后再去解析
//这样就不用去像之前的版本那样回归调用
//同时也解决了不能循环依赖的问题
flowJsonObjectList.forEach(jsonObject -> {
// 解析chain节点
Iterator<JsonNode> iterator = jsonObject.get(FLOW).get(CHAIN).elements();
//先在元数据里放上chain
while (iterator.hasNext()) {
JsonNode innerJsonObject = iterator.next();
//校验加载的 chainName 是否有重复的
// TODO 这里是否有个问题当混合格式加载的时候2个同名的Chain在不同的文件里就不行了
String chainName = innerJsonObject.get(NAME).textValue();
if (!chainNameSet.add(chainName)) {
throw new ChainDuplicateException(String.format("[chain name duplicate] chainName=%s", chainName));
}
FlowBus.addChain(innerJsonObject.get(NAME).textValue());
}
});
// 清空
chainNameSet.clear();
public static void parseNodeJson(List<JsonNode> flowJsonObjectList) {
for (JsonNode flowJsonNode : flowJsonObjectList) {
// 当存在<nodes>节点定义时解析node节点
if (flowJsonNode.get(FLOW).has(NODES)) {
@@ -200,7 +179,34 @@ public class ParserHelper {
ParserHelper.buildNode(nodePropBean);
}
}
}
}
public static void parseChainJson(List<JsonNode> flowJsonObjectList, Set<String> chainNameSet, Consumer<JsonNode> parseOneChainConsumer){
//先在元数据里放上chain
//先放有一个好处可以在parse的时候先映射到FlowBus的chainMap然后再去解析
//这样就不用去像之前的版本那样回归调用
//同时也解决了不能循环依赖的问题
flowJsonObjectList.forEach(jsonObject -> {
// 解析chain节点
Iterator<JsonNode> iterator = jsonObject.get(FLOW).get(CHAIN).elements();
//先在元数据里放上chain
while (iterator.hasNext()) {
JsonNode innerJsonObject = iterator.next();
//校验加载的 chainName 是否有重复的
// TODO 这里是否有个问题当混合格式加载的时候2个同名的Chain在不同的文件里就不行了
String chainName = innerJsonObject.get(NAME).textValue();
if (!chainNameSet.add(chainName)) {
throw new ChainDuplicateException(String.format("[chain name duplicate] chainName=%s", chainName));
}
FlowBus.addChain(innerJsonObject.get(NAME).textValue());
}
});
// 清空
chainNameSet.clear();
for (JsonNode flowJsonNode : flowJsonObjectList) {
//解析每一个chain
Iterator<JsonNode> chainIterator = flowJsonNode.get(FLOW).get(CHAIN).elements();
while (chainIterator.hasNext()) {

View File

@@ -0,0 +1,42 @@
package com.yomahub.liteflow.test.script.groovy.scriptOrder;
import cn.hutool.core.io.resource.ResourceUtil;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.enums.FlowParserTypeEnum;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.slot.DefaultContext;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
/**
* 测试springboot下的groovy脚本组件基于xml配置
* @author Bryan.Zhang
* @since 2.6.0
*/
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/scriptOrder/application.properties")
@SpringBootTest(classes = LiteflowScriptOrderGroovyELTest.class)
@EnableAutoConfiguration
public class LiteflowScriptOrderGroovyELTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
//测试普通脚本节点
@Test
public void testScript1() {
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
Assert.assertTrue(response.isSuccess());
}
}

View File

@@ -0,0 +1 @@
liteflow.rule-source=scriptOrder/flow1.xml,scriptOrder/flow2.xml

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
<flow>
<nodes>
<node id="s1" language="groovy" type="if_script">
<![CDATA[
System.out.println("Groovy 脚本1 被调用。")
return false
]]>
</node>
<node id="s2" language="groovy" type="script">
<![CDATA[
System.out.println("Groovy 脚本2 被调用。")
]]>
</node>
<node id="s3" language="groovy" type="script">
<![CDATA[
System.out.println("Groovy 脚本3 被调用。")
]]>
</node>
</nodes>
<chain name="chain1">
// IF(s1, s2, s3);
IF(s1, s2, s4);
</chain>
</flow>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
<flow>
<nodes>
<node id="s4" language="groovy" type="script">
<![CDATA[
System.out.println("Groovy 脚本4 被调用。")
]]>
</node>
</nodes>
</flow>