feat #I7SVZF 添加JSON中的CHain的抽象继承关系

This commit is contained in:
zy 2023-09-18 23:03:31 +08:00
parent d72fb33a81
commit 439a3e5294
5 changed files with 112 additions and 5 deletions

View File

@ -4,6 +4,7 @@ import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.builder.prop.NodePropBean;
@ -215,6 +216,10 @@ public class ParserHelper {
public static void parseChainJson(List<JsonNode> flowJsonObjectList, Set<String> chainNameSet,
Consumer<JsonNode> parseOneChainConsumer) {
//用于存放抽象chain的map
Map<String,JsonNode> abstratChainMap = new HashMap<>();
//用于存放已经解析过的实现chain
Set<JsonNode> implChainSet = new HashSet<>();
// 先在元数据里放上chain
// 先放有一个好处可以在parse的时候先映射到FlowBus的chainMap然后再去解析
// 这样就不用去像之前的版本那样回归调用
@ -237,6 +242,10 @@ public class ParserHelper {
}
FlowBus.addChain(chainName);
if(innerJsonObject.hasNonNull(ABSTRACT) && innerJsonObject.get(ABSTRACT).asBoolean()) {
abstratChainMap.put(chainName,innerJsonObject);
}
}
});
// 清空
@ -246,8 +255,21 @@ public class ParserHelper {
// 解析每一个chain
Iterator<JsonNode> chainIterator = flowJsonNode.get(FLOW).get(CHAIN).elements();
while (chainIterator.hasNext()) {
JsonNode jsonNode = chainIterator.next();
parseOneChainConsumer.accept(jsonNode);
JsonNode chainNode = chainIterator.next();
//首先需要对继承自抽象Chain的chain进行字符串替换
if(chainNode.hasNonNull(EXTENDS)){
String baseChainId = chainNode.get(EXTENDS).textValue();
if(abstratChainMap.containsKey(baseChainId)) {
JsonNode baseChain = abstratChainMap.get(baseChainId);
parseImplChain(baseChain,chainNode,abstratChainMap,implChainSet);
}else{
throw new ChainNotFoundException(String.format("[abstract chain not found] chainName=%s", baseChainId));
}
}
//如果一个chain不为抽象chain则进行解析
if(chainNode.get(ABSTRACT) == null || !chainNode.get(ABSTRACT).asBoolean()){
parseOneChainConsumer.accept(chainNode);
}
}
}
}
@ -289,7 +311,38 @@ public class ParserHelper {
}
/**
* 解析一个继承自baseChain的implChain
* 解析一个继承自baseChain的implChain,xml格式
* @param baseChain 父Chain
* @param implChain 实现Chain
* @param abstractChainMap 所有的抽象Chain
* @param implChainSet 已经解析过的实现Chain
*/
private static void parseImplChain(JsonNode baseChain,JsonNode implChain,Map<String,JsonNode> abstractChainMap,Set<JsonNode> implChainSet) {
//如果已经解析过了就不再解析
if(implChainSet.contains(implChain)) return;
//如果baseChainId也是继承自其他的chain需要递归解析
if(baseChain.get(EXTENDS)!=null){
String pBaseChainId = baseChain.get(EXTENDS).textValue();
if(abstractChainMap.containsKey(pBaseChainId)) {
JsonNode pBaseChain = abstractChainMap.get(pBaseChainId);
parseImplChain(pBaseChain, baseChain, abstractChainMap, implChainSet);
}else{
throw new ChainNotFoundException(String.format("[abstract chain not found] chainName=%s", pBaseChainId));
}
}
//否则根据baseChainId解析implChainId
String implChainEl = implChain.get(VALUE).textValue();
String baseChainEl = baseChain.get(VALUE).textValue();
//替换baseChainId中的implChainId
// 使用正则表达式匹配占位符并替换
String parsedEl = RegexUtil.replaceAbstractChain(baseChainEl,implChainEl);
ObjectNode objectNode = (ObjectNode) implChain;
objectNode.put(VALUE,parsedEl);
implChainSet.add(implChain);
}
/**
* 解析一个继承自baseChain的implChain,json格式
* @param baseChain 父Chain
* @param implChain 实现Chain
* @param abstractChainMap 所有的抽象Chain

View File

@ -0,0 +1,37 @@
package com.yomahub.liteflow.test.abstractChain;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
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 org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import javax.annotation.Resource;
/**
* 测试显示调用子流程(json) 单元测试
*
* @author justin.xu
*/
@TestPropertySource(value = "classpath:/abstractChain/application-json.properties")
@SpringBootTest(classes = AbstractChainJsonELSpringBootTest.class)
@EnableAutoConfiguration
@ComponentScan({ "com.yomahub.liteflow.test.abstractChain.cmp" })
public class AbstractChainJsonELSpringBootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
// 是否按照流程定义配置执行
@Test
public void testExplicitSubFlow() {
LiteflowResponse response = flowExecutor.execute2Resp("implA", "it's a request");
Assertions.assertTrue(response.isSuccess());
Assertions.assertEquals("a==>b==>c==>d==>f==>j", response.getExecuteStepStrWithoutTime());
}
}

View File

@ -18,10 +18,10 @@ import javax.annotation.Resource;
* @author Bryan.Zhang
*/
@TestPropertySource(value = "classpath:/abstractChain/application.properties")
@SpringBootTest(classes = AbstractChainELSpringbootTest.class)
@SpringBootTest(classes = AbstractChainXMLELSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({ "com.yomahub.liteflow.test.abstractChain.cmp" })
public class AbstractChainELSpringbootTest extends BaseTest {
public class AbstractChainXMLELSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;

View File

@ -0,0 +1 @@
liteflow.rule-source=abstractChain/flow.el.json

View File

@ -0,0 +1,16 @@
{
"flow": {
"chain": [
{
"name": "base",
"abstract": true,
"value": "THEN(a, b, {0}, {1});"
},
{
"name": "implA",
"extends": "base",
"value": "{0}=IF(c, d, e);\n {1}=SWITCH(f).to(j,k);"
}
]
}
}