Merge branch 'refs/heads/dev'
This commit is contained in:
commit
d4e464eb1a
|
@ -0,0 +1,12 @@
|
|||
package com.yomahub.liteflow.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.PARAMETER})
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface LiteflowFact {
|
||||
|
||||
String value();
|
||||
}
|
|
@ -136,8 +136,7 @@ public class LiteFlowChainELBuilder {
|
|||
|
||||
public LiteFlowChainELBuilder setRoute(String routeEl){
|
||||
if (StrUtil.isBlank(routeEl)) {
|
||||
String errMsg = StrUtil.format("You have defined the label <route> but there is no el in the chain route[{}].", chain.getChainId());
|
||||
throw new FlowSystemException(errMsg);
|
||||
return this;
|
||||
}
|
||||
List<String> errorList = new ArrayList<>();
|
||||
try {
|
||||
|
@ -233,6 +232,14 @@ public class LiteFlowChainELBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
public LiteFlowChainELBuilder setNamespace(String nameSpace){
|
||||
if (StrUtil.isBlank(nameSpace)) {
|
||||
nameSpace = ChainConstant.DEFAULT_NAMESPACE;
|
||||
}
|
||||
this.chain.setNamespace(nameSpace);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* EL表达式校验
|
||||
* @param elStr EL表达式
|
||||
|
|
|
@ -32,6 +32,10 @@ public interface ChainConstant {
|
|||
|
||||
String LANGUAGE = "language";
|
||||
|
||||
String NAMESPACE = "namespace";
|
||||
|
||||
String DEFAULT_NAMESPACE = "default";
|
||||
|
||||
String VALUE = "value";
|
||||
|
||||
String ANY = "any";
|
||||
|
|
|
@ -13,6 +13,7 @@ import cn.hutool.core.collection.ListUtil;
|
|||
import cn.hutool.core.lang.Tuple;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.*;
|
||||
import com.yomahub.liteflow.common.ChainConstant;
|
||||
import com.yomahub.liteflow.enums.ChainExecuteModeEnum;
|
||||
import com.yomahub.liteflow.enums.InnerChainTypeEnum;
|
||||
import com.yomahub.liteflow.enums.ParseModeEnum;
|
||||
|
@ -136,8 +137,8 @@ public class FlowExecutor {
|
|||
// 查找对应的解析器
|
||||
parser = FlowParserProvider.lookup(path);
|
||||
parserNameSet.add(parser.getClass().getName());
|
||||
// 替换掉前缀标识(如:xml:/json:),保留剩下的完整地址
|
||||
path = ReUtil.replaceAll(path, PREFIX_FORMAT_CONFIG_REGEX, "");
|
||||
// 替换掉前缀标识(如:xml:/json:),保留剩下的完整地址,并统一路径格式
|
||||
path = ReUtil.replaceAll(path, PREFIX_FORMAT_CONFIG_REGEX, "").replace("\\", "/");
|
||||
rulePathList.add(path);
|
||||
|
||||
// 支持多类型的配置文件,分别解析
|
||||
|
@ -283,7 +284,11 @@ public class FlowExecutor {
|
|||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChain(Object param, Class<?>... contextBeanClazzArray){
|
||||
return this.executeWithRoute(param, null, contextBeanClazzArray, null);
|
||||
return this.executeWithRoute(null, param, null, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChain(String namespace, Object param, Class<?>... contextBeanClazzArray){
|
||||
return this.executeWithRoute(namespace, param, null, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public LiteflowResponse execute2Resp(String chainId, Object param, Object... contextBeanArray) {
|
||||
|
@ -291,23 +296,35 @@ public class FlowExecutor {
|
|||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChain(Object param, Object... contextBeanArray){
|
||||
return this.executeWithRoute(param, null, null, contextBeanArray);
|
||||
return this.executeWithRoute(null, param, null, null, contextBeanArray);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChain(String namespace, Object param, Object... contextBeanArray){
|
||||
return this.executeWithRoute(namespace, param, null, null, contextBeanArray);
|
||||
}
|
||||
|
||||
public LiteflowResponse execute2RespWithRid(String chainId, Object param, String requestId, Class<?>... contextBeanClazzArray) {
|
||||
return this.execute2Resp(chainId, param, requestId, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(String chainId, Object param, String requestId, Class<?>... contextBeanClazzArray) {
|
||||
return this.executeWithRoute(param, requestId, contextBeanClazzArray, null);
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(Object param, String requestId, Class<?>... contextBeanClazzArray) {
|
||||
return this.executeWithRoute(null, param, requestId, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(String namespace, Object param, String requestId, Class<?>... contextBeanClazzArray) {
|
||||
return this.executeWithRoute(namespace, param, requestId, contextBeanClazzArray, null);
|
||||
}
|
||||
|
||||
public LiteflowResponse execute2RespWithRid(String chainId, Object param, String requestId, Object... contextBeanArray) {
|
||||
return this.execute2Resp(chainId, param, requestId, null, contextBeanArray);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(String chainId, Object param, String requestId, Object... contextBeanArray) {
|
||||
return this.executeWithRoute(param, requestId, null, contextBeanArray);
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(Object param, String requestId, Object... contextBeanArray) {
|
||||
return this.executeWithRoute(null, param, requestId, null, contextBeanArray);
|
||||
}
|
||||
|
||||
public List<LiteflowResponse> executeRouteChainWithRid(String namespace, Object param, String requestId, Object... contextBeanArray) {
|
||||
return this.executeWithRoute(namespace, param, requestId, null, contextBeanArray);
|
||||
}
|
||||
|
||||
// 调用一个流程并返回Future<LiteflowResponse>,允许多上下文的传入
|
||||
|
@ -353,8 +370,8 @@ public class FlowExecutor {
|
|||
return LiteflowResponse.newMainResponse(slot);
|
||||
}
|
||||
|
||||
private List<LiteflowResponse> executeWithRoute(Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray){
|
||||
List<Slot> slotList = doExecuteWithRoute(param, requestId, contextBeanClazzArray, contextBeanArray);
|
||||
private List<LiteflowResponse> executeWithRoute(String namespace, Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray){
|
||||
List<Slot> slotList = doExecuteWithRoute(namespace, param, requestId, contextBeanClazzArray, contextBeanArray);
|
||||
return slotList.stream().map(LiteflowResponse::newMainResponse).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
@ -522,15 +539,23 @@ public class FlowExecutor {
|
|||
MonitorFile.getInstance().addMonitorFilePaths(fileAbsolutePath);
|
||||
}
|
||||
|
||||
private List<Slot> doExecuteWithRoute(Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray){
|
||||
private List<Slot> doExecuteWithRoute(String namespace, Object param, String requestId, Class<?>[] contextBeanClazzArray, Object[] contextBeanArray){
|
||||
if (FlowBus.needInit()) {
|
||||
init(true);
|
||||
}
|
||||
|
||||
List<Chain> routeChainList = FlowBus.getChainMap().values().stream().filter(chain -> chain.getRouteItem() != null).collect(Collectors.toList());
|
||||
if (StrUtil.isBlank(namespace)){
|
||||
namespace = ChainConstant.DEFAULT_NAMESPACE;
|
||||
}
|
||||
|
||||
String finalNamespace = namespace;
|
||||
List<Chain> routeChainList = FlowBus.getChainMap().values().stream()
|
||||
.filter(chain -> chain.getNamespace().equals(finalNamespace))
|
||||
.filter(chain -> chain.getRouteItem() != null).collect(Collectors.toList());
|
||||
|
||||
if (CollUtil.isEmpty(routeChainList)){
|
||||
throw new RouteChainNotFoundException("cannot find any route chain");
|
||||
String errorMsg = StrUtil.format("no route found for namespace[{}]", finalNamespace);
|
||||
throw new RouteChainNotFoundException(errorMsg);
|
||||
}
|
||||
|
||||
String finalRequestId;
|
||||
|
@ -601,7 +626,7 @@ public class FlowExecutor {
|
|||
}
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
|
||||
LOG.info("There are {} chains that matched the route.", resultSlotList.size());
|
||||
LOG.info("chain namespace:[{}], total size:[{}], matched size:[{}]", namespace, routeChainList.size(), resultSlotList.size());
|
||||
|
||||
return resultSlotList;
|
||||
}
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
package com.yomahub.liteflow.core.proxy;
|
||||
|
||||
import cn.hutool.core.exceptions.InvocationTargetRuntimeException;
|
||||
import cn.hutool.core.lang.Tuple;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ql.util.express.DefaultContext;
|
||||
import com.ql.util.express.ExpressRunner;
|
||||
import com.ql.util.express.InstructionSet;
|
||||
import com.yomahub.liteflow.annotation.LiteflowMethod;
|
||||
import com.yomahub.liteflow.annotation.LiteflowRetry;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.exception.ComponentMethodDefineErrorException;
|
||||
import com.yomahub.liteflow.exception.LiteFlowException;
|
||||
import com.yomahub.liteflow.exception.ParameterFactException;
|
||||
import com.yomahub.liteflow.exception.ProxyException;
|
||||
import com.yomahub.liteflow.flow.element.Node;
|
||||
import com.yomahub.liteflow.log.LFLog;
|
||||
import com.yomahub.liteflow.log.LFLoggerManager;
|
||||
import com.yomahub.liteflow.slot.DataBus;
|
||||
import com.yomahub.liteflow.util.SerialsUtil;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
||||
|
@ -21,7 +28,12 @@ import java.lang.annotation.Annotation;
|
|||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -112,6 +124,10 @@ public class DeclComponentProxy {
|
|||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (currentMethodWrapBean == null){
|
||||
throw new ProxyException("currentMethodWrapBean is null");
|
||||
}
|
||||
|
||||
// 如果被代理的对象里有此标注标的方法,则调用此被代理的对象里的方法,如果没有,则调用父类里的方法
|
||||
// 进行检查,检查被代理的bean里是否第一个参数为NodeComponent这个类型的
|
||||
boolean checkFlag = currentMethodWrapBean.getMethod().getParameterTypes().length > 0
|
||||
|
@ -124,13 +140,13 @@ public class DeclComponentProxy {
|
|||
throw new ComponentMethodDefineErrorException(errMsg);
|
||||
}
|
||||
|
||||
|
||||
// 这里是针对于参数的处理
|
||||
// 首先需要保证第一个参数是NodeComponent
|
||||
// 其次需要针对于@LiteflowFact做处理
|
||||
try {
|
||||
if (args != null && args.length > 0){
|
||||
Object[] wrapArgs = ArrayUtil.insert(args, 0, proxy);
|
||||
return ReflectUtil.invoke(declWarpBean.getRawBean(), currentMethodWrapBean.getMethod(), wrapArgs);
|
||||
}else{
|
||||
return ReflectUtil.invoke(declWarpBean.getRawBean(), currentMethodWrapBean.getMethod(), proxy);
|
||||
}
|
||||
Object[] realArgs = loadMethodParameter(proxy, currentMethodWrapBean);
|
||||
return ReflectUtil.invoke(declWarpBean.getRawBean(), currentMethodWrapBean.getMethod(), realArgs);
|
||||
}catch (InvocationTargetRuntimeException e) {
|
||||
InvocationTargetException targetEx = (InvocationTargetException) e.getCause();
|
||||
throw targetEx.getTargetException();
|
||||
|
@ -138,4 +154,55 @@ public class DeclComponentProxy {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private final ExpressRunner expressRunner = new ExpressRunner();
|
||||
|
||||
private Object[] loadMethodParameter(Object proxy, MethodWrapBean methodWrapBean){
|
||||
NodeComponent thisNodeComponent = (NodeComponent) proxy;
|
||||
|
||||
return methodWrapBean.getParameterWrapBeanList().stream().map(parameterWrapBean -> {
|
||||
// 如果参数是NodeComponent,那就返回proxy本身
|
||||
if (parameterWrapBean.getParameterType().isAssignableFrom(NodeComponent.class)) {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
// 如果没有@LiteflowFact标注,那么不处理,直接赋值null
|
||||
if (parameterWrapBean.getFact() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 把上下文数据转换成map形式的,key为别名,value为上下文
|
||||
Map<String, Object> contextMap = DataBus.getSlot(thisNodeComponent.getSlotIndex()).getContextBeanList().stream().collect(
|
||||
Collectors.toMap(tuple -> tuple.get(0), tuple -> tuple.get(1))
|
||||
);
|
||||
|
||||
List<String> errorList = new ArrayList<>();
|
||||
|
||||
Object result = null;
|
||||
// 根据表达式去上下文里搜索相匹配的数据
|
||||
for(Map.Entry<String, Object> entry : contextMap.entrySet()){
|
||||
try{
|
||||
InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache(entry.getKey() + "." + parameterWrapBean.getFact().value());
|
||||
DefaultContext<String, Object> context = new DefaultContext<>();
|
||||
context.put(entry.getKey(), entry.getValue());
|
||||
result = expressRunner.execute(instructionSet, context, errorList, false, false);
|
||||
if (result != null){
|
||||
break;
|
||||
}
|
||||
}catch (Exception ignore){}
|
||||
}
|
||||
|
||||
if (result == null){
|
||||
try{
|
||||
// 如果没有搜到,那么尝试推断表达式是指定的上下文,按照指定上下文的方式去再获取
|
||||
InstructionSet instructionSet = expressRunner.getInstructionSetFromLocalCache("contextMap." + parameterWrapBean.getFact().value());
|
||||
DefaultContext<String, Object> context = new DefaultContext<>();
|
||||
context.put("contextMap", contextMap);
|
||||
result = expressRunner.execute(instructionSet, context, errorList, false, false);
|
||||
}catch (Exception ignore){}
|
||||
}
|
||||
|
||||
return result;
|
||||
}).toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.yomahub.liteflow.annotation.LiteflowMethod;
|
|||
import com.yomahub.liteflow.annotation.LiteflowRetry;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* LiteflowMethod的包装类
|
||||
|
@ -18,10 +19,13 @@ public class MethodWrapBean {
|
|||
|
||||
private LiteflowRetry liteflowRetry;
|
||||
|
||||
public MethodWrapBean(Method method, LiteflowMethod liteflowMethod, LiteflowRetry liteflowRetry) {
|
||||
private List<ParameterWrapBean> parameterWrapBeanList;
|
||||
|
||||
public MethodWrapBean(Method method, LiteflowMethod liteflowMethod, LiteflowRetry liteflowRetry, List<ParameterWrapBean> parameterWrapBeanList) {
|
||||
this.method = method;
|
||||
this.liteflowMethod = liteflowMethod;
|
||||
this.liteflowRetry = liteflowRetry;
|
||||
this.parameterWrapBeanList = parameterWrapBeanList;
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
|
@ -47,4 +51,12 @@ public class MethodWrapBean {
|
|||
public void setLiteflowRetry(LiteflowRetry liteflowRetry) {
|
||||
this.liteflowRetry = liteflowRetry;
|
||||
}
|
||||
|
||||
public List<ParameterWrapBean> getParameterWrapBeanList() {
|
||||
return parameterWrapBeanList;
|
||||
}
|
||||
|
||||
public void setParameterWrapBeanList(List<ParameterWrapBean> parameterWrapBeanList) {
|
||||
this.parameterWrapBeanList = parameterWrapBeanList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package com.yomahub.liteflow.core.proxy;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowFact;
|
||||
|
||||
/**
|
||||
* 声明式的包装类
|
||||
* @author Bryan.Zhang
|
||||
* @since 2.12.1
|
||||
*/
|
||||
public class ParameterWrapBean {
|
||||
|
||||
private Class<?> parameterType;
|
||||
|
||||
private LiteflowFact fact;
|
||||
|
||||
private int index;
|
||||
|
||||
public ParameterWrapBean(Class<?> parameterType, LiteflowFact fact, int index) {
|
||||
this.parameterType = parameterType;
|
||||
this.fact = fact;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Class<?> getParameterType() {
|
||||
return parameterType;
|
||||
}
|
||||
|
||||
public void setParameterType(Class<?> parameterType) {
|
||||
this.parameterType = parameterType;
|
||||
}
|
||||
|
||||
public LiteflowFact getFact() {
|
||||
return fact;
|
||||
}
|
||||
|
||||
public void setFact(LiteflowFact fact) {
|
||||
this.fact = fact;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
}
|
|
@ -2,13 +2,15 @@ package com.yomahub.liteflow.enums;
|
|||
|
||||
public enum ScriptTypeEnum {
|
||||
|
||||
CUSTOM("custom", "custom"),
|
||||
GROOVY("groovy", "groovy"),
|
||||
QLEXPRESS("qlexpress", "qlexpress"),
|
||||
JS("javascript", "js"),
|
||||
PYTHON("python", "python"),
|
||||
LUA("luaj", "lua"),
|
||||
AVIATOR("AviatorScript", "aviator"),
|
||||
JAVA("java", "java");
|
||||
JAVA("java", "java"),
|
||||
KOTLIN("kotlin", "kotlin");
|
||||
|
||||
private String engineName;
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package com.yomahub.liteflow.exception;
|
||||
|
||||
/**
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
public class ParameterFactException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 异常信息 */
|
||||
private String message;
|
||||
|
||||
public ParameterFactException(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
|
@ -40,6 +40,8 @@ public class Chain implements Executable{
|
|||
|
||||
private boolean isCompiled = true;
|
||||
|
||||
private String namespace;
|
||||
|
||||
public Chain(String chainName) {
|
||||
this.chainId = chainName;
|
||||
}
|
||||
|
@ -195,4 +197,12 @@ public class Chain implements Executable{
|
|||
public void setCompiled(boolean compiled) {
|
||||
isCompiled = compiled;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,29 +15,6 @@ import java.util.List;
|
|||
*/
|
||||
public class NodeConvertHelper {
|
||||
|
||||
/*script节点的修改/添加*/
|
||||
public static void changeScriptNode(NodeSimpleVO nodeSimpleVO, String newValue) {
|
||||
// 有语言类型
|
||||
if (StrUtil.isNotBlank(nodeSimpleVO.getLanguage())) {
|
||||
LiteFlowNodeBuilder.createScriptNode()
|
||||
.setId(nodeSimpleVO.getNodeId())
|
||||
.setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType()))
|
||||
.setName(nodeSimpleVO.getName())
|
||||
.setScript(newValue)
|
||||
.setLanguage(nodeSimpleVO.getLanguage())
|
||||
.build();
|
||||
}
|
||||
// 没有语言类型
|
||||
else {
|
||||
LiteFlowNodeBuilder.createScriptNode()
|
||||
.setId(nodeSimpleVO.getNodeId())
|
||||
.setType(NodeTypeEnum.getEnumByCode(nodeSimpleVO.getType()))
|
||||
.setName(nodeSimpleVO.getName())
|
||||
.setScript(newValue)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
public static NodeSimpleVO convert(String scriptKey){
|
||||
// 不需要去理解这串正则,就是一个匹配冒号的
|
||||
// 一定得是a:b,或是a:b:c...这种完整类型的字符串的
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.yomahub.liteflow.parser.helper;
|
||||
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
@ -24,6 +25,7 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.yomahub.liteflow.common.ChainConstant.*;
|
||||
|
||||
|
@ -205,7 +207,7 @@ public class ParserHelper {
|
|||
// 当存在<nodes>节点定义时,解析node节点
|
||||
if (flowJsonNode.get(FLOW).has(NODES)) {
|
||||
Iterator<JsonNode> nodeIterator = flowJsonNode.get(FLOW).get(NODES).get(NODE).elements();
|
||||
String id, name, clazz, script, type, file;
|
||||
String id, name, clazz, script, type, file, language;
|
||||
while ((nodeIterator.hasNext())) {
|
||||
JsonNode nodeObject = nodeIterator.next();
|
||||
id = nodeObject.get(ID).textValue();
|
||||
|
@ -214,6 +216,7 @@ public class ParserHelper {
|
|||
type = nodeObject.hasNonNull(TYPE) ? nodeObject.get(TYPE).textValue() : null;
|
||||
script = nodeObject.hasNonNull(VALUE) ? nodeObject.get(VALUE).textValue() : "";
|
||||
file = nodeObject.hasNonNull(FILE) ? nodeObject.get(FILE).textValue() : "";
|
||||
language = nodeObject.hasNonNull(LANGUAGE) ? nodeObject.get(LANGUAGE).textValue() : "";
|
||||
|
||||
// 如果是禁用的,就不编译了
|
||||
if (!getEnableByJsonNode(nodeObject)) {
|
||||
|
@ -226,7 +229,8 @@ public class ParserHelper {
|
|||
.setClazz(clazz)
|
||||
.setScript(script)
|
||||
.setType(type)
|
||||
.setFile(file);
|
||||
.setFile(file)
|
||||
.setLanguage(language);
|
||||
|
||||
ParserHelper.buildNode(nodePropBean);
|
||||
}
|
||||
|
@ -308,9 +312,11 @@ public class ParserHelper {
|
|||
// 构建chainBuilder
|
||||
String chainId = Optional.ofNullable(chainNode.get(ID)).orElse(chainNode.get(NAME)).textValue();
|
||||
|
||||
String namespace = chainNode.get(NAMESPACE) == null? DEFAULT_NAMESPACE : chainNode.get(NAMESPACE).textValue();
|
||||
|
||||
JsonNode routeJsonNode = chainNode.get(ROUTE);
|
||||
|
||||
LiteFlowChainELBuilder builder = LiteFlowChainELBuilder.createChain().setChainId(chainId);
|
||||
LiteFlowChainELBuilder builder = LiteFlowChainELBuilder.createChain().setChainId(chainId).setNamespace(namespace);
|
||||
|
||||
// 如果有route这个标签,说明是决策表chain
|
||||
// 决策表链路必须有route和body这两个标签
|
||||
|
@ -337,9 +343,11 @@ public class ParserHelper {
|
|||
// 构建chainBuilder
|
||||
String chainId = Optional.ofNullable(e.attributeValue(ID)).orElse(e.attributeValue(NAME));
|
||||
|
||||
String namespace = StrUtil.blankToDefault(e.attributeValue(NAMESPACE), DEFAULT_NAMESPACE);
|
||||
|
||||
Element routeElement = e.element(ROUTE);
|
||||
|
||||
LiteFlowChainELBuilder builder = LiteFlowChainELBuilder.createChain().setChainId(chainId);
|
||||
LiteFlowChainELBuilder builder = LiteFlowChainELBuilder.createChain().setChainId(chainId).setNamespace(namespace);
|
||||
|
||||
// 如果有route这个标签,说明是决策表chain
|
||||
// 决策表链路必须有route和body这两个标签
|
||||
|
@ -362,6 +370,7 @@ public class ParserHelper {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
builder.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.yomahub.liteflow.util;
|
|||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yomahub.liteflow.exception.JsonProcessException;
|
||||
|
@ -27,6 +28,7 @@ public class JsonUtil {
|
|||
|
||||
static {
|
||||
objectMapper.setTimeZone(TimeZone.getDefault());
|
||||
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
}
|
||||
|
||||
public static String toJsonString(Object object) {
|
||||
|
@ -71,5 +73,4 @@ public class JsonUtil {
|
|||
throw new JsonProcessException(errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,10 +13,13 @@
|
|||
type (script|boolean_script|switch_script|for_script) #IMPLIED
|
||||
class CDATA #IMPLIED
|
||||
file CDATA #IMPLIED
|
||||
language (qlexpress|groovy|js|python|lua|aviator|java) #IMPLIED
|
||||
language (qlexpress|groovy|js|python|lua|aviator|java|kotlin) #IMPLIED
|
||||
enable (true|false) #IMPLIED
|
||||
>
|
||||
<!ATTLIST chain
|
||||
id CDATA #IMPLIED
|
||||
name CDATA #IMPLIED
|
||||
extends CDATA #IMPLIED
|
||||
enable (true|false) #IMPLIED
|
||||
namespace CDATA #IMPLIED
|
||||
>
|
|
@ -16,7 +16,7 @@ public class SqlReadConstant {
|
|||
|
||||
public static final String SCRIPT_SQL_PATTERN = "SELECT * FROM {} WHERE {}=?";
|
||||
|
||||
public static final String CHAIN_XML_PATTERN = "<chain name=\"{}\"><![CDATA[{}]]></chain>";
|
||||
public static final String CHAIN_XML_PATTERN = "<chain id=\"{}\" namespace=\"{}\"><route><![CDATA[{}]]></route><body><![CDATA[{}]]></body></chain>";
|
||||
|
||||
public static final String NODE_XML_PATTERN = "<nodes>{}</nodes>";
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* sql 轮询任务抽象类,维护公共方法
|
||||
|
@ -19,11 +21,11 @@ import java.util.Set;
|
|||
* @author houxinyu
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public abstract class AbstractSqlReadPollTask implements SqlReadPollTask {
|
||||
public abstract class AbstractSqlReadPollTask<T> implements SqlReadPollTask<T> {
|
||||
private final Map<String/*唯一键*/, String/*data-xml的sha1值*/> DATA_SHA_MAP = new HashMap<>();
|
||||
private final SqlRead read;
|
||||
private final SqlRead<T> read;
|
||||
|
||||
public AbstractSqlReadPollTask(SqlRead read) {
|
||||
public AbstractSqlReadPollTask(SqlRead<T> read) {
|
||||
this.read = read;
|
||||
|
||||
if (!read.type().equals(type())) {
|
||||
|
@ -33,35 +35,34 @@ public abstract class AbstractSqlReadPollTask implements SqlReadPollTask {
|
|||
|
||||
@Override
|
||||
public void execute() {
|
||||
Map<String/*唯一键*/, String/*data-xml*/> newData = read.read();
|
||||
List<T> dataList = read.read();
|
||||
// 新增或者更新的元素
|
||||
Map<String, String> saveElementMap = new HashMap<>();
|
||||
List<T> saveElementList = new ArrayList<>();
|
||||
// 删除的元素
|
||||
List<String> deleteElementIds = new ArrayList<>();
|
||||
List<String> deleteElementIds;
|
||||
|
||||
for (Map.Entry<String, String> entry : newData.entrySet()) {
|
||||
String id = entry.getKey();
|
||||
String element = entry.getValue();
|
||||
String newSHA = DigestUtil.sha1Hex(element);
|
||||
for (T data : dataList) {
|
||||
String id = getKey(data);
|
||||
String newSHA = getNeedSha1Value(data);
|
||||
|
||||
// 新增
|
||||
// 如果封装的SHAMap中不存在该chain, 表示该元素为新增
|
||||
if (!DATA_SHA_MAP.containsKey(id)) {
|
||||
saveElementMap.put(id, element);
|
||||
saveElementList.add(data);
|
||||
|
||||
DATA_SHA_MAP.put(id, newSHA);
|
||||
}
|
||||
// 修改
|
||||
// SHA值发生变化,表示该元素的值已被修改,重新拉取变化的chain
|
||||
else if (!StrUtil.equals(newSHA, DATA_SHA_MAP.get(id))) {
|
||||
saveElementMap.put(id, element);
|
||||
saveElementList.add(data);
|
||||
|
||||
DATA_SHA_MAP.put(id, newSHA);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> oldIdList = DATA_SHA_MAP.keySet(); // 旧的 id 列表
|
||||
Set<String> newIdList = newData.keySet(); // 新的 id 列表
|
||||
Set<String> newIdList = dataList.stream().map(this::getKey).collect(Collectors.toSet()); // 新的 id 列表
|
||||
// 计算单差集
|
||||
// 计算集合的单差集,即只返回【oldIdList】中有,但是【newIdList】中没有的元素,例如:
|
||||
// subtractToList([1,2,3,4],[2,3,4,5]) -》 [1]
|
||||
|
@ -71,8 +72,8 @@ public abstract class AbstractSqlReadPollTask implements SqlReadPollTask {
|
|||
DATA_SHA_MAP.remove(id);
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(saveElementMap)) {
|
||||
doSave(saveElementMap);
|
||||
if (CollUtil.isNotEmpty(saveElementList)) {
|
||||
doSave(saveElementList);
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(deleteElementIds)) {
|
||||
|
@ -81,20 +82,34 @@ public abstract class AbstractSqlReadPollTask implements SqlReadPollTask {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void initData(Map<String/*唯一键*/, String/*data-xml的数据*/> dataMap) {
|
||||
DATA_SHA_MAP.putAll(shaMapValue(dataMap));
|
||||
public void initData(List<T> dataList) {
|
||||
DATA_SHA_MAP.putAll(shaValue(dataList));
|
||||
}
|
||||
|
||||
public abstract void doSave(Map<String, String> saveElementMap);
|
||||
public abstract void doSave(List<T> saveElementList);
|
||||
|
||||
public abstract void doDelete(List<String> deleteElementId);
|
||||
|
||||
private Map<String/*唯一键*/, String/*data-xml的sha1值*/> shaMapValue(Map<String, String> dataMap) {
|
||||
private Map<String/*唯一键*/, String/*data-xml的sha1值*/> shaValue(List<T> dataList) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
dataMap.forEach((k, v) -> {
|
||||
result.put(k, DigestUtil.sha1Hex(v));
|
||||
});
|
||||
|
||||
dataList.forEach(t -> result.put(getKey(t), DigestUtil.sha1Hex(getNeedSha1Value(t))));
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getNeedSha1Value(T data) {
|
||||
if (StrUtil.isBlank(getExtValue(data))) {
|
||||
return DigestUtil.sha1Hex(getValue(data));
|
||||
}else{
|
||||
return DigestUtil.sha1Hex(getValue(data) + "|||" + getExtValue(data));
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是chain,那就是返回chain的id,如果是script,那就返回script的id
|
||||
protected abstract String getKey(T t);
|
||||
|
||||
// 如果是chain,那就返回EL,如果是script,那就返回脚本数据
|
||||
protected abstract String getValue(T t);
|
||||
|
||||
// 如果是chain,那就返回route el,如果是script,这个不返回,因为script没有扩展value
|
||||
protected abstract String getExtValue(T t);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.yomahub.liteflow.parser.sql.polling;
|
|||
|
||||
import com.yomahub.liteflow.parser.constant.ReadType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -11,7 +12,7 @@ import java.util.Map;
|
|||
* @author houxinyu
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public interface SqlReadPollTask {
|
||||
public interface SqlReadPollTask<T> {
|
||||
|
||||
/**
|
||||
* 执行
|
||||
|
@ -21,9 +22,8 @@ public interface SqlReadPollTask {
|
|||
/**
|
||||
* 初始化数据
|
||||
*
|
||||
* @param dataMap 数据
|
||||
*/
|
||||
void initData(Map<String/*唯一键*/, String/*data-xml的数据*/> dataMap);
|
||||
void initData(List<T> dataList);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
package com.yomahub.liteflow.parser.sql.polling.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.parser.constant.ReadType;
|
||||
import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask;
|
||||
import com.yomahub.liteflow.parser.sql.read.SqlRead;
|
||||
import com.yomahub.liteflow.parser.sql.read.vo.ChainVO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* chain 读取任务
|
||||
|
@ -16,20 +19,20 @@ import java.util.Map;
|
|||
* @author houxinyu
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class ChainReadPollTask extends AbstractSqlReadPollTask {
|
||||
public class ChainReadPollTask extends AbstractSqlReadPollTask<ChainVO> {
|
||||
|
||||
public ChainReadPollTask(SqlRead read) {
|
||||
public ChainReadPollTask(SqlRead<ChainVO> read) {
|
||||
super(read);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSave(Map<String, String> saveElementMap) {
|
||||
for (Map.Entry<String, String> entry : saveElementMap.entrySet()) {
|
||||
String chainName = entry.getKey();
|
||||
String newData = entry.getValue();
|
||||
|
||||
LiteFlowChainELBuilder.createChain().setChainId(chainName).setEL(newData).build();
|
||||
}
|
||||
public void doSave(List<ChainVO> saveElementList) {
|
||||
saveElementList.forEach(chainVO ->
|
||||
LiteFlowChainELBuilder.createChain().setChainId(chainVO.getChainId())
|
||||
.setRoute(chainVO.getRoute())
|
||||
.setNamespace(chainVO.getNamespace())
|
||||
.setEL(chainVO.getBody())
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,6 +42,21 @@ public class ChainReadPollTask extends AbstractSqlReadPollTask {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey(ChainVO chainVO) {
|
||||
return chainVO.getChainId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getValue(ChainVO chainVO) {
|
||||
return chainVO.getBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getExtValue(ChainVO chainVO) {
|
||||
return chainVO.getRoute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadType type() {
|
||||
return ReadType.CHAIN;
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
package com.yomahub.liteflow.parser.sql.polling.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.builder.LiteFlowNodeBuilder;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.parser.constant.ReadType;
|
||||
import com.yomahub.liteflow.parser.helper.NodeConvertHelper;
|
||||
import com.yomahub.liteflow.parser.sql.polling.AbstractSqlReadPollTask;
|
||||
import com.yomahub.liteflow.parser.sql.read.SqlRead;
|
||||
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 脚本轮询任务
|
||||
|
@ -16,32 +21,45 @@ import java.util.Map;
|
|||
* @author houxinyu
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class ScriptReadPollTask extends AbstractSqlReadPollTask {
|
||||
public ScriptReadPollTask(SqlRead read) {
|
||||
public class ScriptReadPollTask extends AbstractSqlReadPollTask<ScriptVO> {
|
||||
public ScriptReadPollTask(SqlRead<ScriptVO> read) {
|
||||
super(read);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSave(Map<String, String> saveElementMap) {
|
||||
for (Map.Entry<String, String> entry : saveElementMap.entrySet()) {
|
||||
String scriptKey = entry.getKey();
|
||||
String newData = entry.getValue();
|
||||
|
||||
NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey);
|
||||
NodeConvertHelper.changeScriptNode(scriptVO, newData);
|
||||
}
|
||||
public void doSave(List<ScriptVO> saveElementList) {
|
||||
saveElementList.forEach(scriptVO -> LiteFlowNodeBuilder.createScriptNode()
|
||||
.setId(scriptVO.getNodeId())
|
||||
.setType(NodeTypeEnum.getEnumByCode(scriptVO.getType()))
|
||||
.setName(scriptVO.getName())
|
||||
.setScript(scriptVO.getScript())
|
||||
.setLanguage(scriptVO.getLanguage())
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDelete(List<String> deleteElementId) {
|
||||
for (String id : deleteElementId) {
|
||||
NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(id);
|
||||
|
||||
// 删除script
|
||||
FlowBus.unloadScriptNode(scriptVO.getNodeId());
|
||||
FlowBus.unloadScriptNode(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey(ScriptVO scriptVO) {
|
||||
return scriptVO.getNodeId();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getValue(ScriptVO scriptVO) {
|
||||
return scriptVO.getScript();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getExtValue(ScriptVO scriptVO) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadType type() {
|
||||
return ReadType.SCRIPT;
|
||||
|
|
|
@ -9,7 +9,9 @@ import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil;
|
|||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -20,7 +22,7 @@ import java.util.Map;
|
|||
* @author Bryan.Zhang
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public abstract class AbstractSqlRead implements SqlRead {
|
||||
public abstract class AbstractSqlRead<T> implements SqlRead<T> {
|
||||
public final SQLParserVO config;
|
||||
private static LFLog LOG = LFLoggerManager.getLogger(AbstractSqlRead.class);
|
||||
|
||||
|
@ -29,10 +31,10 @@ public abstract class AbstractSqlRead implements SqlRead {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Map<String/*规则唯一键*/, String/*规则内容*/> read() {
|
||||
public List<T> read() {
|
||||
// 如果不需要读取直接返回
|
||||
if (!needRead()) {
|
||||
return new HashMap<>();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
checkConfig();
|
||||
|
@ -40,7 +42,7 @@ public abstract class AbstractSqlRead implements SqlRead {
|
|||
// 如果允许,就打印 sql 语句
|
||||
logSqlIfEnable(sqlCmd);
|
||||
|
||||
Map<String/*规则唯一键*/, String/*规则*/> result = new HashMap<>();
|
||||
List<T> result = new ArrayList<>();
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
|
@ -54,9 +56,6 @@ public abstract class AbstractSqlRead implements SqlRead {
|
|||
rs = stmt.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
String xml = buildXmlElement(rs);
|
||||
String uniqueKey = buildXmlElementUniqueKey(rs);
|
||||
|
||||
if (hasEnableFiled()){
|
||||
boolean enable = getEnableFiledValue(rs);
|
||||
// 如果停用,直接跳过
|
||||
|
@ -64,7 +63,7 @@ public abstract class AbstractSqlRead implements SqlRead {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
result.put(uniqueKey, xml);
|
||||
result.add(parse(rs));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ELSQLException(e.getMessage());
|
||||
|
@ -76,6 +75,8 @@ public abstract class AbstractSqlRead implements SqlRead {
|
|||
return result;
|
||||
}
|
||||
|
||||
protected abstract T parse(ResultSet rs) throws SQLException;
|
||||
|
||||
/**
|
||||
* 是否包含启停字段
|
||||
*/
|
||||
|
@ -88,10 +89,6 @@ public abstract class AbstractSqlRead implements SqlRead {
|
|||
|
||||
public abstract String buildQuerySql();
|
||||
|
||||
public abstract String buildXmlElement(ResultSet rs) throws SQLException;
|
||||
|
||||
public abstract String buildXmlElementUniqueKey(ResultSet rs) throws SQLException;
|
||||
|
||||
public abstract void checkConfig();
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.yomahub.liteflow.parser.sql.read;
|
|||
|
||||
import com.yomahub.liteflow.parser.constant.ReadType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -11,14 +12,14 @@ import java.util.Map;
|
|||
* @author houxinyu
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public interface SqlRead {
|
||||
public interface SqlRead<T> {
|
||||
|
||||
/**
|
||||
* 读取
|
||||
*
|
||||
* @return 返回读取到的数据
|
||||
*/
|
||||
Map<String/*规则唯一键*/, String/*规则内容*/> read();
|
||||
List<T> read();
|
||||
|
||||
/**
|
||||
* 类型
|
||||
|
|
|
@ -19,8 +19,8 @@ import java.util.Map;
|
|||
* @since 2.11.1
|
||||
*/
|
||||
public class SqlReadFactory {
|
||||
private static final Map<ReadType, SqlRead> READ_MAP = new HashMap<>();
|
||||
private static final Map<ReadType, SqlReadPollTask> POLL_TASK_MAP = new HashMap<>();
|
||||
private static final Map<ReadType, SqlRead<?>> READ_MAP = new HashMap<>();
|
||||
private static final Map<ReadType, SqlReadPollTask<?>> POLL_TASK_MAP = new HashMap<>();
|
||||
|
||||
public static void registerRead(SQLParserVO config) {
|
||||
READ_MAP.put(ReadType.CHAIN, new ChainRead(config));
|
||||
|
@ -28,19 +28,21 @@ public class SqlReadFactory {
|
|||
}
|
||||
|
||||
public static void registerSqlReadPollTask(ReadType readType) {
|
||||
SqlRead sqlRead = getSqlRead(readType);
|
||||
SqlRead<?> sqlRead = getSqlRead(readType);
|
||||
if (ReadType.CHAIN.equals(readType)) {
|
||||
POLL_TASK_MAP.put(ReadType.CHAIN, new ChainReadPollTask(sqlRead));
|
||||
POLL_TASK_MAP.put(ReadType.CHAIN, new ChainReadPollTask((ChainRead)sqlRead));
|
||||
} else if (ReadType.SCRIPT.equals(readType)) {
|
||||
POLL_TASK_MAP.put(ReadType.SCRIPT, new ScriptReadPollTask(sqlRead));
|
||||
POLL_TASK_MAP.put(ReadType.SCRIPT, new ScriptReadPollTask((ScriptRead)sqlRead));
|
||||
}
|
||||
}
|
||||
|
||||
public static SqlRead getSqlRead(ReadType readType) {
|
||||
return READ_MAP.get(readType);
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> SqlRead<T> getSqlRead(ReadType readType) {
|
||||
return (SqlRead<T>)READ_MAP.get(readType);
|
||||
}
|
||||
|
||||
public static SqlReadPollTask getSqlReadPollTask(ReadType readType) {
|
||||
return POLL_TASK_MAP.get(readType);
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> SqlReadPollTask<T> getSqlReadPollTask(ReadType readType) {
|
||||
return (SqlReadPollTask<T>)POLL_TASK_MAP.get(readType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.yomahub.liteflow.parser.constant.ReadType;
|
|||
import com.yomahub.liteflow.parser.constant.SqlReadConstant;
|
||||
import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
|
||||
import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
|
||||
import com.yomahub.liteflow.parser.sql.read.vo.ChainVO;
|
||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
@ -17,12 +18,26 @@ import java.sql.SQLException;
|
|||
* @author houxinyu
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class ChainRead extends AbstractSqlRead {
|
||||
public class ChainRead extends AbstractSqlRead<ChainVO> {
|
||||
|
||||
public ChainRead(SQLParserVO config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChainVO parse(ResultSet rs) throws SQLException {
|
||||
ChainVO chainVO = new ChainVO();
|
||||
chainVO.setChainId(getStringFromRsWithCheck(rs, super.config.getChainNameField()));
|
||||
chainVO.setBody(getStringFromRsWithCheck(rs, super.config.getElDataField()));
|
||||
if (StrUtil.isNotBlank(super.config.getNamespaceField())){
|
||||
chainVO.setNamespace(getStringFromRs(rs, super.config.getNamespaceField()));
|
||||
}
|
||||
if (StrUtil.isNotBlank(super.config.getRouteField())){
|
||||
chainVO.setRoute(getStringFromRs(rs, super.config.getRouteField()));
|
||||
}
|
||||
return chainVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnableFiled() {
|
||||
String chainEnableField = super.config.getChainEnableField();
|
||||
|
@ -70,20 +85,6 @@ public class ChainRead extends AbstractSqlRead {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildXmlElement(ResultSet rs) throws SQLException {
|
||||
String elDataField = super.config.getElDataField();
|
||||
|
||||
return getStringFromRs(rs, elDataField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildXmlElementUniqueKey(ResultSet rs) throws SQLException {
|
||||
String chainNameField = super.config.getChainNameField();
|
||||
|
||||
return getStringFromRsWithCheck(rs, chainNameField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadType type() {
|
||||
return ReadType.CHAIN;
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.yomahub.liteflow.parser.constant.ReadType;
|
|||
import com.yomahub.liteflow.parser.constant.SqlReadConstant;
|
||||
import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
|
||||
import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
|
||||
import com.yomahub.liteflow.parser.sql.read.vo.ScriptVO;
|
||||
import com.yomahub.liteflow.parser.sql.util.LiteFlowJdbcUtil;
|
||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
|
||||
|
@ -24,12 +25,23 @@ import java.util.Objects;
|
|||
* @author houxinyu
|
||||
* @since 2.11.1
|
||||
*/
|
||||
public class ScriptRead extends AbstractSqlRead {
|
||||
public class ScriptRead extends AbstractSqlRead<ScriptVO> {
|
||||
|
||||
public ScriptRead(SQLParserVO config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ScriptVO parse(ResultSet rs) throws SQLException {
|
||||
ScriptVO scriptVO = new ScriptVO();
|
||||
scriptVO.setNodeId(getStringFromRsWithCheck(rs, super.config.getScriptIdField()));
|
||||
scriptVO.setName(getStringFromRs(rs, super.config.getScriptNameField()));
|
||||
scriptVO.setType(getStringFromRsWithCheck(rs, super.config.getScriptTypeField()));
|
||||
scriptVO.setLanguage(getStringFromRs(rs, super.config.getScriptLanguageField()));
|
||||
scriptVO.setScript(getStringFromRsWithCheck(rs, super.config.getScriptDataField()));
|
||||
return scriptVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEnableFiled() {
|
||||
String scriptEnableField = super.config.getScriptEnableField();
|
||||
|
@ -80,46 +92,6 @@ public class ScriptRead extends AbstractSqlRead {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildXmlElement(ResultSet rs) throws SQLException {
|
||||
String scriptDataField = super.config.getScriptDataField();
|
||||
|
||||
return getStringFromRs(rs, scriptDataField);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildXmlElementUniqueKey(ResultSet rs) throws SQLException {
|
||||
String scriptIdField = super.config.getScriptIdField();
|
||||
String scriptNameField = super.config.getScriptNameField();
|
||||
String scriptTypeField = super.config.getScriptTypeField();
|
||||
String scriptLanguageField = super.config.getScriptLanguageField();
|
||||
|
||||
String id = getStringFromRsWithCheck(rs, scriptIdField);
|
||||
String name = getStringFromRsWithCheck(rs, scriptNameField);
|
||||
String type = getStringFromRsWithCheck(rs, scriptTypeField);
|
||||
String language = withLanguage() ? getStringFromRs(rs, scriptLanguageField) : null;
|
||||
|
||||
NodeTypeEnum nodeTypeEnum = NodeTypeEnum.getEnumByCode(type);
|
||||
if (Objects.isNull(nodeTypeEnum)) {
|
||||
throw new ELSQLException(StrUtil.format("Invalid type value[{}]", type));
|
||||
}
|
||||
|
||||
if (!nodeTypeEnum.isScript()) {
|
||||
throw new ELSQLException(StrUtil.format("The type value[{}] is not a script type", type));
|
||||
}
|
||||
|
||||
if (withLanguage() && !ScriptTypeEnum.checkScriptType(language)) {
|
||||
throw new ELSQLException(StrUtil.format("The language value[{}] is invalid", language));
|
||||
}
|
||||
List<String> keys = CollUtil.newArrayList(id, type, name);
|
||||
if (StrUtil.isNotBlank(language)) {
|
||||
keys.add(language);
|
||||
}
|
||||
|
||||
return StrUtil.join(StrUtil.COLON, keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needRead() {
|
||||
if (StrUtil.isBlank(super.config.getScriptTableName())) {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package com.yomahub.liteflow.parser.sql.read.vo;
|
||||
|
||||
public class ChainVO {
|
||||
|
||||
private String chainId;
|
||||
|
||||
private String route;
|
||||
|
||||
private String namespace;
|
||||
|
||||
private String body;
|
||||
|
||||
public String getChainId() {
|
||||
return chainId;
|
||||
}
|
||||
|
||||
public void setChainId(String chainId) {
|
||||
this.chainId = chainId;
|
||||
}
|
||||
|
||||
public String getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public void setRoute(String route) {
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.yomahub.liteflow.parser.sql.read.vo;
|
||||
|
||||
public class ScriptVO {
|
||||
|
||||
private String nodeId;
|
||||
|
||||
private String type;
|
||||
|
||||
private String name;
|
||||
|
||||
private String language;
|
||||
|
||||
private Boolean enable;
|
||||
|
||||
private String script;
|
||||
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
public void setNodeId(String nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public Boolean getEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
public void setEnable(Boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
public void setScript(String script) {
|
||||
this.script = script;
|
||||
}
|
||||
}
|
|
@ -11,9 +11,12 @@ import com.yomahub.liteflow.parser.constant.ReadType;
|
|||
|
||||
import com.yomahub.liteflow.parser.helper.NodeConvertHelper;
|
||||
import com.yomahub.liteflow.parser.sql.exception.ELSQLException;
|
||||
import com.yomahub.liteflow.parser.sql.polling.SqlReadPollTask;
|
||||
import com.yomahub.liteflow.parser.sql.read.AbstractSqlRead;
|
||||
import com.yomahub.liteflow.parser.sql.read.SqlRead;
|
||||
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.ScriptVO;
|
||||
import com.yomahub.liteflow.parser.sql.vo.SQLParserVO;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
|
@ -87,30 +90,30 @@ public class JDBCHelper {
|
|||
* @return 数据内容
|
||||
*/
|
||||
public String getContent() {
|
||||
SqlRead chainRead = SqlReadFactory.getSqlRead(ReadType.CHAIN);
|
||||
SqlRead scriptRead = SqlReadFactory.getSqlRead(ReadType.SCRIPT);
|
||||
SqlRead<ChainVO> chainRead = SqlReadFactory.getSqlRead(ReadType.CHAIN);
|
||||
SqlRead<ScriptVO> scriptRead = SqlReadFactory.getSqlRead(ReadType.SCRIPT);
|
||||
|
||||
// 获取 chain 数据
|
||||
Map<String, String> chainMap = chainRead.read();
|
||||
List<ChainVO> chainVOList = chainRead.read();
|
||||
List<String> chainList = new ArrayList<>();
|
||||
|
||||
chainMap.entrySet().stream()
|
||||
.filter(entry -> StrUtil.isNotBlank(entry.getValue()))
|
||||
.forEach(
|
||||
entry -> chainList.add(StrUtil.format(CHAIN_XML_PATTERN, XmlUtil.escape(entry.getKey()), entry.getValue()))
|
||||
chainVOList.forEach(
|
||||
chainVO -> chainList.add(StrUtil.format(CHAIN_XML_PATTERN, XmlUtil.escape(chainVO.getChainId()), StrUtil.emptyIfNull(chainVO.getNamespace()), StrUtil.emptyIfNull(chainVO.getRoute()), chainVO.getBody()))
|
||||
);
|
||||
|
||||
|
||||
String chainsContent = CollUtil.join(chainList, StrUtil.EMPTY);
|
||||
|
||||
// 获取脚本数据
|
||||
Map<String, String> scriptMap = scriptRead.read();
|
||||
List<ScriptVO> scriptVOList = scriptRead.read();
|
||||
List<String> scriptList = new ArrayList<>();
|
||||
scriptMap.forEach((scriptKey, elData) -> {
|
||||
NodeConvertHelper.NodeSimpleVO scriptVO = NodeConvertHelper.convert(scriptKey);
|
||||
|
||||
scriptVOList.forEach(scriptVO -> {
|
||||
String id = scriptVO.getNodeId();
|
||||
String name = scriptVO.getName();
|
||||
String type = scriptVO.getType();
|
||||
String language = scriptVO.getLanguage();
|
||||
String elData = scriptVO.getScript();
|
||||
|
||||
if (StringUtils.isNotBlank(scriptVO.getLanguage())) {
|
||||
scriptList.add(StrUtil.format(NODE_ITEM_WITH_LANGUAGE_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, language, elData));
|
||||
|
@ -118,11 +121,14 @@ public class JDBCHelper {
|
|||
scriptList.add(StrUtil.format(NODE_ITEM_XML_PATTERN, XmlUtil.escape(id), XmlUtil.escape(name), type, elData));
|
||||
}
|
||||
});
|
||||
|
||||
String nodesContent = StrUtil.format(NODE_XML_PATTERN, CollUtil.join(scriptList, StrUtil.EMPTY));
|
||||
|
||||
// 初始化轮询任务
|
||||
SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN).initData(chainMap);
|
||||
SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT).initData(scriptMap);
|
||||
SqlReadPollTask<ChainVO> sqlReadPollTask4Chain = SqlReadFactory.getSqlReadPollTask(ReadType.CHAIN);
|
||||
sqlReadPollTask4Chain.initData(chainVOList);
|
||||
SqlReadPollTask<ScriptVO> sqlReadPollTask4Script = SqlReadFactory.getSqlReadPollTask(ReadType.SCRIPT);
|
||||
sqlReadPollTask4Script.initData(scriptVOList);
|
||||
return StrUtil.format(XML_PATTERN, nodesContent, chainsContent);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,16 @@ public class SQLParserVO {
|
|||
*/
|
||||
private String elDataField = "el_data";
|
||||
|
||||
/**
|
||||
* 决策路由字段
|
||||
*/
|
||||
private String routeField;
|
||||
|
||||
/**
|
||||
* 命名空间字段
|
||||
*/
|
||||
private String namespaceField;
|
||||
|
||||
/**
|
||||
* 是否启动某一条chain
|
||||
*/
|
||||
|
@ -310,4 +320,20 @@ public class SQLParserVO {
|
|||
public boolean hasEnableField() {
|
||||
return StrUtil.isNotBlank(chainEnableField) || StrUtil.isNotBlank(scriptEnableField);
|
||||
}
|
||||
|
||||
public String getRouteField() {
|
||||
return routeField;
|
||||
}
|
||||
|
||||
public void setRouteField(String routeField) {
|
||||
this.routeField = routeField;
|
||||
}
|
||||
|
||||
public String getNamespaceField() {
|
||||
return namespaceField;
|
||||
}
|
||||
|
||||
public void setNamespaceField(String namespaceField) {
|
||||
this.namespaceField = namespaceField;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>liteflow-script-plugin</artifactId>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>liteflow-script-kotlin</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-core</artifactId>
|
||||
<version>${revision}</version>
|
||||
<optional>true</optional>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-scripting-jsr223</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,15 @@
|
|||
package com.yomahub.liteflow.script.kotlin;
|
||||
|
||||
import com.yomahub.liteflow.enums.ScriptTypeEnum;
|
||||
import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
|
||||
|
||||
/**
|
||||
* Kotlin脚本执行器
|
||||
* @author DaleLee
|
||||
*/
|
||||
public class KotlinScriptExecutor extends JSR223ScriptExecutor {
|
||||
@Override
|
||||
public ScriptTypeEnum scriptType() {
|
||||
return ScriptTypeEnum.KOTLIN;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
# Kotlin的实现
|
||||
com.yomahub.liteflow.script.kotlin.KotlinScriptExecutor
|
|
@ -23,6 +23,7 @@
|
|||
<module>liteflow-script-lua</module>
|
||||
<module>liteflow-script-aviator</module>
|
||||
<module>liteflow-script-java</module>
|
||||
<module>liteflow-script-kotlin</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
|
@ -8,6 +8,7 @@ import cn.hutool.core.util.CharsetUtil;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.exception.ConfigErrorException;
|
||||
import com.yomahub.liteflow.spi.PathContentParser;
|
||||
import com.yomahub.liteflow.util.PathMatchUtil;
|
||||
import org.noear.solon.Utils;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -47,9 +48,10 @@ public class SolonPathContentParser implements PathContentParser {
|
|||
if (CollectionUtil.isEmpty(pathList)) {
|
||||
throw new ConfigErrorException("rule source must not be null");
|
||||
}
|
||||
|
||||
List<String> absolutePathList = PathMatchUtil.searchAbsolutePath(pathList);
|
||||
List<URL> allResource = new ArrayList<>();
|
||||
for (String path : pathList) {
|
||||
|
||||
for (String path : absolutePathList) {
|
||||
// 如果 path 是绝对路径且这个文件存在时,我们认为这是一个本地文件路径,而并非classpath路径
|
||||
if (FileUtil.isAbsolutePath(path) && FileUtil.isFile(path)) {
|
||||
allResource.add(new File(path).toURI().toURL());
|
||||
|
|
|
@ -1,24 +1,27 @@
|
|||
package com.yomahub.liteflow.spi.spring;
|
||||
|
||||
import cn.hutool.core.annotation.AnnotationUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.yomahub.liteflow.annotation.LiteflowCmpDefine;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.annotation.LiteflowMethod;
|
||||
import com.yomahub.liteflow.annotation.LiteflowRetry;
|
||||
import com.yomahub.liteflow.annotation.*;
|
||||
import com.yomahub.liteflow.annotation.util.AnnoUtil;
|
||||
import com.yomahub.liteflow.core.proxy.DeclWarpBean;
|
||||
import com.yomahub.liteflow.core.proxy.MethodWrapBean;
|
||||
import com.yomahub.liteflow.core.proxy.ParameterWrapBean;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.exception.CmpDefinitionException;
|
||||
import com.yomahub.liteflow.spi.DeclComponentParser;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* Spring环境声明式组件解析器实现
|
||||
|
@ -73,7 +76,16 @@ public class SpringDeclComponentParser implements DeclComponentParser {
|
|||
nodeType = liteflowMethod.nodeType();
|
||||
}
|
||||
|
||||
return new DeclInfo(currNodeId, currNodeName, nodeType, method.getDeclaringClass(), new MethodWrapBean(method, liteflowMethod, liteflowRetry));
|
||||
|
||||
Parameter[] parameters = method.getParameters();
|
||||
List<ParameterWrapBean> parameterList = IntStream.range(0, parameters.length).boxed().map(index -> {
|
||||
Parameter parameter = parameters[index];
|
||||
return new ParameterWrapBean(parameter.getType(), AnnotationUtil.getAnnotation(parameter, LiteflowFact.class), index);
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
|
||||
|
||||
return new DeclInfo(currNodeId, currNodeName, nodeType, method.getDeclaringClass(), new MethodWrapBean(method, liteflowMethod, liteflowRetry, parameterList));
|
||||
}).filter(declInfo -> StrUtil.isNotBlank(declInfo.getNodeId())).collect(Collectors.groupingBy(DeclInfo::getNodeId));
|
||||
|
||||
return definitionMap.entrySet().stream().map(entry -> {
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.junit.jupiter.api.AfterAll;
|
|||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIf;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -63,6 +64,29 @@ public class AbsoluteConfigPathELDeclMultiSpringbootTest extends BaseTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledIf("isWindows")
|
||||
public void testAbsPath() throws Exception{
|
||||
Assertions.assertTrue(() -> {
|
||||
LiteflowConfig config = LiteflowConfigGetter.get();
|
||||
config.setRuleSource(StrUtil.format("{}\\sub\\**\\*.xml",rootDir));
|
||||
flowExecutor.reloadRule();
|
||||
return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isWindows() {
|
||||
try {
|
||||
String osName = System.getProperty("os.name");
|
||||
if (osName.isEmpty()) return false;
|
||||
else {
|
||||
return osName.contains("Windows");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void createFiles() {
|
||||
rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package com.yomahub.liteflow.test.processFact;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import com.yomahub.liteflow.test.processFact.context.*;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* process方法上的fact映射参数测试
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/processFact/application.properties")
|
||||
@SpringBootTest(classes = ProcessFactELDeclMultiSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.processFact.cmp"})
|
||||
public class ProcessFactELDeclMultiSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
// 最基本的情况
|
||||
@Test
|
||||
public void testFact1() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", createContext());
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
TestContext context = response.getContextBean(TestContext.class);
|
||||
Assertions.assertEquals("jack", context.getUser().getName());
|
||||
}
|
||||
|
||||
// 多上下文自动搜寻
|
||||
@Test
|
||||
public void testFact2() throws Exception {
|
||||
TestContext testContext = createContext();
|
||||
Demo1Context demo1Context = new Demo1Context();
|
||||
demo1Context.setData1("xxxx");
|
||||
demo1Context.setData2(99);
|
||||
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg", demo1Context, testContext);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
TestContext context = response.getContextBean(TestContext.class);
|
||||
Assertions.assertEquals(20, context.getUser().getCompany().getHeadCount());
|
||||
}
|
||||
|
||||
// 多上下文都有user,指定上下文中的user
|
||||
@Test
|
||||
public void testFact3() throws Exception {
|
||||
TestContext testContext = createContext();
|
||||
Demo2Context demo2Context = createDemo2Context();
|
||||
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg", testContext, demo2Context);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Demo2Context context = response.getContextBean(Demo2Context.class);
|
||||
Assertions.assertEquals("rose", context.getUser().getName());
|
||||
}
|
||||
|
||||
// 多上下文都有user,指定上下文中的user
|
||||
@Test
|
||||
public void testFact4() throws Exception {
|
||||
Demo3Context demo3Context = createDemo3Context();
|
||||
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg", demo3Context);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Demo3Context context = response.getContextBean(Demo3Context.class);
|
||||
Assertions.assertEquals("jelly", context.getUser().getName());
|
||||
}
|
||||
|
||||
private TestContext createContext(){
|
||||
Company company = new Company("XXX有限公司", "黄河路34号303室", 400);
|
||||
User user = new User("张三", 18, DateUtil.parseDate("1990-08-20"), company);
|
||||
return new TestContext(user, "this is data");
|
||||
}
|
||||
|
||||
private Demo2Context createDemo2Context(){
|
||||
Company company = new Company("XXX有限公司", "和平路12号101室", 600);
|
||||
User user = new User("李四", 28, DateUtil.parseDate("1990-06-01"), company);
|
||||
return new Demo2Context("xxx", user);
|
||||
}
|
||||
|
||||
private Demo3Context createDemo3Context(){
|
||||
Company company = new Company("XXX有限公司", "和平路12号101室", 600);
|
||||
User user = new User("王五", 28, DateUtil.parseDate("1990-06-01"), company);
|
||||
return new Demo3Context("xxx", user);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.yomahub.liteflow.test.processFact.cmp;
|
||||
|
||||
import cn.hutool.core.collection.ConcurrentHashSet;
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.annotation.LiteflowFact;
|
||||
import com.yomahub.liteflow.annotation.LiteflowMethod;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.processFact.context.Company;
|
||||
import com.yomahub.liteflow.test.processFact.context.User;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@LiteflowComponent
|
||||
public class CmpConfig {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "a")
|
||||
public void processA(NodeComponent bindCmp,
|
||||
@LiteflowFact("user") User user,
|
||||
@LiteflowFact("user.company.address") String address) {
|
||||
user.setName("jack");
|
||||
}
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "b")
|
||||
public void processB(NodeComponent bindCmp,
|
||||
@LiteflowFact("user.company") Company company,
|
||||
@LiteflowFact("data2") Integer data) {
|
||||
company.setHeadCount(20);
|
||||
}
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "c")
|
||||
public void processC(NodeComponent bindCmp,
|
||||
@LiteflowFact("demo2Context.user") User user) {
|
||||
user.setName("rose");
|
||||
}
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "d")
|
||||
public void processD(NodeComponent bindCmp,
|
||||
@LiteflowFact("ctx.user") User user) {
|
||||
user.setName("jelly");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
public class Company {
|
||||
|
||||
private String name;
|
||||
|
||||
private String address;
|
||||
|
||||
private int headCount;
|
||||
|
||||
public Company(String name, String address, int headCount) {
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.headCount = headCount;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public int getHeadCount() {
|
||||
return headCount;
|
||||
}
|
||||
|
||||
public void setHeadCount(int headCount) {
|
||||
this.headCount = headCount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
public class Demo1Context {
|
||||
|
||||
private String data1;
|
||||
|
||||
private Integer data2;
|
||||
|
||||
public String getData1() {
|
||||
return data1;
|
||||
}
|
||||
|
||||
public void setData1(String data1) {
|
||||
this.data1 = data1;
|
||||
}
|
||||
|
||||
public Integer getData2() {
|
||||
return data2;
|
||||
}
|
||||
|
||||
public void setData2(Integer data2) {
|
||||
this.data2 = data2;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
public class Demo2Context {
|
||||
|
||||
private String data1;
|
||||
|
||||
private User user;
|
||||
|
||||
public Demo2Context(String data1, User user) {
|
||||
this.data1 = data1;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getData1() {
|
||||
return data1;
|
||||
}
|
||||
|
||||
public void setData1(String data1) {
|
||||
this.data1 = data1;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
import com.yomahub.liteflow.context.ContextBean;
|
||||
|
||||
@ContextBean("ctx")
|
||||
public class Demo3Context {
|
||||
|
||||
private String data1;
|
||||
|
||||
private User user;
|
||||
|
||||
public Demo3Context(String data1, User user) {
|
||||
this.data1 = data1;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getData1() {
|
||||
return data1;
|
||||
}
|
||||
|
||||
public void setData1(String data1) {
|
||||
this.data1 = data1;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
public class TestContext {
|
||||
|
||||
private User user;
|
||||
|
||||
private String data1;
|
||||
|
||||
public TestContext(User user, String data1) {
|
||||
this.user = user;
|
||||
this.data1 = data1;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getData1() {
|
||||
return data1;
|
||||
}
|
||||
|
||||
public void setData1(String data1) {
|
||||
this.data1 = data1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class User {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private Date birthday;
|
||||
|
||||
private Company company;
|
||||
|
||||
public User(String name, int age, Date birthday, Company company) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.birthday = birthday;
|
||||
this.company = company;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public Company getCompany() {
|
||||
return company;
|
||||
}
|
||||
|
||||
public void setCompany(Company company) {
|
||||
this.company = company;
|
||||
}
|
||||
|
||||
public Date getBirthday() {
|
||||
return birthday;
|
||||
}
|
||||
|
||||
public void setBirthday(Date birthday) {
|
||||
this.birthday = birthday;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
liteflow.rule-source=processFact/flow.xml
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
THEN(a);
|
||||
</chain>
|
||||
|
||||
<chain name="chain2">
|
||||
THEN(b);
|
||||
</chain>
|
||||
|
||||
<chain name="chain3">
|
||||
THEN(c);
|
||||
</chain>
|
||||
|
||||
<chain name="chain4">
|
||||
THEN(d);
|
||||
</chain>
|
||||
</flow>
|
|
@ -15,6 +15,7 @@ import org.junit.jupiter.api.AfterAll;
|
|||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIf;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -65,6 +66,29 @@ public class AbsoluteConfigPathELDeclSpringbootTest extends BaseTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledIf("isWindows")
|
||||
public void testAbsPath() throws Exception{
|
||||
Assertions.assertTrue(() -> {
|
||||
LiteflowConfig config = LiteflowConfigGetter.get();
|
||||
config.setRuleSource(StrUtil.format("{}\\sub\\**\\*.xml",rootDir));
|
||||
flowExecutor.reloadRule();
|
||||
return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isWindows() {
|
||||
try {
|
||||
String osName = System.getProperty("os.name");
|
||||
if (osName.isEmpty()) return false;
|
||||
else {
|
||||
return osName.contains("Windows");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void createFiles() {
|
||||
rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package com.yomahub.liteflow.test.processFact;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import com.yomahub.liteflow.test.processFact.context.*;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* process方法上的fact映射参数测试
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/processFact/application.properties")
|
||||
@SpringBootTest(classes = ProcessFactELDeclSpringbootTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.processFact.cmp"})
|
||||
public class ProcessFactELDeclSpringbootTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
// 最基本的情况
|
||||
@Test
|
||||
public void testFact1() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", createContext());
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
TestContext context = response.getContextBean(TestContext.class);
|
||||
Assertions.assertEquals("jack", context.getUser().getName());
|
||||
}
|
||||
|
||||
// 多上下文自动搜寻
|
||||
@Test
|
||||
public void testFact2() throws Exception {
|
||||
TestContext testContext = createContext();
|
||||
Demo1Context demo1Context = new Demo1Context();
|
||||
demo1Context.setData1("xxxx");
|
||||
demo1Context.setData2(99);
|
||||
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg", demo1Context, testContext);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
TestContext context = response.getContextBean(TestContext.class);
|
||||
Assertions.assertEquals(20, context.getUser().getCompany().getHeadCount());
|
||||
}
|
||||
|
||||
// 多上下文都有user,指定上下文中的user
|
||||
@Test
|
||||
public void testFact3() throws Exception {
|
||||
TestContext testContext = createContext();
|
||||
Demo2Context demo2Context = createDemo2Context();
|
||||
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg", testContext, demo2Context);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Demo2Context context = response.getContextBean(Demo2Context.class);
|
||||
Assertions.assertEquals("rose", context.getUser().getName());
|
||||
}
|
||||
|
||||
// 多上下文都有user,指定上下文中的user
|
||||
@Test
|
||||
public void testFact4() throws Exception {
|
||||
Demo3Context demo3Context = createDemo3Context();
|
||||
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg", demo3Context);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Demo3Context context = response.getContextBean(Demo3Context.class);
|
||||
Assertions.assertEquals("jelly", context.getUser().getName());
|
||||
}
|
||||
|
||||
private TestContext createContext(){
|
||||
Company company = new Company("XXX有限公司", "黄河路34号303室", 400);
|
||||
User user = new User("张三", 18, DateUtil.parseDate("1990-08-20"), company);
|
||||
return new TestContext(user, "this is data");
|
||||
}
|
||||
|
||||
private Demo2Context createDemo2Context(){
|
||||
Company company = new Company("XXX有限公司", "和平路12号101室", 600);
|
||||
User user = new User("李四", 28, DateUtil.parseDate("1990-06-01"), company);
|
||||
return new Demo2Context("xxx", user);
|
||||
}
|
||||
|
||||
private Demo3Context createDemo3Context(){
|
||||
Company company = new Company("XXX有限公司", "和平路12号101室", 600);
|
||||
User user = new User("王五", 28, DateUtil.parseDate("1990-06-01"), company);
|
||||
return new Demo3Context("xxx", user);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.processFact.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowFact;
|
||||
import com.yomahub.liteflow.annotation.LiteflowMethod;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.test.processFact.context.User;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@Component("a")
|
||||
public class ACmp {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON)
|
||||
public void process(NodeComponent bindCmp,
|
||||
@LiteflowFact("user") User user,
|
||||
@LiteflowFact("user.company.address") String address) {
|
||||
user.setName("jack");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.processFact.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowFact;
|
||||
import com.yomahub.liteflow.annotation.LiteflowMethod;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.test.processFact.context.Company;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("b")
|
||||
public class BCmp {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON)
|
||||
public void process(NodeComponent bindCmp,
|
||||
@LiteflowFact("user.company") Company company,
|
||||
@LiteflowFact("data2") Integer data) {
|
||||
company.setHeadCount(20);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.processFact.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowFact;
|
||||
import com.yomahub.liteflow.annotation.LiteflowMethod;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.test.processFact.context.User;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("c")
|
||||
public class CCmp {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON)
|
||||
public void process(NodeComponent bindCmp,
|
||||
@LiteflowFact("demo2Context.user") User user) {
|
||||
user.setName("rose");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.processFact.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowFact;
|
||||
import com.yomahub.liteflow.annotation.LiteflowMethod;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
|
||||
import com.yomahub.liteflow.enums.NodeTypeEnum;
|
||||
import com.yomahub.liteflow.test.processFact.context.User;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("d")
|
||||
public class DCmp {
|
||||
|
||||
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON)
|
||||
public void process(NodeComponent bindCmp,
|
||||
@LiteflowFact("ctx.user") User user) {
|
||||
user.setName("jelly");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
public class Company {
|
||||
|
||||
private String name;
|
||||
|
||||
private String address;
|
||||
|
||||
private int headCount;
|
||||
|
||||
public Company(String name, String address, int headCount) {
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.headCount = headCount;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public int getHeadCount() {
|
||||
return headCount;
|
||||
}
|
||||
|
||||
public void setHeadCount(int headCount) {
|
||||
this.headCount = headCount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
public class Demo1Context {
|
||||
|
||||
private String data1;
|
||||
|
||||
private Integer data2;
|
||||
|
||||
public String getData1() {
|
||||
return data1;
|
||||
}
|
||||
|
||||
public void setData1(String data1) {
|
||||
this.data1 = data1;
|
||||
}
|
||||
|
||||
public Integer getData2() {
|
||||
return data2;
|
||||
}
|
||||
|
||||
public void setData2(Integer data2) {
|
||||
this.data2 = data2;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
public class Demo2Context {
|
||||
|
||||
private String data1;
|
||||
|
||||
private User user;
|
||||
|
||||
public Demo2Context(String data1, User user) {
|
||||
this.data1 = data1;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getData1() {
|
||||
return data1;
|
||||
}
|
||||
|
||||
public void setData1(String data1) {
|
||||
this.data1 = data1;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
import com.yomahub.liteflow.context.ContextBean;
|
||||
|
||||
@ContextBean("ctx")
|
||||
public class Demo3Context {
|
||||
|
||||
private String data1;
|
||||
|
||||
private User user;
|
||||
|
||||
public Demo3Context(String data1, User user) {
|
||||
this.data1 = data1;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getData1() {
|
||||
return data1;
|
||||
}
|
||||
|
||||
public void setData1(String data1) {
|
||||
this.data1 = data1;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
public class TestContext {
|
||||
|
||||
private User user;
|
||||
|
||||
private String data1;
|
||||
|
||||
public TestContext(User user, String data1) {
|
||||
this.user = user;
|
||||
this.data1 = data1;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getData1() {
|
||||
return data1;
|
||||
}
|
||||
|
||||
public void setData1(String data1) {
|
||||
this.data1 = data1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.yomahub.liteflow.test.processFact.context;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class User {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private Date birthday;
|
||||
|
||||
private Company company;
|
||||
|
||||
public User(String name, int age, Date birthday, Company company) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.birthday = birthday;
|
||||
this.company = company;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public Company getCompany() {
|
||||
return company;
|
||||
}
|
||||
|
||||
public void setCompany(Company company) {
|
||||
this.company = company;
|
||||
}
|
||||
|
||||
public Date getBirthday() {
|
||||
return birthday;
|
||||
}
|
||||
|
||||
public void setBirthday(Date birthday) {
|
||||
this.birthday = birthday;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
liteflow.rule-source=processFact/flow.xml
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow>
|
||||
<chain name="chain1">
|
||||
THEN(a);
|
||||
</chain>
|
||||
|
||||
<chain name="chain2">
|
||||
THEN(b);
|
||||
</chain>
|
||||
|
||||
<chain name="chain3">
|
||||
THEN(c);
|
||||
</chain>
|
||||
|
||||
<chain name="chain4">
|
||||
THEN(d);
|
||||
</chain>
|
||||
</flow>
|
|
@ -14,6 +14,7 @@ import org.junit.jupiter.api.AfterAll;
|
|||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIf;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -50,6 +51,29 @@ public class AbsoluteConfigPathTest extends BaseTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledIf("isWindows")
|
||||
public void testAbsPath() throws Exception{
|
||||
Assertions.assertTrue(() -> {
|
||||
LiteflowConfig config = new LiteflowConfig();
|
||||
config.setRuleSource(StrUtil.format("{}\\sub\\**\\*.xml",rootDir));
|
||||
flowExecutor = FlowExecutorHolder.loadInstance(config);
|
||||
return flowExecutor.execute2Resp("chain1", "arg").isSuccess();
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isWindows() {
|
||||
try {
|
||||
String osName = System.getProperty("os.name");
|
||||
if (osName.isEmpty()) return false;
|
||||
else {
|
||||
return osName.contains("Windows");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void createFiles() {
|
||||
rootDir = FileUtil.getAbsolutePath(ResourceUtil.getResource("").getPath());
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package com.yomahub.liteflow.test.namespace;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.exception.NoMatchedRouteChainException;
|
||||
import com.yomahub.liteflow.exception.RouteChainNotFoundException;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
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;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* springboot环境EL常规的例子测试
|
||||
*
|
||||
* @author Bryan.Zhang
|
||||
*/
|
||||
@TestPropertySource(value = "classpath:/namespace/application.properties")
|
||||
@SpringBootTest(classes = RouteSpringbootNamespaceTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.namespace.cmp" })
|
||||
public class RouteSpringbootNamespaceTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
// n1 space中的两个链路都能匹配
|
||||
@Test
|
||||
public void testNamespaceRoute1() throws Exception {
|
||||
List<LiteflowResponse> responseList = flowExecutor.executeRouteChain("n1", 15, DefaultContext.class);
|
||||
LiteflowResponse response1 = responseList.stream().filter(
|
||||
liteflowResponse -> liteflowResponse.getChainId().equals("r_chain1")
|
||||
).findFirst().orElse(null);
|
||||
|
||||
assert response1 != null;
|
||||
Assertions.assertTrue(response1.isSuccess());
|
||||
Assertions.assertEquals("b==>a", response1.getExecuteStepStr());
|
||||
|
||||
LiteflowResponse response2 = responseList.stream().filter(
|
||||
liteflowResponse -> liteflowResponse.getChainId().equals("r_chain2")
|
||||
).findFirst().orElse(null);
|
||||
|
||||
assert response2 != null;
|
||||
Assertions.assertTrue(response2.isSuccess());
|
||||
Assertions.assertEquals("a==>b", response2.getExecuteStepStr());
|
||||
}
|
||||
|
||||
// n1这个namespace中没有规则被匹配上
|
||||
@Test
|
||||
public void testNamespaceRoute2() throws Exception {
|
||||
Assertions.assertThrows(NoMatchedRouteChainException.class, () -> flowExecutor.executeRouteChain("n1", 8, DefaultContext.class));
|
||||
}
|
||||
|
||||
// 没有n3这个namespace
|
||||
@Test
|
||||
public void testNamespaceRoute3() throws Exception {
|
||||
Assertions.assertThrows(RouteChainNotFoundException.class, () -> flowExecutor.executeRouteChain("n3", 8, DefaultContext.class));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.namespace.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.namespace.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.namespace.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeBooleanComponent;
|
||||
|
||||
@LiteflowComponent("r1")
|
||||
public class R1 extends NodeBooleanComponent {
|
||||
@Override
|
||||
public boolean processBoolean() throws Exception {
|
||||
int testInt = this.getRequestData();
|
||||
return testInt >= 10 && testInt <= 20;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.yomahub.liteflow.test.namespace.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeBooleanComponent;
|
||||
|
||||
@LiteflowComponent("r2")
|
||||
public class R2 extends NodeBooleanComponent {
|
||||
@Override
|
||||
public boolean processBoolean() throws Exception {
|
||||
int testInt = this.getRequestData();
|
||||
return testInt > 100;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
liteflow.rule-source=namespace/flow.el.xml
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE flow PUBLIC "liteflow" "liteflow.dtd">
|
||||
<flow>
|
||||
<chain name="r_chain1" namespace="n1">
|
||||
<route>
|
||||
r1
|
||||
</route>
|
||||
<body>
|
||||
THEN(b,a);
|
||||
</body>
|
||||
</chain>
|
||||
|
||||
<chain name="r_chain2" namespace="n1">
|
||||
<route>
|
||||
OR(r1,r2)
|
||||
</route>
|
||||
<body>
|
||||
THEN(a,b);
|
||||
</body>
|
||||
</chain>
|
||||
|
||||
<chain name="r_chain3" namespace="n2">
|
||||
<route>
|
||||
r2
|
||||
</route>
|
||||
<body>
|
||||
THEN(b,b);
|
||||
</body>
|
||||
</chain>
|
||||
</flow>
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>liteflow-testcase-el</artifactId>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>liteflow-testcase-el-script-kotlin-springboot</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-spring-boot-starter</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.yomahub</groupId>
|
||||
<artifactId>liteflow-script-kotlin</artifactId>
|
||||
<version>${revision}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,24 @@
|
|||
package com.yomahub.liteflow.test.script;
|
||||
|
||||
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();
|
||||
FlowBus.clearStat();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.cmpdata;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.script.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/cmpdata/application.properties")
|
||||
@SpringBootTest(classes = LiteFlowCmpDataKotlinScriptELTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.script.kotlin.cmpdata.cmp" })
|
||||
public class LiteFlowCmpDataKotlinScriptELTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testCmpData1() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("1995-10-01", context.getData("s1"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.cmpdata.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println(this.getCmpData(String.class));
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.common;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.script.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* Kotlin 脚本测试
|
||||
*
|
||||
* @author DaleLee
|
||||
*/
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/common/application.properties")
|
||||
@SpringBootTest(classes = LiteFlowKotlinScriptCommonELTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.script.kotlin.common.cmp"})
|
||||
public class LiteFlowKotlinScriptCommonELTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testCommonScript1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("testCommonScript1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals(Integer.valueOf(5), context.getData("s1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForScript1() {
|
||||
DefaultContext context = new DefaultContext();
|
||||
context.setData("k1", 1);
|
||||
context.setData("k2", 2);
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("testForScript1", "arg", context);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("s2==>a==>a==>a", response.getExecuteStepStr());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBooleanScript1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("testBooleanScript1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("s3==>b", response.getExecuteStepStr());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBooleanScript2() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("testBooleanScript2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("s4", response.getExecuteStepStr());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBooleanScript3() {
|
||||
DefaultContext context = new DefaultContext();
|
||||
context.setData("count", 2);
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("testBooleanScript3", "arg", context);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("s3==>b==>s6==>s3==>b==>s6==>s3==>b==>s6",response.getExecuteStepStr());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitchScript1() {
|
||||
DefaultContext context = new DefaultContext();
|
||||
context.setData("id", "c");
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("testSwitchScript1", "arg", context);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("s5==>c", response.getExecuteStepStr());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileScript1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("testFileScript1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals(Integer.valueOf(6), context.getData("s7"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.common.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.common.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.common.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.contextbean;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.test.script.BaseTest;
|
||||
import com.yomahub.liteflow.test.script.kotlin.contextbean.bean.CheckContext;
|
||||
import com.yomahub.liteflow.test.script.kotlin.contextbean.bean.Order2Context;
|
||||
import com.yomahub.liteflow.test.script.kotlin.contextbean.bean.OrderContext;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/contextbean/application.properties")
|
||||
@SpringBootTest(classes = LiteFlowScriptContextbeanKotlinELTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.script.kotlin.contextbean.cmp",
|
||||
"com.yomahub.liteflow.test.script.kotlin.contextbean.bean" })
|
||||
public class LiteFlowScriptContextbeanKotlinELTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testContextBean1() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg", OrderContext.class, CheckContext.class,
|
||||
Order2Context.class);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
OrderContext orderContext = response.getContextBean(OrderContext.class);
|
||||
CheckContext checkContext = response.getContextBean(CheckContext.class);
|
||||
Order2Context order2Context = response.getContextBean(Order2Context.class);
|
||||
Assertions.assertEquals("order1", orderContext.getOrderNo());
|
||||
Assertions.assertEquals("sign1", checkContext.getSign());
|
||||
Assertions.assertEquals("order2", order2Context.getOrderNo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContextBean2() throws Exception {
|
||||
OrderContext orderContext = new OrderContext();
|
||||
orderContext.setOrderNo("order1");
|
||||
CheckContext checkContext = new CheckContext();
|
||||
checkContext.setSign("sign1");
|
||||
Order2Context orderContext2 = new Order2Context();
|
||||
orderContext2.setOrderNo("order2");
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain2", null, orderContext, checkContext,
|
||||
orderContext2);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.contextbean.bean;
|
||||
|
||||
import com.yomahub.liteflow.context.ContextBean;
|
||||
|
||||
@ContextBean
|
||||
public class CheckContext {
|
||||
|
||||
private String sign;
|
||||
|
||||
private int randomId;
|
||||
|
||||
public String getSign() {
|
||||
return sign;
|
||||
}
|
||||
|
||||
public void setSign(String sign) {
|
||||
this.sign = sign;
|
||||
}
|
||||
|
||||
public int getRandomId() {
|
||||
return randomId;
|
||||
}
|
||||
|
||||
public void setRandomId(int randomId) {
|
||||
this.randomId = randomId;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.contextbean.bean;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class Order2Context {
|
||||
|
||||
private String orderNo;
|
||||
|
||||
private int orderType;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
public String getOrderNo() {
|
||||
return orderNo;
|
||||
}
|
||||
|
||||
public void setOrderNo(String orderNo) {
|
||||
this.orderNo = orderNo;
|
||||
}
|
||||
|
||||
public int getOrderType() {
|
||||
return orderType;
|
||||
}
|
||||
|
||||
public void setOrderType(int orderType) {
|
||||
this.orderType = orderType;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.contextbean.bean;
|
||||
|
||||
import com.yomahub.liteflow.context.ContextBean;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ContextBean("order")
|
||||
public class OrderContext {
|
||||
|
||||
private String orderNo;
|
||||
|
||||
private int orderType;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
public String getOrderNo() {
|
||||
return orderNo;
|
||||
}
|
||||
|
||||
public void setOrderNo(String orderNo) {
|
||||
this.orderNo = orderNo;
|
||||
}
|
||||
|
||||
public int getOrderType() {
|
||||
return orderType;
|
||||
}
|
||||
|
||||
public void setOrderType(int orderType) {
|
||||
this.orderType = orderType;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.contextbean.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.contextbean.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.contextbean.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.meta;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.script.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/meta/application.properties")
|
||||
@SpringBootTest(classes = LiteflowKotlinScriptMetaELTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"com.yomahub.liteflow.test.script.kotlin.meta.cmp"})
|
||||
public class LiteflowKotlinScriptMetaELTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testMeta() {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Assertions.assertEquals("chain1", context.getData("currChainId"));
|
||||
Assertions.assertEquals("arg", context.getData("requestData"));
|
||||
Assertions.assertEquals("s1", context.getData("nodeId"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.meta.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.meta.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.meta.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.refresh;
|
||||
|
||||
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.test.script.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/refresh/application.properties")
|
||||
@SpringBootTest(classes = LiteflowKotlinScriptRefreshELTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.script.kotlin.refresh.cmp" })
|
||||
public class LiteflowKotlinScriptRefreshELTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
// 测试脚本的热重载
|
||||
@Test
|
||||
public void testRefresh1() throws Exception {
|
||||
// 根据配置,加载的应该是flow.xml,执行原来的规则
|
||||
LiteflowResponse responseOld = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assertions.assertTrue(responseOld.isSuccess());
|
||||
Assertions.assertEquals("d==>s1[选择脚本]==>a", responseOld.getExecuteStepStr());
|
||||
// 更改规则,重新加载,更改的规则内容从flow_update.xml里读取,这里只是为了模拟下获取新的内容。不一定是从文件中读取
|
||||
String newContent = ResourceUtil.readUtf8Str("classpath: /refresh/flow_update.xml");
|
||||
// 进行刷新
|
||||
FlowBus.refreshFlowMetaData(FlowParserTypeEnum.TYPE_EL_XML, newContent);
|
||||
|
||||
// 重新执行chain2这个链路,结果会变
|
||||
LiteflowResponse responseNew = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assertions.assertTrue(responseNew.isSuccess());
|
||||
Assertions.assertEquals("d==>s1[选择脚本_改]==>b==>s2[普通脚本_新增]", responseNew.getExecuteStepStr());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.refresh.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.refresh.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.refresh.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
|
||||
@LiteflowComponent("c")
|
||||
public class CCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("CCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.refresh.cmp;
|
||||
|
||||
import com.yomahub.liteflow.annotation.LiteflowComponent;
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
|
||||
@LiteflowComponent("d")
|
||||
public class DCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
DefaultContext context = this.getFirstContextBean();
|
||||
context.setData("count", 198);
|
||||
System.out.println("DCmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.remove;
|
||||
|
||||
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.enums.ScriptTypeEnum;
|
||||
import com.yomahub.liteflow.exception.ELParseException;
|
||||
import com.yomahub.liteflow.flow.FlowBus;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.script.ScriptExecutor;
|
||||
import com.yomahub.liteflow.script.ScriptExecutorFactory;
|
||||
import com.yomahub.liteflow.script.exception.ScriptLoadException;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.script.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 测试脚本的卸载和重载功能
|
||||
*
|
||||
* @author DaleLee
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/remove/application.properties")
|
||||
@SpringBootTest(classes = LiteFlowKotlinScriptRemoveELTest.class)
|
||||
@EnableAutoConfiguration
|
||||
public class LiteFlowKotlinScriptRemoveELTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
private ScriptExecutor scriptExecutor = ScriptExecutorFactory.loadInstance()
|
||||
.getScriptExecutor(ScriptTypeEnum.KOTLIN.getDisplayName());
|
||||
|
||||
// 仅卸载脚本
|
||||
@Test
|
||||
public void testUnload() {
|
||||
flowExecutor.reloadRule();
|
||||
|
||||
// 获取节点id
|
||||
List<String> nodeIds = scriptExecutor.getNodeIds();
|
||||
Assertions.assertEquals(2, nodeIds.size());
|
||||
Assertions.assertTrue(nodeIds.contains("s1"));
|
||||
Assertions.assertTrue(nodeIds.contains("s2"));
|
||||
|
||||
// 保证脚本可以正常运行
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals(Integer.valueOf(6), context.getData("s1"));
|
||||
|
||||
// 卸载脚本
|
||||
scriptExecutor.unLoad("s1");
|
||||
response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assertions.assertFalse(response.isSuccess());
|
||||
Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass());
|
||||
Assertions.assertEquals("script for node[s1] is not loaded", response.getMessage());
|
||||
|
||||
// 脚本已卸载
|
||||
Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s1"));
|
||||
}
|
||||
|
||||
// 卸载节点和脚本
|
||||
@Test
|
||||
public void testRemove() {
|
||||
flowExecutor.reloadRule();
|
||||
|
||||
// 保证脚本可以正常运行
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals(Integer.valueOf(5), context.getData("s2"));
|
||||
|
||||
// 卸载节点
|
||||
FlowBus.unloadScriptNode("s2");
|
||||
|
||||
// 旧 chain 报脚本加载错误
|
||||
response = flowExecutor.execute2Resp("chain2", "arg");
|
||||
Assertions.assertEquals(ScriptLoadException.class, response.getCause().getClass());
|
||||
|
||||
// 新 chian 会找不到节点
|
||||
Assertions.assertThrows(ELParseException.class,
|
||||
() -> LiteFlowChainELBuilder.createChain()
|
||||
.setChainId("chain3")
|
||||
.setEL("THEN(s2)")
|
||||
.build());
|
||||
|
||||
// 节点已卸载
|
||||
Assertions.assertFalse(FlowBus.containNode("s2"));
|
||||
// 脚本已卸载
|
||||
Assertions.assertFalse(scriptExecutor.getNodeIds().contains("s2"));
|
||||
}
|
||||
|
||||
// 重载脚本
|
||||
@Test
|
||||
public void testReloadScript() {
|
||||
flowExecutor.reloadRule();
|
||||
String script = "(bindings[\"defaultContext\"] as? DefaultContext)?.setData(\"s1\", \"abc\")";
|
||||
FlowBus.reloadScript("s1", script);
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
// 执行结果变更
|
||||
Assertions.assertEquals("abc", context.getData("s1"));
|
||||
// 脚本变更
|
||||
Assertions.assertEquals(FlowBus.getNode("s1").getScript(), script);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.scriptbean;
|
||||
|
||||
import com.yomahub.liteflow.core.FlowExecutor;
|
||||
import com.yomahub.liteflow.exception.ScriptBeanMethodInvokeException;
|
||||
import com.yomahub.liteflow.flow.LiteflowResponse;
|
||||
import com.yomahub.liteflow.script.ScriptBeanManager;
|
||||
import com.yomahub.liteflow.slot.DefaultContext;
|
||||
import com.yomahub.liteflow.test.script.BaseTest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
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.junit.jupiter.SpringExtension;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@TestPropertySource(value = "classpath:/scriptbean/application.properties")
|
||||
@SpringBootTest(classes = LiteFlowScriptScriptbeanKotlinELTest.class)
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({ "com.yomahub.liteflow.test.script.kotlin.scriptbean.cmp",
|
||||
"com.yomahub.liteflow.test.script.kotlin.scriptbean.bean" })
|
||||
public class LiteFlowScriptScriptbeanKotlinELTest extends BaseTest {
|
||||
|
||||
@Resource
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@Test
|
||||
public void testScriptBean1() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals("hello", context.getData("demo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScriptBean2() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals("hello,kobe", context.getData("demo"));
|
||||
}
|
||||
|
||||
// 测试scriptBean includeMethodName配置包含情况下
|
||||
@Test
|
||||
public void testScriptBean3() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals("hello,kobe", context.getData("demo"));
|
||||
}
|
||||
|
||||
// 测试scriptBean includeMethodName配置不包含情况下
|
||||
@Test
|
||||
public void testScriptBean4() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
|
||||
Assertions.assertFalse(response.isSuccess());
|
||||
Assertions.assertEquals(ScriptBeanMethodInvokeException.class, response.getCause().getClass());
|
||||
}
|
||||
|
||||
// 测试scriptBean excludeMethodName配置不包含情况下
|
||||
@Test
|
||||
public void testScriptBean5() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain5", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals("hello,kobe", context.getData("demo"));
|
||||
}
|
||||
|
||||
// 测试scriptBean excludeMethodName配置包含情况下
|
||||
@Test
|
||||
public void testScriptBean6() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain6", "arg");
|
||||
Assertions.assertFalse(response.isSuccess());
|
||||
Assertions.assertEquals(ScriptBeanMethodInvokeException.class, response.getCause().getClass());
|
||||
}
|
||||
|
||||
// 测试在ScriptBeanManager里放入上下文,实现自定义脚本引用名称
|
||||
@Test
|
||||
public void testScriptBean7() throws Exception {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
ScriptBeanManager.addScriptBean("abcCx", map);
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain7", "arg", map);
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
Map<String, String> context = response.getFirstContextBean();
|
||||
Assertions.assertEquals("hello", context.get("demo"));
|
||||
}
|
||||
|
||||
//测试用构造方法的方式注入bean的场景
|
||||
@Test
|
||||
public void testScriptBean8() throws Exception {
|
||||
LiteflowResponse response = flowExecutor.execute2Resp("chain8", "arg");
|
||||
Assertions.assertTrue(response.isSuccess());
|
||||
DefaultContext context = response.getFirstContextBean();
|
||||
Assertions.assertEquals("hello,jordan", context.getData("demo"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.scriptbean.bean;
|
||||
|
||||
import com.yomahub.liteflow.script.annotation.ScriptBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Component
|
||||
@ScriptBean("demo")
|
||||
public class DemoBean1 {
|
||||
|
||||
@Resource
|
||||
private DemoBean2 demoBean2;
|
||||
|
||||
public String getDemoStr1() {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
public String getDemoStr2(String name) {
|
||||
return demoBean2.getDemoStr2(name);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.scriptbean.bean;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class DemoBean2 {
|
||||
|
||||
public String getDemoStr2(String name) {
|
||||
return "hello," + name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.scriptbean.bean;
|
||||
|
||||
import com.yomahub.liteflow.script.annotation.ScriptBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ScriptBean(name = "demo3", includeMethodName = { "test1", "test2" })
|
||||
public class DemoBean3 {
|
||||
|
||||
public String test1(String name) {
|
||||
return "hello," + name;
|
||||
}
|
||||
|
||||
public String test2(String name) {
|
||||
return "hello," + name;
|
||||
}
|
||||
|
||||
public String test3(String name) {
|
||||
return "hello," + name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.scriptbean.bean;
|
||||
|
||||
import com.yomahub.liteflow.script.annotation.ScriptBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ScriptBean(name = "demo4", excludeMethodName = { "test2", "test3" })
|
||||
public class DemoBean4 {
|
||||
|
||||
public String test1(String name) {
|
||||
return "hello," + name;
|
||||
}
|
||||
|
||||
public String test2(String name) {
|
||||
return "hello," + name;
|
||||
}
|
||||
|
||||
public String test3(String name) {
|
||||
return "hello," + name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.yomahub.liteflow.test.script.kotlin.scriptbean.bean;
|
||||
|
||||
import com.yomahub.liteflow.script.annotation.ScriptBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ScriptBean("demo5")
|
||||
public class DemoBean5 {
|
||||
|
||||
private final DemoBean2 demoBean2;
|
||||
|
||||
public DemoBean5(DemoBean2 demoBean2) {
|
||||
this.demoBean2 = demoBean2;
|
||||
}
|
||||
|
||||
public String getDemoStr1() {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
public String getDemoStr2(String name) {
|
||||
return demoBean2.getDemoStr2(name);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.scriptbean.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("a")
|
||||
public class ACmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("ACmp executed!");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* <p>Title: liteflow</p>
|
||||
* <p>Description: 轻量级的组件式流程框架</p>
|
||||
* @author Bryan.Zhang
|
||||
* @email weenyc31@163.com
|
||||
* @Date 2020/4/1
|
||||
*/
|
||||
package com.yomahub.liteflow.test.script.kotlin.scriptbean.cmp;
|
||||
|
||||
import com.yomahub.liteflow.core.NodeComponent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("b")
|
||||
public class BCmp extends NodeComponent {
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
System.out.println("BCmp executed!");
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue