From 07edfbde8888936fc3639d0903e8d7c0279d5b62 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 4 Apr 2023 15:56:42 +0800 Subject: [PATCH 01/24] add lombok dependency --- engine/pom.xml | 5 +++++ pom.xml | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/engine/pom.xml b/engine/pom.xml index 90995706..20b05675 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -83,6 +83,11 @@ com.google.guava guava + + org.projectlombok + lombok + provided + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 72dc8fc1..92d3d5e6 100644 --- a/pom.xml +++ b/pom.xml @@ -67,6 +67,7 @@ 1.2.83 2.3.7 31.0.1-jre + 1.18.26 @@ -136,6 +137,12 @@ guava ${guava.version} + + org.projectlombok + lombok + ${lombok.version} + provided + From e150aa69af896a8a15aeb180928204d379ec2390 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 4 Apr 2023 16:16:30 +0800 Subject: [PATCH 02/24] rebuild IdGenerator and ExpressionCalculator with SPI --- .../engine/executor/ElementExecutor.java | 6 +- .../engine/executor/RuntimeExecutor.java | 51 +++++++++++-- .../engine/processor/DefinitionProcessor.java | 10 +-- .../turbo/engine/spi/SingletonSPI.java | 14 ++++ .../turbo/engine/spi/TurboServiceLoader.java | 73 +++++++++++++++++++ .../calulator}/ExpressionCalculator.java | 9 ++- .../ExpressionCalculatorManager.java | 36 +++++++++ .../GroovyExpressionCalculator.java | 10 +-- .../spi/generator/IdGenerateManager.java | 33 +++++++++ .../engine/spi/generator/IdGenerator.java | 18 +++++ .../generator}/StrongUuidGenerator.java | 6 +- .../turbo/engine/util/IdGenerator.java | 7 -- ....engine.spi.calulator.ExpressionCalculator | 1 + ...bal.turbo.engine.spi.generator.IdGenerator | 1 + .../turbo/engine/util/IdGeneratorTest.java | 2 + 15 files changed, 249 insertions(+), 28 deletions(-) create mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java create mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java rename engine/src/main/java/com/didiglobal/turbo/engine/{util => spi/calulator}/ExpressionCalculator.java (65%) create mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorManager.java rename engine/src/main/java/com/didiglobal/turbo/engine/{util/impl => spi/calulator}/GroovyExpressionCalculator.java (88%) create mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateManager.java create mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java rename engine/src/main/java/com/didiglobal/turbo/engine/{util => spi/generator}/StrongUuidGenerator.java (83%) delete mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/util/IdGenerator.java create mode 100644 engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator create mode 100644 engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java index 1efecfde..72f96b74 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java @@ -12,7 +12,7 @@ import com.didiglobal.turbo.engine.exception.SuspendException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.model.InstanceData; -import com.didiglobal.turbo.engine.util.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculatorManager; import com.didiglobal.turbo.engine.util.FlowModelUtil; import com.didiglobal.turbo.engine.util.InstanceDataUtil; import org.apache.commons.lang3.StringUtils; @@ -29,7 +29,7 @@ public abstract class ElementExecutor extends RuntimeExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(ElementExecutor.class); @Resource - protected ExpressionCalculator expressionCalculator; + protected ExpressionCalculatorManager expressionCalculatorManager; @Override public void execute(RuntimeContext runtimeContext) throws ProcessException { @@ -320,6 +320,6 @@ private FlowElement calculateOutgoing(FlowElement flowElement, Map instanceDataMap) throws ProcessException { Map dataMap = InstanceDataUtil.parseInstanceDataMap(instanceDataMap); - return expressionCalculator.calculate(expression, dataMap); + return expressionCalculatorManager.getExpressionCalculator().calculate(expression, dataMap); } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java index 30f1fa29..38bad5a3 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java @@ -6,11 +6,13 @@ import com.didiglobal.turbo.engine.dao.NodeInstanceDAO; import com.didiglobal.turbo.engine.dao.NodeInstanceLogDAO; import com.didiglobal.turbo.engine.exception.ProcessException; -import com.didiglobal.turbo.engine.util.IdGenerator; -import com.didiglobal.turbo.engine.util.StrongUuidGenerator; +import com.didiglobal.turbo.engine.spi.generator.IdGenerateManager; import javax.annotation.Resource; +/** + * runtime executor + */ public abstract class RuntimeExecutor { @Resource @@ -25,22 +27,61 @@ public abstract class RuntimeExecutor { @Resource protected NodeInstanceLogDAO nodeInstanceLogDAO; - private static final IdGenerator ID_GENERATOR = new StrongUuidGenerator(); - + @Resource + private IdGenerateManager idGenerateManager; protected String genId() { - return ID_GENERATOR.getNextId(); + return idGenerateManager.getIdGenerator().getNextId(); } + /** + * execute the process + * + * @param runtimeContext runtime context information + * @throws ProcessException the exception thrown during execution + */ public abstract void execute(RuntimeContext runtimeContext) throws ProcessException; + /** + * commit and continue the process + * + * @param runtimeContext runtime context information + * @throws ProcessException the exception thrown during execution + */ public abstract void commit(RuntimeContext runtimeContext) throws ProcessException; + /** + * roll back to the previous user node + * + * @param runtimeContext runtime context information + * @throws ProcessException the exception thrown during execution + */ public abstract void rollback(RuntimeContext runtimeContext) throws ProcessException; + /** + * determine whether the process has been completed + * + * @param runtimeContext runtime context information + * @return true or false + * @throws ProcessException the exception thrown during execution + */ protected abstract boolean isCompleted(RuntimeContext runtimeContext) throws ProcessException; + /** + * get the current execute executor + * + * @param runtimeContext runtime context information + * @return execute executor + * @throws ProcessException the exception thrown during execution + */ protected abstract RuntimeExecutor getExecuteExecutor(RuntimeContext runtimeContext) throws ProcessException; + /** + * get the rollback executor + * + * @param runtimeContext runtime context information + * @return rollback executor + * @throws ProcessException the exception thrown during execution + */ protected abstract RuntimeExecutor getRollbackExecutor(RuntimeContext runtimeContext) throws ProcessException; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java b/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java index 169ba87f..d9f81b9e 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java @@ -17,8 +17,7 @@ import com.didiglobal.turbo.engine.param.GetFlowModuleParam; import com.didiglobal.turbo.engine.param.UpdateFlowParam; import com.didiglobal.turbo.engine.result.*; -import com.didiglobal.turbo.engine.util.IdGenerator; -import com.didiglobal.turbo.engine.util.StrongUuidGenerator; +import com.didiglobal.turbo.engine.spi.generator.IdGenerateManager; import com.didiglobal.turbo.engine.validator.ModelValidator; import com.didiglobal.turbo.engine.validator.ParamValidator; import org.apache.commons.lang3.StringUtils; @@ -35,7 +34,8 @@ public class DefinitionProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(DefinitionProcessor.class); - private static final IdGenerator idGenerator = new StrongUuidGenerator(); + @Resource + private IdGenerateManager idGenerateManager; @Resource private ModelValidator modelValidator; @@ -53,7 +53,7 @@ public CreateFlowResult create(CreateFlowParam createFlowParam) { FlowDefinitionPO flowDefinitionPO = new FlowDefinitionPO(); BeanUtils.copyProperties(createFlowParam, flowDefinitionPO); - String flowModuleId = idGenerator.getNextId(); + String flowModuleId = idGenerateManager.getIdGenerator().getNextId(); flowDefinitionPO.setFlowModuleId(flowModuleId); flowDefinitionPO.setStatus(FlowDefinitionStatus.INIT); Date date = new Date(); @@ -118,7 +118,7 @@ public DeployFlowResult deploy(DeployFlowParam deployFlowParam) { FlowDeploymentPO flowDeploymentPO = new FlowDeploymentPO(); BeanUtils.copyProperties(flowDefinitionPO, flowDeploymentPO); - String flowDeployId = idGenerator.getNextId(); + String flowDeployId = idGenerateManager.getIdGenerator().getNextId(); flowDeploymentPO.setFlowDeployId(flowDeployId); flowDeploymentPO.setStatus(FlowDeploymentStatus.DEPLOYED); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java new file mode 100644 index 00000000..beb35437 --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java @@ -0,0 +1,14 @@ +package com.didiglobal.turbo.engine.spi; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface SingletonSPI { + + +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java new file mode 100644 index 00000000..f31fac02 --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java @@ -0,0 +1,73 @@ +package com.didiglobal.turbo.engine.spi; + +import com.google.common.base.Preconditions; +import lombok.Getter; +import lombok.SneakyThrows; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; + +/** + *

turbo service loader

+ * + * @param the type of service + */ +public class TurboServiceLoader { + + private static final Map, TurboServiceLoader> LOADERS = new ConcurrentHashMap<>(); + + private final Class serviceInterface; + + @Getter + private final Collection services; + + private TurboServiceLoader(final Class serviceInterface){ + this.serviceInterface = serviceInterface; + validate(); + services = load(); + } + + private Collection load() { + Collection result = new LinkedList<>(); + for (T each : ServiceLoader.load(serviceInterface)) { + result.add(each); + } + return result; + } + + private void validate() { + Preconditions.checkNotNull(serviceInterface, "SPI interface is null."); + Preconditions.checkArgument(serviceInterface.isInterface(), "SPI interface `%s` is not interface.", serviceInterface); + } + + @SuppressWarnings("unchecked") + public static Collection getServiceInterfaces(final Class serviceInterface){ + TurboServiceLoader result = LOADERS.get(serviceInterface); + return (Collection) (result != null ? result.getServiceInterfaces(): LOADERS.computeIfAbsent(serviceInterface, TurboServiceLoader::new).getServiceInterfaces()); + + } + + private Collection getServiceInterfaces() { + return serviceInterface.getAnnotation(SingletonSPI.class) == null ? createNewServiceInstances() : getSingletonServiceInstances(); + + } + + private Collection getSingletonServiceInstances() { + return services; + + } + + @SneakyThrows(ReflectiveOperationException.class) + @SuppressWarnings("unchecked") + private Collection createNewServiceInstances() { + Collection result = new LinkedList<>(); + for (Object each : services) { + result.add((T) each.getClass().getDeclaredConstructor().newInstance()); + } + return result; + } +} + diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/ExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java similarity index 65% rename from engine/src/main/java/com/didiglobal/turbo/engine/util/ExpressionCalculator.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java index 2a854c71..93de2097 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/ExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java @@ -1,9 +1,14 @@ -package com.didiglobal.turbo.engine.util; +package com.didiglobal.turbo.engine.spi.calulator; import com.didiglobal.turbo.engine.exception.ProcessException; +import com.didiglobal.turbo.engine.spi.SingletonSPI; import java.util.Map; +/** + * turbo outgoing condition calculator + */ +@SingletonSPI public interface ExpressionCalculator { /** @@ -12,7 +17,7 @@ public interface ExpressionCalculator { * @param expression conditional expression * @param dataMap data for calculate * @return true or false - * @throws ProcessException + * @throws ProcessException the exception thrown during execution */ Boolean calculate(String expression, Map dataMap) throws ProcessException; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorManager.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorManager.java new file mode 100644 index 00000000..a6963424 --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorManager.java @@ -0,0 +1,36 @@ +package com.didiglobal.turbo.engine.spi.calulator; + +import com.didiglobal.turbo.engine.spi.TurboServiceLoader; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Optional; + +/** + * expression calculator manager + */ +@Service +public class ExpressionCalculatorManager { + + /** + * expression calculator + */ + private ExpressionCalculator expressionCalculator; + + public ExpressionCalculator getExpressionCalculator(){ + if(expressionCalculator != null){ + return expressionCalculator; + } + + synchronized (ExpressionCalculatorManager.class){ + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); + // In the order in which the services are loaded, take the first implementation + Optional optional = serviceInterfaces.stream().findFirst(); + if(optional.isPresent()){ + expressionCalculator = optional.get(); + return expressionCalculator; + } + return null; + } + } +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/impl/GroovyExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java similarity index 88% rename from engine/src/main/java/com/didiglobal/turbo/engine/util/impl/GroovyExpressionCalculator.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java index bbafe930..90e85354 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/impl/GroovyExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java @@ -1,19 +1,19 @@ -package com.didiglobal.turbo.engine.util.impl; +package com.didiglobal.turbo.engine.spi.calulator; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.ProcessException; -import com.didiglobal.turbo.engine.util.ExpressionCalculator; import com.didiglobal.turbo.engine.util.GroovyUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; import java.text.MessageFormat; import java.util.Map; -@Service +/** + * Implementation of calculator that uses script based on `Groovy` + */ public class GroovyExpressionCalculator implements ExpressionCalculator { private static final Logger LOGGER = LoggerFactory.getLogger(GroovyExpressionCalculator.class); @@ -30,7 +30,7 @@ public Boolean calculate(String expression, Map dataMap) throws return (Boolean) result; } else { LOGGER.warn("the result of expression is not boolean.||expression={}||result={}||dataMap={}", - expression, result, JSON.toJSONString(dataMap)); + expression, result, JSON.toJSONString(dataMap)); throw new ProcessException(ErrorEnum.GROOVY_CALCULATE_FAILED.getErrNo(), "expression is not instanceof bool."); } } catch (Exception e) { diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateManager.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateManager.java new file mode 100644 index 00000000..f23c6225 --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateManager.java @@ -0,0 +1,33 @@ +package com.didiglobal.turbo.engine.spi.generator; + +import com.didiglobal.turbo.engine.spi.TurboServiceLoader; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Optional; + +@Service +public class IdGenerateManager { + + /** + * id generator + */ + private IdGenerator idGenerator; + + public IdGenerator getIdGenerator(){ + if(idGenerator != null){ + return idGenerator; + } + + synchronized (IdGenerateManager.class){ + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(IdGenerator.class); + // In the order in which the services are loaded, take the first implementation + Optional optional = serviceInterfaces.stream().findFirst(); + if(optional.isPresent()){ + idGenerator = optional.get(); + return idGenerator; + } + return null; + } + } +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java new file mode 100644 index 00000000..c76ca24d --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java @@ -0,0 +1,18 @@ +package com.didiglobal.turbo.engine.spi.generator; + +import com.didiglobal.turbo.engine.spi.SingletonSPI; + +/** + * turbo id generator + */ +@SingletonSPI +public interface IdGenerator { + + /** + * Get the next ID + * + * @return ID + */ + String getNextId(); + +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/StrongUuidGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java similarity index 83% rename from engine/src/main/java/com/didiglobal/turbo/engine/util/StrongUuidGenerator.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java index 521c509b..bc5ca4aa 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/StrongUuidGenerator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java @@ -1,9 +1,12 @@ -package com.didiglobal.turbo.engine.util; +package com.didiglobal.turbo.engine.spi.generator; import com.fasterxml.uuid.EthernetAddress; import com.fasterxml.uuid.Generators; import com.fasterxml.uuid.impl.TimeBasedGenerator; +/** + * Implementation of UUID generator that uses time/location based generation method + */ public final class StrongUuidGenerator implements IdGenerator { private static volatile TimeBasedGenerator timeBasedGenerator; @@ -22,6 +25,7 @@ private void initGenerator() { } } + @Override public String getNextId() { return timeBasedGenerator.generate().toString(); } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/IdGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/util/IdGenerator.java deleted file mode 100644 index 00067001..00000000 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/IdGenerator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.turbo.engine.util; - -public interface IdGenerator { - - String getNextId(); - -} diff --git a/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator new file mode 100644 index 00000000..50bd6f00 --- /dev/null +++ b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator @@ -0,0 +1 @@ +com.didiglobal.turbo.engine.spi.calulator.GroovyExpressionCalculator \ No newline at end of file diff --git a/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator new file mode 100644 index 00000000..79bc031b --- /dev/null +++ b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator @@ -0,0 +1 @@ +com.didiglobal.turbo.engine.spi.generator.StrongUuidGenerator \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java index b1ebf1c5..d399a631 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java @@ -1,5 +1,7 @@ package com.didiglobal.turbo.engine.util; +import com.didiglobal.turbo.engine.spi.generator.IdGenerator; +import com.didiglobal.turbo.engine.spi.generator.StrongUuidGenerator; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From 6dc89beeeef17603f4cc8d36a91135a69670ae03 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 4 Apr 2023 16:17:13 +0800 Subject: [PATCH 03/24] add SPI test --- .../didiglobal/turbo/demo/spi/TestIdGenerator.java | 13 +++++++++++++ ...idiglobal.turbo.engine.spi.generator.IdGenerator | 1 + ...idiglobal.turbo.engine.spi.generator.IdGenerator | 0 3 files changed, 14 insertions(+) create mode 100644 demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java create mode 100644 demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator create mode 100644 demo/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java new file mode 100644 index 00000000..ebfcf098 --- /dev/null +++ b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java @@ -0,0 +1,13 @@ +package com.didiglobal.turbo.demo.spi; + +import com.didiglobal.turbo.engine.spi.generator.IdGenerator; +import org.apache.commons.lang3.RandomStringUtils; + +public class TestIdGenerator implements IdGenerator { + + @Override + public String getNextId() { + // 通过这种方式扩展自己的ID生成器 + return RandomStringUtils.randomAlphabetic(20); + } +} diff --git a/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator new file mode 100644 index 00000000..2f64f25c --- /dev/null +++ b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator @@ -0,0 +1 @@ +com.didiglobal.turbo.demo.spi.TestIdGenerator \ No newline at end of file diff --git a/demo/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator b/demo/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator new file mode 100644 index 00000000..e69de29b From a6508c43bf9fc13d0a59e43816230f4b6a97e2d5 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 4 Apr 2023 16:35:35 +0800 Subject: [PATCH 04/24] add labels --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 77f6a55a..d28b6894 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Turbo 简介 +[![License](https://img.shields.io/github/license/didi/turbo.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![Maven](https://img.shields.io/maven-central/v/com.didiglobal.turbo/turbo.svg)](https://github.com/didi/turbo/releases) + + Turbo是一款Java实现的轻量级流程引擎,是公司内多个低代码平台的核心后端服务。 # 特性 From 1fd35eceb1865928abbac5f650a2d352993f0781 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Wed, 24 May 2023 20:56:02 +0800 Subject: [PATCH 05/24] update some code --- .../turbo/demo/service/HookServiceImpl.java | 2 +- .../engine/executor/ElementExecutor.java | 7 ++-- .../executor/ExclusiveGatewayExecutor.java | 2 +- .../engine/executor/RuntimeExecutor.java | 7 ++-- .../engine/{spi => hook}/HookService.java | 4 +-- .../engine/processor/DefinitionProcessor.java | 16 +++++---- .../turbo/engine/spi/TurboServiceLoader.java | 3 +- .../ExpressionCalculatorFactory.java | 33 +++++++++++++++++ .../ExpressionCalculatorManager.java | 36 ------------------- .../spi/generator/IdGenerateFactory.java | 32 +++++++++++++++++ .../spi/generator/IdGenerateManager.java | 33 ----------------- 11 files changed, 84 insertions(+), 91 deletions(-) rename engine/src/main/java/com/didiglobal/turbo/engine/{spi => hook}/HookService.java (91%) create mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java delete mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorManager.java create mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java delete mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateManager.java diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/service/HookServiceImpl.java b/demo/src/main/java/com/didiglobal/turbo/demo/service/HookServiceImpl.java index 06988eef..3f43ba69 100644 --- a/demo/src/main/java/com/didiglobal/turbo/demo/service/HookServiceImpl.java +++ b/demo/src/main/java/com/didiglobal/turbo/demo/service/HookServiceImpl.java @@ -1,7 +1,7 @@ package com.didiglobal.turbo.demo.service; import com.didiglobal.turbo.engine.model.InstanceData; -import com.didiglobal.turbo.engine.spi.HookService; +import com.didiglobal.turbo.engine.hook.HookService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java index 72f96b74..67522d9b 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java @@ -12,7 +12,7 @@ import com.didiglobal.turbo.engine.exception.SuspendException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.model.InstanceData; -import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculatorManager; +import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculatorFactory; import com.didiglobal.turbo.engine.util.FlowModelUtil; import com.didiglobal.turbo.engine.util.InstanceDataUtil; import org.apache.commons.lang3.StringUtils; @@ -28,9 +28,6 @@ public abstract class ElementExecutor extends RuntimeExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(ElementExecutor.class); - @Resource - protected ExpressionCalculatorManager expressionCalculatorManager; - @Override public void execute(RuntimeContext runtimeContext) throws ProcessException { try { @@ -320,6 +317,6 @@ private FlowElement calculateOutgoing(FlowElement flowElement, Map instanceDataMap) throws ProcessException { Map dataMap = InstanceDataUtil.parseInstanceDataMap(instanceDataMap); - return expressionCalculatorManager.getExpressionCalculator().calculate(expression, dataMap); + return ExpressionCalculatorFactory.getExpressionCalculator().calculate(expression, dataMap); } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ExclusiveGatewayExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ExclusiveGatewayExecutor.java index 10134b59..674d898d 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ExclusiveGatewayExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ExclusiveGatewayExecutor.java @@ -8,7 +8,7 @@ import com.didiglobal.turbo.engine.exception.ProcessException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.model.InstanceData; -import com.didiglobal.turbo.engine.spi.HookService; +import com.didiglobal.turbo.engine.hook.HookService; import com.didiglobal.turbo.engine.util.FlowModelUtil; import com.didiglobal.turbo.engine.util.InstanceDataUtil; import com.google.common.collect.Lists; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java index 38bad5a3..d174c20a 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java @@ -6,7 +6,7 @@ import com.didiglobal.turbo.engine.dao.NodeInstanceDAO; import com.didiglobal.turbo.engine.dao.NodeInstanceLogDAO; import com.didiglobal.turbo.engine.exception.ProcessException; -import com.didiglobal.turbo.engine.spi.generator.IdGenerateManager; +import com.didiglobal.turbo.engine.spi.generator.IdGenerateFactory; import javax.annotation.Resource; @@ -27,11 +27,8 @@ public abstract class RuntimeExecutor { @Resource protected NodeInstanceLogDAO nodeInstanceLogDAO; - @Resource - private IdGenerateManager idGenerateManager; - protected String genId() { - return idGenerateManager.getIdGenerator().getNextId(); + return IdGenerateFactory.getIdGenerator().getNextId(); } /** diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/HookService.java b/engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java similarity index 91% rename from engine/src/main/java/com/didiglobal/turbo/engine/spi/HookService.java rename to engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java index 83c5eb4e..2cc7df6d 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/HookService.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java @@ -1,11 +1,11 @@ -package com.didiglobal.turbo.engine.spi; +package com.didiglobal.turbo.engine.hook; import com.didiglobal.turbo.engine.model.InstanceData; import java.util.List; /** - *

HookService

+ * HookService * * @author lijinghao * @version v1.0 diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java b/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java index d9f81b9e..771260ce 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java @@ -16,8 +16,12 @@ import com.didiglobal.turbo.engine.param.DeployFlowParam; import com.didiglobal.turbo.engine.param.GetFlowModuleParam; import com.didiglobal.turbo.engine.param.UpdateFlowParam; -import com.didiglobal.turbo.engine.result.*; -import com.didiglobal.turbo.engine.spi.generator.IdGenerateManager; +import com.didiglobal.turbo.engine.result.CommonResult; +import com.didiglobal.turbo.engine.result.CreateFlowResult; +import com.didiglobal.turbo.engine.result.DeployFlowResult; +import com.didiglobal.turbo.engine.result.FlowModuleResult; +import com.didiglobal.turbo.engine.result.UpdateFlowResult; +import com.didiglobal.turbo.engine.spi.generator.IdGenerateFactory; import com.didiglobal.turbo.engine.validator.ModelValidator; import com.didiglobal.turbo.engine.validator.ParamValidator; import org.apache.commons.lang3.StringUtils; @@ -27,6 +31,7 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; + import java.util.Date; @Component @@ -34,9 +39,6 @@ public class DefinitionProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(DefinitionProcessor.class); - @Resource - private IdGenerateManager idGenerateManager; - @Resource private ModelValidator modelValidator; @@ -53,7 +55,7 @@ public CreateFlowResult create(CreateFlowParam createFlowParam) { FlowDefinitionPO flowDefinitionPO = new FlowDefinitionPO(); BeanUtils.copyProperties(createFlowParam, flowDefinitionPO); - String flowModuleId = idGenerateManager.getIdGenerator().getNextId(); + String flowModuleId = IdGenerateFactory.getIdGenerator().getNextId(); flowDefinitionPO.setFlowModuleId(flowModuleId); flowDefinitionPO.setStatus(FlowDefinitionStatus.INIT); Date date = new Date(); @@ -118,7 +120,7 @@ public DeployFlowResult deploy(DeployFlowParam deployFlowParam) { FlowDeploymentPO flowDeploymentPO = new FlowDeploymentPO(); BeanUtils.copyProperties(flowDefinitionPO, flowDeploymentPO); - String flowDeployId = idGenerateManager.getIdGenerator().getNextId(); + String flowDeployId = IdGenerateFactory.getIdGenerator().getNextId(); flowDeploymentPO.setFlowDeployId(flowDeployId); flowDeploymentPO.setStatus(FlowDeploymentStatus.DEPLOYED); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java index f31fac02..d59a7013 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java @@ -11,8 +11,9 @@ import java.util.concurrent.ConcurrentHashMap; /** - *

turbo service loader

+ * turbo service loader * + * @author lijinghao * @param the type of service */ public class TurboServiceLoader { diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java new file mode 100644 index 00000000..7a0574de --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java @@ -0,0 +1,33 @@ +package com.didiglobal.turbo.engine.spi.calulator; + +import com.didiglobal.turbo.engine.spi.TurboServiceLoader; + +import java.util.Collection; +import java.util.Optional; + +/** + * expression calculator manager + * @author lijinghao + */ +public class ExpressionCalculatorFactory { + + /** + * expression calculator + */ + private static final ExpressionCalculator EXPRESSION_CALCULATOR; + + static { + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); + // In the order in which the services are loaded, take the first implementation + Optional optional = serviceInterfaces.stream().findFirst(); + if(optional.isPresent()){ + EXPRESSION_CALCULATOR = optional.get(); + } else { + throw new RuntimeException("spi load exception: not found Implementation class of interface ExpressionCalculator"); + } + } + + public static ExpressionCalculator getExpressionCalculator(){ + return EXPRESSION_CALCULATOR; + } +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorManager.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorManager.java deleted file mode 100644 index a6963424..00000000 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorManager.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.didiglobal.turbo.engine.spi.calulator; - -import com.didiglobal.turbo.engine.spi.TurboServiceLoader; -import org.springframework.stereotype.Service; - -import java.util.Collection; -import java.util.Optional; - -/** - * expression calculator manager - */ -@Service -public class ExpressionCalculatorManager { - - /** - * expression calculator - */ - private ExpressionCalculator expressionCalculator; - - public ExpressionCalculator getExpressionCalculator(){ - if(expressionCalculator != null){ - return expressionCalculator; - } - - synchronized (ExpressionCalculatorManager.class){ - Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); - // In the order in which the services are loaded, take the first implementation - Optional optional = serviceInterfaces.stream().findFirst(); - if(optional.isPresent()){ - expressionCalculator = optional.get(); - return expressionCalculator; - } - return null; - } - } -} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java new file mode 100644 index 00000000..abf498ca --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java @@ -0,0 +1,32 @@ +package com.didiglobal.turbo.engine.spi.generator; + +import com.didiglobal.turbo.engine.spi.TurboServiceLoader; + +import java.util.Collection; +import java.util.Optional; + +/** + * @author lijinghao + */ +public class IdGenerateFactory { + + /** + * id generator + */ + private static final IdGenerator ID_GENERATOR; + + static { + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(IdGenerator.class); + // In the order in which the services are loaded, take the first implementation + Optional optional = serviceInterfaces.stream().findFirst(); + if (optional.isPresent()) { + ID_GENERATOR = optional.get(); + } else { + throw new RuntimeException("spi load exception: not found Implementation class of interface IdGenerator"); + } + } + + public static IdGenerator getIdGenerator() { + return ID_GENERATOR; + } +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateManager.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateManager.java deleted file mode 100644 index f23c6225..00000000 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateManager.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.didiglobal.turbo.engine.spi.generator; - -import com.didiglobal.turbo.engine.spi.TurboServiceLoader; -import org.springframework.stereotype.Service; - -import java.util.Collection; -import java.util.Optional; - -@Service -public class IdGenerateManager { - - /** - * id generator - */ - private IdGenerator idGenerator; - - public IdGenerator getIdGenerator(){ - if(idGenerator != null){ - return idGenerator; - } - - synchronized (IdGenerateManager.class){ - Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(IdGenerator.class); - // In the order in which the services are loaded, take the first implementation - Optional optional = serviceInterfaces.stream().findFirst(); - if(optional.isPresent()){ - idGenerator = optional.get(); - return idGenerator; - } - return null; - } - } -} From 9a37d2a63c7507e34d465839cc7adcb0f244cd59 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Wed, 24 May 2023 21:00:50 +0800 Subject: [PATCH 06/24] update some code --- .../didiglobal/turbo/engine/executor/ElementExecutor.java | 1 - .../java/com/didiglobal/turbo/engine/spi/SingletonSPI.java | 3 +++ .../engine/spi/calulator/ExpressionCalculatorFactory.java | 7 ++++--- .../turbo/engine/spi/generator/IdGenerateFactory.java | 2 ++ .../didiglobal/turbo/engine/spi/generator/IdGenerator.java | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java index 67522d9b..9da7dc33 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java @@ -20,7 +20,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; -import javax.annotation.Resource; import java.util.List; import java.util.Map; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java index beb35437..bc7697f0 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java @@ -6,6 +6,9 @@ import java.lang.annotation.Target; +/** + * @author lijinghao + */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SingletonSPI { diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java index 7a0574de..d1f40d75 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java @@ -6,7 +6,8 @@ import java.util.Optional; /** - * expression calculator manager + * expression calculator factory + * * @author lijinghao */ public class ExpressionCalculatorFactory { @@ -20,14 +21,14 @@ public class ExpressionCalculatorFactory { Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); // In the order in which the services are loaded, take the first implementation Optional optional = serviceInterfaces.stream().findFirst(); - if(optional.isPresent()){ + if (optional.isPresent()) { EXPRESSION_CALCULATOR = optional.get(); } else { throw new RuntimeException("spi load exception: not found Implementation class of interface ExpressionCalculator"); } } - public static ExpressionCalculator getExpressionCalculator(){ + public static ExpressionCalculator getExpressionCalculator() { return EXPRESSION_CALCULATOR; } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java index abf498ca..d4507736 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java @@ -6,6 +6,8 @@ import java.util.Optional; /** + * id generate factory + * * @author lijinghao */ public class IdGenerateFactory { diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java index c76ca24d..ce172acd 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java @@ -9,7 +9,7 @@ public interface IdGenerator { /** - * Get the next ID + * get the next ID * * @return ID */ From 31c9ebcc8a4d59b542b38a08e87c214cd1922587 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 30 May 2023 17:05:10 +0800 Subject: [PATCH 07/24] Improve testing code --- .../engine/dao/FlowDefinitionDAOTest.java | 14 ++- .../turbo/engine/dao/NodeInstanceDAOTest.java | 4 +- .../dao/mapper/FlowDefinitionMapperTest.java | 15 +-- .../dao/mapper/FlowDeploymentMapperTest.java | 10 +- .../dao/mapper/InstanceDataMapperTest.java | 10 +- .../engine/engine/ProcessEngineTest.java | 5 +- .../processor/RuntimeProcessorTest.java | 100 +++++++-------- .../turbo/engine/runner/BaseTest.java | 4 + .../engine/runner/TestEngineApplication.java | 7 +- .../engine/util/ExpressionCalculatorTest.java | 29 +++++ .../turbo/engine/util/GroovyUtilTest.java | 6 +- .../turbo/engine/util/IdGeneratorTest.java | 13 +- .../validator/EndEventValidatorTest.java | 20 ++- .../ExclusiveGatewayValidatorTest.java | 90 +++++++------- .../validator/FlowModelValidatorTest.java | 52 +++----- .../engine/validator/ModelValidatorTest.java | 27 ++-- .../validator/SequenceFlowValidatorTest.java | 21 ++-- .../validator/StartEventValidatorTest.java | 46 ++++--- .../validator/UserTaskValidatorTest.java | 28 ++--- .../src/test/resources/application.properties | 17 ++- .../resources/script/turbo-mysql-h2-ddl.sql | 116 ++++++++++++++++++ 21 files changed, 375 insertions(+), 259 deletions(-) create mode 100644 engine/src/test/java/com/didiglobal/turbo/engine/util/ExpressionCalculatorTest.java create mode 100644 engine/src/test/resources/script/turbo-mysql-h2-ddl.sql diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/FlowDefinitionDAOTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/FlowDefinitionDAOTest.java index d6291622..3f766a97 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/FlowDefinitionDAOTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/FlowDefinitionDAOTest.java @@ -7,9 +7,11 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.Resource; + public class FlowDefinitionDAOTest extends BaseTest { - @Autowired + @Resource private FlowDefinitionDAO flowDefinitionDAO; @Test @@ -18,7 +20,7 @@ public void insertTest() { flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int result = flowDefinitionDAO.insert(flowDefinitionPO); LOGGER.info("insertTest.result={}", result); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -26,10 +28,10 @@ public void updateByModuleIdTest() { FlowDefinitionPO flowDefinitionPO = EntityBuilder.buildFlowDefinitionPO(); flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int insertResult = flowDefinitionDAO.insert(flowDefinitionPO); - Assert.assertTrue(insertResult == 1); + Assert.assertEquals(1, insertResult); int updateResult = flowDefinitionDAO.updateByModuleId(flowDefinitionPO); LOGGER.info("updateByModuleIdTest.||result={}", updateResult); - Assert.assertTrue(updateResult == 1); + Assert.assertEquals(1, updateResult); } @Test @@ -37,10 +39,10 @@ public void selectByModuleIdTest() { FlowDefinitionPO flowDefinitionPO = EntityBuilder.buildFlowDefinitionPO(); flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int result = flowDefinitionDAO.insert(flowDefinitionPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); String flowModuleId = flowDefinitionPO.getFlowModuleId(); FlowDefinitionPO queryFlowDefinitionPO = flowDefinitionDAO.selectByModuleId(flowDefinitionPO.getFlowModuleId()); LOGGER.info("selectByModuleIdTest.||flowDefinitionPO={}", flowDefinitionPO); - Assert.assertTrue(flowModuleId.equals(queryFlowDefinitionPO.getFlowModuleId())); + Assert.assertEquals(flowModuleId, queryFlowDefinitionPO.getFlowModuleId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java index 10b19f4f..62c904a8 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java @@ -20,7 +20,7 @@ public class NodeInstanceDAOTest extends BaseTest { public void insert(){ NodeInstancePO nodeInstancePO = EntityBuilder.buildNodeInstancePO(); int result = nodeInstanceDAO.insert(nodeInstancePO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -43,6 +43,6 @@ public void updateStatus() { nodeInstanceDAO.updateStatus(nodeInstancePO, NodeInstanceStatus.COMPLETED); NodeInstancePO result = nodeInstanceDAO.selectByNodeInstanceId(nodeInstancePO.getFlowInstanceId(), nodeInstancePO.getNodeInstanceId()); - Assert.assertTrue(result.getStatus() == NodeInstanceStatus.COMPLETED); + Assert.assertEquals(NodeInstanceStatus.COMPLETED, (int) result.getStatus()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDefinitionMapperTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDefinitionMapperTest.java index 2c91fc98..d8624858 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDefinitionMapperTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDefinitionMapperTest.java @@ -5,11 +5,12 @@ import com.didiglobal.turbo.engine.util.EntityBuilder; import org.junit.Assert; import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.Resource; public class FlowDefinitionMapperTest extends BaseTest { - @Autowired + @Resource private FlowDefinitionMapper flowDefinitionMapper; @Test @@ -17,7 +18,7 @@ public void insert() { FlowDefinitionPO flowDefinitionPO = EntityBuilder.buildFlowDefinitionPO(); flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int result = flowDefinitionMapper.insert(flowDefinitionPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -28,9 +29,9 @@ public void update() { flowDefinitionPO = flowDefinitionMapper.selectByFlowModuleId(flowDefinitionPO.getFlowModuleId()); flowDefinitionPO.setStatus(3); int result = flowDefinitionMapper.updateById(flowDefinitionPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); flowDefinitionPO = flowDefinitionMapper.selectByFlowModuleId(flowDefinitionPO.getFlowModuleId()); - Assert.assertTrue(flowDefinitionPO.getStatus().equals(3)); + Assert.assertEquals(3, (int) flowDefinitionPO.getStatus()); } @Test @@ -38,11 +39,11 @@ public void selectByFlowModuleId() { FlowDefinitionPO flowDefinitionPO = EntityBuilder.buildFlowDefinitionPO(); flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int result = flowDefinitionMapper.insert(flowDefinitionPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); String flowModuleId = flowDefinitionPO.getFlowModuleId(); FlowDefinitionPO queryFlowDefinitionPO = flowDefinitionMapper.selectByFlowModuleId(flowModuleId); LOGGER.info("selectByModuleIdTest.||flowDefinitionPO={}", flowDefinitionPO); - Assert.assertTrue(flowModuleId.equals(queryFlowDefinitionPO.getFlowModuleId())); + Assert.assertEquals(flowModuleId, queryFlowDefinitionPO.getFlowModuleId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDeploymentMapperTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDeploymentMapperTest.java index 9c43f7da..6d244ef2 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDeploymentMapperTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDeploymentMapperTest.java @@ -8,9 +8,11 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.Resource; + public class FlowDeploymentMapperTest extends BaseTest { - @Autowired + @Resource private FlowDeploymentMapper flowDeploymentMapper; @Test @@ -18,7 +20,7 @@ public void insert() { FlowDeploymentPO flowDeploymentPO = EntityBuilder.buildFlowDeploymentPO(); flowDeploymentPO.setFlowDeployId("testFlowDeployId_" + System.currentTimeMillis()); int result = flowDeploymentMapper.insert(flowDeploymentPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -29,7 +31,7 @@ public void selectByDeployId() { flowDeploymentMapper.insert(flowDeploymentPO); String flowDeployId = flowDeploymentPO.getFlowDeployId(); flowDeploymentPO = flowDeploymentMapper.selectByDeployId(flowDeployId); - Assert.assertTrue(flowDeployId.equals(flowDeploymentPO.getFlowDeployId())); + Assert.assertEquals(flowDeployId, flowDeploymentPO.getFlowDeployId()); } @Test @@ -45,6 +47,6 @@ public void selectByModuleId() { flowDeploymentPO.setFlowDeployId("testFlowDeployId_" + System.currentTimeMillis()); flowDeploymentMapper.insert(flowDeploymentPONew); FlowDeploymentPO flowDeploymentPORes = flowDeploymentMapper.selectByModuleId(flowModuleId1); - Assert.assertTrue(flowDeploymentPONew.getFlowDeployId().equals(flowDeploymentPORes.getFlowDeployId())); + Assert.assertEquals(flowDeploymentPONew.getFlowDeployId(), flowDeploymentPORes.getFlowDeployId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/InstanceDataMapperTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/InstanceDataMapperTest.java index 7071d2b0..e78329c1 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/InstanceDataMapperTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/InstanceDataMapperTest.java @@ -7,9 +7,11 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.Resource; + public class InstanceDataMapperTest extends BaseTest { - @Autowired + @Resource private InstanceDataMapper instanceDataMapper; @Test @@ -17,7 +19,7 @@ public void insert() { InstanceDataPO instanceDataPO = EntityBuilder.buildDynamicInstanceDataPO(); int result = instanceDataMapper.insert(instanceDataPO); LOGGER.info("insert.result={}", result); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -25,7 +27,7 @@ public void select() { InstanceDataPO instanceDataPO = EntityBuilder.buildDynamicInstanceDataPO(); instanceDataMapper.insert(instanceDataPO); InstanceDataPO result = instanceDataMapper.select(instanceDataPO.getFlowInstanceId(), instanceDataPO.getInstanceDataId()); - Assert.assertTrue(result.getInstanceDataId().equals(instanceDataPO.getInstanceDataId())); + Assert.assertEquals(result.getInstanceDataId(), instanceDataPO.getInstanceDataId()); } @Test @@ -35,6 +37,6 @@ public void selectRecentOne() { InstanceDataPO newInstanceDataPO = EntityBuilder.buildDynamicInstanceDataPO(); instanceDataMapper.insert(newInstanceDataPO); InstanceDataPO result = instanceDataMapper.selectRecentOne(oldInstanceDataPO.getFlowInstanceId()); - Assert.assertTrue(result.getInstanceDataId().equals(newInstanceDataPO.getInstanceDataId())); + Assert.assertEquals(result.getInstanceDataId(), newInstanceDataPO.getInstanceDataId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/engine/ProcessEngineTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/engine/ProcessEngineTest.java index ad6e9484..60e8027a 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/engine/ProcessEngineTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/engine/ProcessEngineTest.java @@ -16,11 +16,8 @@ public class ProcessEngineTest extends BaseTest { - @Autowired - ProcessEngine processEngine; - @Resource - ProcessEngineImpl processEngineImpl; + private ProcessEngineImpl processEngineImpl; @Test public void createFlowTest() { diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java index e200e07e..63fe412f 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java @@ -29,7 +29,7 @@ public class RuntimeProcessorTest extends BaseTest { @Resource private FlowDeploymentMapper flowDeploymentMapper; - private StartProcessResult startProcess() throws Exception { + private StartProcessResult startProcess() { // prepare FlowDeploymentPO flowDeploymentPO = EntityBuilder.buildSpecialFlowDeploymentPO(); FlowDeploymentPO _flowDeploymentPO = flowDeploymentMapper.selectByDeployId(flowDeploymentPO.getFlowDeployId()); @@ -54,15 +54,15 @@ private StartProcessResult startProcess() throws Exception { } @Test - public void testStartProcess() throws Exception { + public void testStartProcess() { StartProcessResult startProcessResult = startProcess(); - Assert.assertTrue(startProcessResult.getErrCode() == ErrorEnum.COMMIT_SUSPEND.getErrNo()); + Assert.assertEquals(startProcessResult.getErrCode(), ErrorEnum.COMMIT_SUSPEND.getErrNo()); Assert.assertTrue(StringUtils.equals(startProcessResult.getActiveTaskInstance().getModelKey(), "BranchUserTask_0scrl8d")); } // UserTask -> EndEvent @Test - public void testNormalCommitToEnd() throws Exception { + public void testNormalCommitToEnd() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -74,13 +74,13 @@ public void testNormalCommitToEnd() throws Exception { CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testCommit.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.SUCCESS.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.SUCCESS.getErrNo()); Assert.assertTrue(StringUtils.equals(commitTaskResult.getActiveTaskInstance().getModelKey(), "EndEvent_0s4vsxw")); } // UserTask -> ExclusiveGateway -> UserTask @Test - public void testNormalCommitToUserTask() throws Exception { + public void testNormalCommitToUserTask() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -92,14 +92,14 @@ public void testNormalCommitToUserTask() throws Exception { CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testCommit.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.COMMIT_SUSPEND.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_SUSPEND.getErrNo()); Assert.assertTrue(StringUtils.equals(commitTaskResult.getActiveTaskInstance().getModelKey(), "UserTask_0uld0u9")); } // UserTask -> ExclusiveGateway -> UserTask // UserTask -> @Test - public void testRepeatedCommitToUserTask() throws Exception { + public void testRepeatedCommitToUserTask() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -108,18 +108,19 @@ public void testRepeatedCommitToUserTask() throws Exception { List variables = new ArrayList<>(); variables.add(new InstanceData("danxuankuang_ytgyk", 0)); commitTaskParam.setVariables(variables); + // first commit + runtimeProcessor.commit(commitTaskParam); + // commit again CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); - - commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testCommit.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.COMMIT_SUSPEND.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_SUSPEND.getErrNo()); Assert.assertTrue(StringUtils.equals(commitTaskResult.getActiveTaskInstance().getModelKey(), "UserTask_0uld0u9")); } // UserTask -> EndEvent -> Commit again @Test - public void testCommitCompletedFlowInstance() throws Exception { + public void testCommitCompletedFlowInstance() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -128,16 +129,17 @@ public void testCommitCompletedFlowInstance() throws Exception { List variables = new ArrayList<>(); variables.add(new InstanceData("danxuankuang_ytgyk", 1)); commitTaskParam.setVariables(variables); + // first commit + runtimeProcessor.commit(commitTaskParam); + // commit again CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); - - commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testCommit.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.REENTRANT_WARNING.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.REENTRANT_WARNING.getErrNo()); } @Test - public void testCommitTerminatedFlowInstance() throws Exception { + public void testCommitTerminatedFlowInstance() { StartProcessResult startProcessResult = startProcess(); runtimeProcessor.terminateProcess(startProcessResult.getFlowInstanceId()); @@ -150,12 +152,12 @@ public void testCommitTerminatedFlowInstance() throws Exception { commitTaskParam.setVariables(variables); CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.COMMIT_REJECTRD.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_REJECTRD.getErrNo()); } // UserTask <- ExclusiveGateway <- UserTask : Commit old UserTask @Test - public void testRollbackToUserTaskAndCommitOldUserTask() throws Exception { + public void testRollbackToUserTaskAndCommitOldUserTask() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -178,12 +180,12 @@ public void testRollbackToUserTaskAndCommitOldUserTask() throws Exception { commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testRollbackToUserTaskAndCommitOldUserTask.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.COMMIT_FAILED.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_FAILED.getErrNo()); Assert.assertTrue(StringUtils.equals(commitTaskResult.getActiveTaskInstance().getModelKey(), "BranchUserTask_0scrl8d")); } @Test - public void testRollbackFromMiddleUserTask() throws Exception { + public void testRollbackFromMiddleUserTask() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -206,15 +208,14 @@ public void testRollbackFromMiddleUserTask() throws Exception { // Ignore current userTask LOGGER.info("testRollbackFromMiddleUserTask.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertTrue(rollbackTaskResult.getErrCode() == ErrorEnum.ROLLBACK_SUSPEND.getErrNo()); - Assert.assertTrue(StringUtils.equals(rollbackTaskResult.getActiveTaskInstance().getModelKey(), "BranchUserTask_0scrl8d")); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.ROLLBACK_SUSPEND.getErrNo()); + Assert.assertEquals("BranchUserTask_0scrl8d", rollbackTaskResult.getActiveTaskInstance().getModelKey()); } - // UserTask <- ExclusiveGateway <- UserTask @Test - public void testRollbackToUserTask() throws Exception { + public void testRollbackToUserTask() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -234,13 +235,13 @@ public void testRollbackToUserTask() throws Exception { RollbackTaskResult rollbackTaskResult = runtimeProcessor.rollback(rollbackTaskParam); LOGGER.info("testRollback.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertTrue(rollbackTaskResult.getErrCode() == ErrorEnum.ROLLBACK_SUSPEND.getErrNo()); - Assert.assertTrue(StringUtils.equals(rollbackTaskResult.getActiveTaskInstance().getModelKey(), "BranchUserTask_0scrl8d")); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.ROLLBACK_SUSPEND.getErrNo()); + Assert.assertEquals("BranchUserTask_0scrl8d", rollbackTaskResult.getActiveTaskInstance().getModelKey()); } // StartEvent <- UserTask @Test - public void testRollbackToStartEvent() throws Exception { + public void testRollbackToStartEvent() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -265,12 +266,12 @@ public void testRollbackToStartEvent() throws Exception { rollbackTaskParam.setTaskInstanceId(rollbackTaskResult.getActiveTaskInstance().getNodeInstanceId()); rollbackTaskResult = runtimeProcessor.rollback(rollbackTaskParam); LOGGER.info("testRollback.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertTrue(rollbackTaskResult.getErrCode() == ErrorEnum.NO_USER_TASK_TO_ROLLBACK.getErrNo()); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.NO_USER_TASK_TO_ROLLBACK.getErrNo()); } // rollback completed process @Test - public void testRollbackFromEndEvent() throws Exception { + public void testRollbackFromEndEvent() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -290,19 +291,19 @@ public void testRollbackFromEndEvent() throws Exception { RollbackTaskResult rollbackTaskResult = runtimeProcessor.rollback(rollbackTaskParam); LOGGER.info("testRollback.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertTrue(rollbackTaskResult.getErrCode() == ErrorEnum.ROLLBACK_REJECTRD.getErrNo()); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.ROLLBACK_REJECTRD.getErrNo()); } @Test - public void testTerminateProcess() throws Exception { + public void testTerminateProcess() { StartProcessResult startProcessResult = startProcess(); TerminateResult terminateResult = runtimeProcessor.terminateProcess(startProcessResult.getFlowInstanceId()); LOGGER.info("testTerminateProcess.||terminateResult={}", terminateResult); - Assert.assertTrue(terminateResult.getErrCode() == ErrorEnum.SUCCESS.getErrNo()); + Assert.assertEquals(terminateResult.getErrCode(), ErrorEnum.SUCCESS.getErrNo()); } @Test - public void testGetHistoryUserTaskList() throws Exception { + public void testGetHistoryUserTaskList() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); commitTaskParam.setFlowInstanceId(startProcessResult.getFlowInstanceId()); @@ -324,15 +325,14 @@ public void testGetHistoryUserTaskList() throws Exception { sb.append(elementInstanceResult.getStatus()); sb.append("]->"); } - LOGGER.info("testGetHistoryUserTaskList.||snapshot={}", sb.toString()); + LOGGER.info("testGetHistoryUserTaskList.||snapshot={}", sb); - Assert.assertTrue(nodeInstanceListResult.getNodeInstanceList().size() == 2); - Assert.assertTrue(StringUtils.equals(nodeInstanceListResult.getNodeInstanceList().get(0).getModelKey(), "UserTask_0uld0u9")); + Assert.assertEquals(2, nodeInstanceListResult.getNodeInstanceList().size()); + Assert.assertEquals("UserTask_0uld0u9", nodeInstanceListResult.getNodeInstanceList().get(0).getModelKey()); } - @Test - public void testGetFailedHistoryElementList() throws Exception { + public void testGetFailedHistoryElementList() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); commitTaskParam.setFlowInstanceId(startProcessResult.getFlowInstanceId()); @@ -345,7 +345,7 @@ public void testGetFailedHistoryElementList() throws Exception { // UserTask -> ExclusiveGateway : Failed CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testGetFailedHistoryElementList.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.GET_OUTGOING_FAILED.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.GET_OUTGOING_FAILED.getErrNo()); ElementInstanceListResult elementInstanceListResult = runtimeProcessor.getHistoryElementList(commitTaskResult.getFlowInstanceId()); LOGGER.info("testGetHistoryElementList.||elementInstanceListResult={}", elementInstanceListResult); @@ -357,14 +357,14 @@ public void testGetFailedHistoryElementList() throws Exception { sb.append(elementInstanceResult.getStatus()); sb.append("]->"); } - LOGGER.info("testGetHistoryElementList.||snapshot={}", sb.toString()); + LOGGER.info("testGetHistoryElementList.||snapshot={}", sb); - Assert.assertTrue(elementInstanceListResult.getElementInstanceList().size() == 5); - Assert.assertTrue(StringUtils.equals(elementInstanceListResult.getElementInstanceList().get(4).getModelKey(), "ExclusiveGateway_0yq2l0s")); + Assert.assertEquals(5, elementInstanceListResult.getElementInstanceList().size()); + Assert.assertEquals("ExclusiveGateway_0yq2l0s", elementInstanceListResult.getElementInstanceList().get(4).getModelKey()); } @Test - public void testGetCompletedHistoryElementList() throws Exception { + public void testGetCompletedHistoryElementList() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); commitTaskParam.setFlowInstanceId(startProcessResult.getFlowInstanceId()); @@ -386,15 +386,15 @@ public void testGetCompletedHistoryElementList() throws Exception { sb.append(elementInstanceResult.getStatus()); sb.append("]->"); } - LOGGER.info("testGetHistoryElementList.||snapshot={}", sb.toString()); + LOGGER.info("testGetHistoryElementList.||snapshot={}", sb); - Assert.assertTrue(elementInstanceListResult.getElementInstanceList().size() == 5); - Assert.assertTrue(StringUtils.equals(elementInstanceListResult.getElementInstanceList().get(4).getModelKey(), "EndEvent_0s4vsxw")); + Assert.assertEquals(5, elementInstanceListResult.getElementInstanceList().size()); + Assert.assertEquals("EndEvent_0s4vsxw", elementInstanceListResult.getElementInstanceList().get(4).getModelKey()); } @Test - public void testGetInstanceData() throws Exception { + public void testGetInstanceData() { StartProcessResult startProcessResult = startProcess(); String flowInstanceId = startProcessResult.getFlowInstanceId(); InstanceDataListResult instanceDataList = runtimeProcessor.getInstanceData(flowInstanceId); @@ -442,16 +442,16 @@ public void testGetInstanceData() throws Exception { LOGGER.info("testGetInstanceData 5.||instanceDataList={}", instanceDataList); String initData = JSON.toJSONString(startProcessResult.getVariables()); String rollbackData = JSON.toJSONString(rollbackTaskResult1.getVariables()); - Assert.assertTrue(StringUtils.equals(initData, rollbackData)); + Assert.assertEquals(initData, rollbackData); } @Test - public void testGetNodeInstance() throws Exception { + public void testGetNodeInstance() { StartProcessResult startProcessResult = startProcess(); String flowInstanceId = startProcessResult.getFlowInstanceId(); NodeInstanceResult nodeInstanceResult = runtimeProcessor.getNodeInstance(flowInstanceId, startProcessResult.getActiveTaskInstance().getNodeInstanceId()); LOGGER.info("testGetNodeInstance.||nodeInstanceResult={}", nodeInstanceResult); - Assert.assertTrue(StringUtils.equals(nodeInstanceResult.getNodeInstance().getNodeInstanceId(), startProcessResult.getActiveTaskInstance().getNodeInstanceId())); + Assert.assertEquals(startProcessResult.getActiveTaskInstance().getNodeInstanceId(), nodeInstanceResult.getNodeInstance().getNodeInstanceId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/runner/BaseTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/runner/BaseTest.java index 7697ef65..b1773e77 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/runner/BaseTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/runner/BaseTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.runner; +import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,4 +12,7 @@ public class BaseTest { protected static final Logger LOGGER = LoggerFactory.getLogger(BaseTest.class); + + @Test + public void test(){} } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/runner/TestEngineApplication.java b/engine/src/test/java/com/didiglobal/turbo/engine/runner/TestEngineApplication.java index 123add85..1f53ff1c 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/runner/TestEngineApplication.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/runner/TestEngineApplication.java @@ -1,16 +1,15 @@ package com.didiglobal.turbo.engine.runner; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.didiglobal.turbo.engine.annotation.EnableTurboEngine; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; -@SpringBootApplication -@EnableAutoConfiguration(exclude = {DruidDataSourceAutoConfigure.class}) -@ComponentScan("com.didiglobal.turbo.engine") -@MapperScan(basePackages = {"com.didiglobal.turbo.engine.dao"}) +@EnableTurboEngine +@SpringBootApplication(scanBasePackages = "com.didiglobal.turbo.engine", exclude = {DruidDataSourceAutoConfigure.class}) public class TestEngineApplication { public static void main(String[] args) { SpringApplication.run(TestEngineApplication.class, args); diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/ExpressionCalculatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/ExpressionCalculatorTest.java new file mode 100644 index 00000000..544d1216 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/util/ExpressionCalculatorTest.java @@ -0,0 +1,29 @@ +package com.didiglobal.turbo.engine.util; + +import com.didiglobal.turbo.engine.exception.ProcessException; +import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculatorFactory; +import com.google.common.collect.Maps; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Map; + +/** + * @author lijinghao + * @version v1.0 + * @date 2023/5/30 2:55 PM + */ +public class ExpressionCalculatorTest { + + private final ExpressionCalculator expressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(); + + @Test + public void testExpressionCalculator() throws ProcessException { + String expression = "str.length() > 2"; + Map data = Maps.newHashMap(); + data.put("str", "1234"); + Boolean result = expressionCalculator.calculate(expression, data); + Assert.assertTrue(result); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/GroovyUtilTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/GroovyUtilTest.java index 17dcfa64..06f7cd06 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/GroovyUtilTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/util/GroovyUtilTest.java @@ -2,6 +2,7 @@ import com.didiglobal.turbo.engine.runner.BaseTest; import com.google.common.collect.Maps; +import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,9 +28,12 @@ public class GroovyUtilTest { @Test public void fun1(){ try { - String expression = ""; + String expression = "str.length() > 2"; Map dataMap = Maps.newHashMap(); + dataMap.put("str","1234"); Object result = GroovyUtil.execute(expression, dataMap); + Assert.assertNotNull(result); + Assert.assertTrue((Boolean) result); LOGGER.warn("result:{}:{}", result.getClass().getSimpleName(), result); } catch (Exception e) { LOGGER.warn("catch exception", e); diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java index d399a631..dd555855 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.util; +import com.didiglobal.turbo.engine.spi.generator.IdGenerateFactory; import com.didiglobal.turbo.engine.spi.generator.IdGenerator; import com.didiglobal.turbo.engine.spi.generator.StrongUuidGenerator; import org.junit.Test; @@ -10,15 +11,19 @@ public class IdGeneratorTest { private static final Logger LOGGER = LoggerFactory.getLogger(IdGeneratorTest.class); - private IdGenerator idGenerator = new StrongUuidGenerator(); + private final IdGenerator idGenerator = IdGenerateFactory.getIdGenerator(); @Test public void testDoExecute() { + int count = 1000; long start = System.currentTimeMillis(); - for (int i = 0; i < 1000000; i++) { - LOGGER.info("{}", idGenerator.getNextId()); + for (int i = 0; i < count; i++) { + String nextId = idGenerator.getNextId(); + if (LOGGER.isDebugEnabled()) { + LOGGER.info(nextId); + } } - LOGGER.info("{}", System.currentTimeMillis() - start); + LOGGER.info("generate {} ids, cost {}ms", count, System.currentTimeMillis() - start); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/EndEventValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/EndEventValidatorTest.java index 8d31f73d..78bccf12 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/EndEventValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/EndEventValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -8,6 +9,7 @@ import org.junit.Test; import javax.annotation.Resource; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -16,14 +18,14 @@ public class EndEventValidatorTest extends BaseTest { - @Resource EndEventValidator endEventValidator; + @Resource + EndEventValidator endEventValidator; /** * Test endEvent's checkIncoming, while incoming is normal. - * */ @Test - public void checkIncomingAcess() { + public void checkIncomingAccess() { FlowElement endEvent = EntityBuilder.buildEndEvent(); Map map = new HashMap<>(); map.put(endEvent.getKey(), endEvent); @@ -31,17 +33,16 @@ public void checkIncomingAcess() { try { endEventValidator.checkIncoming(map, endEvent); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); + } /** * Test endEvent's checkIncoming, while incoming is null. - * */ @Test public void checkWithoutIncoming() { @@ -53,16 +54,14 @@ public void checkWithoutIncoming() { try { endEventValidator.checkIncoming(map, endEventInvalid); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_INCOMING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test endEvent's checkOutgoing, while outgoing is normal. - * */ @Test public void checkOutgoingAccess() { @@ -74,7 +73,6 @@ public void checkOutgoingAccess() { /** * Test endEvent's checkOutgoing, while outgoing is not null. - * */ @Test public void checkOutgoingIsNotNull() { diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/ExclusiveGatewayValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/ExclusiveGatewayValidatorTest.java index 6c2acd3a..9b370040 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/ExclusiveGatewayValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/ExclusiveGatewayValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -8,6 +9,7 @@ import org.junit.Test; import javax.annotation.Resource; + import java.util.HashMap; import java.util.Map; @@ -20,134 +22,128 @@ public class ExclusiveGatewayValidatorTest extends BaseTest { /** * Test exclusiveGateway's checkIncoming, while exclusiveGateway's incoming is normal. - * */ @Test public void checkIncomingAccess() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); - FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); + FlowElement outGoingSequence1 = EntityBuilder.buildSequenceFlow3(); Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); - map.put(outgoningSequence1.getKey(), outgoningSequence1); + map.put(outGoingSequence.getKey(), outGoingSequence); + map.put(outGoingSequence1.getKey(), outGoingSequence1); boolean access = false; try { exclusiveGatewayValidator.checkIncoming(map, exclusiveGateway); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test exclusiveGateway's checkIncoming, while incoming is null. - * */ @Test public void checkWithoutIncoming() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); - FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); + FlowElement outGoingSequence1 = EntityBuilder.buildSequenceFlow3(); exclusiveGateway.setIncoming(null); Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); - map.put(outgoningSequence1.getKey(), outgoningSequence1); + map.put(outGoingSequence.getKey(), outGoingSequence); + map.put(outGoingSequence1.getKey(), outGoingSequence1); boolean access = false; try { exclusiveGatewayValidator.checkIncoming(map, exclusiveGateway); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_INCOMING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test exclusiveGateway's checkOutgoing, while exclusiveGateway's outgoing is normal. - * */ @Test public void checkOutgoingAccess() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); - FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); + FlowElement outGoingSequence1 = EntityBuilder.buildSequenceFlow3(); Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); - map.put(outgoningSequence1.getKey(), outgoningSequence1); + map.put(outGoingSequence.getKey(), outGoingSequence); + map.put(outGoingSequence1.getKey(), outGoingSequence1); boolean access = false; try { exclusiveGatewayValidator.checkOutgoing(map, exclusiveGateway); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test exclusiveGateway's checkOutgoing, while exclusiveGateway's outgoing is empty. - * */ @Test public void checkEmptyOutgoing() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); Map properties = new HashMap<>(); properties.put("defaultConditions", "false"); properties.put("conditionsequenceflow", ""); - outgoningSequence.setProperties(properties); + outGoingSequence.setProperties(properties); FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); + map.put(outGoingSequence.getKey(), outGoingSequence); map.put(outgoningSequence1.getKey(), outgoningSequence1); boolean access = false; try { exclusiveGatewayValidator.checkOutgoing(map, exclusiveGateway); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.EMPTY_SEQUENCE_OUTGOING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test exclusiveGateway's checkOutgoing, while too many default sequence. - * */ @Test - public void checkTooManySequenceOutgoig() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); + public void checkTooManyDefaultSequenceOutgoing() { + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); Map properties = new HashMap<>(); properties.put("defaultConditions", "true"); properties.put("conditionsequenceflow", ""); - outgoningSequence.setProperties(properties); - FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); + outGoingSequence.setProperties(properties); + + FlowElement outGoingSequence1 = EntityBuilder.buildSequenceFlow3(); Map properties1 = new HashMap<>(); - properties.put("defaultConditions", "true"); - properties.put("conditionsequenceflow", ""); - outgoningSequence1.setProperties(properties); + properties1.put("defaultConditions", "true"); + properties1.put("conditionsequenceflow", ""); + outGoingSequence1.setProperties(properties1); + Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); - map.put(outgoningSequence1.getKey(), outgoningSequence1); + map.put(outGoingSequence.getKey(), outGoingSequence); + map.put(outGoingSequence1.getKey(), outGoingSequence1); + boolean access = false; try { exclusiveGatewayValidator.checkOutgoing(map, exclusiveGateway); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.TOO_MANY_DEFAULT_SEQUENCE.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/FlowModelValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/FlowModelValidatorTest.java index 867c439e..19bf11dc 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/FlowModelValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/FlowModelValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.common.FlowElementType; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.exception.ProcessException; @@ -13,17 +14,17 @@ import org.junit.Test; import javax.annotation.Resource; + import java.util.ArrayList; import java.util.List; public class FlowModelValidatorTest extends BaseTest { @Resource - FlowModelValidator flowModelValidator; + private FlowModelValidator flowModelValidator; /** * Test flowModel's validate, while normal. - * */ @Test public void validateAccess() { @@ -34,22 +35,15 @@ public void validateAccess() { try { flowModelValidator.validate(flowModel); access = true; - Assert.assertTrue(access); - } catch (ProcessException e) { - LOGGER.error("", e); - access = true; - Assert.assertTrue(access); - } catch (DefinitionException e) { + } catch (ProcessException | DefinitionException e) { LOGGER.error("", e); - access = true; - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test flowModel's validate, while element's key is not unique. - * */ @Test public void validateElementKeyNotUnique() { @@ -70,19 +64,14 @@ public void validateElementKeyNotUnique() { try { flowModelValidator.validate(flowModel); access = true; - Assert.assertFalse(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertFalse(access); - } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + } catch (ProcessException | DefinitionException e) { + Assert.assertEquals(ErrorEnum.ELEMENT_KEY_NOT_UNIQUE.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test flowModel's validate, while startEvent's num is not equal 1. - * */ @Test public void validateStartEventNotOne() { @@ -101,39 +90,30 @@ public void validateStartEventNotOne() { try { flowModelValidator.validate(flowModel); access = true; - Assert.assertFalse(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertFalse(access); - } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + } catch (ProcessException | DefinitionException e) { + Assert.assertEquals(ErrorEnum.START_NODE_INVALID.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test flowModel's validate, while endEvent is null. - * */ @Test public void validateWithoutEndEvent() { List flowElementsList = EntityBuilder.buildFlowElementList(); int flowElementsListSize = flowElementsList.size(); - flowElementsList.remove(flowElementsListSize-1); - flowElementsList.remove(flowElementsListSize-2); + flowElementsList.remove(flowElementsListSize - 1); + flowElementsList.remove(flowElementsListSize - 2); FlowModel flowModel = new FlowModel(); flowModel.setFlowElementList(flowElementsList); boolean access = false; try { flowModelValidator.validate(flowModel); access = true; - Assert.assertFalse(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertFalse(access); - } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + } catch (ProcessException | DefinitionException e) { + Assert.assertEquals(ErrorEnum.END_NODE_INVALID.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/ModelValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/ModelValidatorTest.java index c781952d..5ff25782 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/ModelValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/ModelValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.exception.ProcessException; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -11,11 +12,11 @@ public class ModelValidatorTest extends BaseTest { - @Resource ModelValidator modelValidator; + @Resource + private ModelValidator modelValidator; /** * Test modelValidator, while model is normal. - * */ @Test public void validateAccess() { @@ -24,20 +25,14 @@ public void validateAccess() { try { modelValidator.validate(modelStr); access = true; - Assert.assertTrue(access); - } catch (DefinitionException e) { + } catch (DefinitionException | ProcessException e) { LOGGER.error("", e); - Assert.assertTrue(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertTrue(access); } - - + Assert.assertTrue(access); } + /** * Test modelValidator, while model is empty. - * */ @Test public void validateEmptyModel() { @@ -46,14 +41,10 @@ public void validateEmptyModel() { try { modelValidator.validate(modelStr); access = true; - Assert.assertFalse(access); - } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + } catch (DefinitionException | ProcessException e) { + Assert.assertEquals(ErrorEnum.MODEL_EMPTY.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidatorTest.java index 4c25e853..6748cb46 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -21,7 +22,6 @@ public class SequenceFlowValidatorTest extends BaseTest { /** * Test sequenceFlow's checkIncoming, while incoming is normal. - * */ @Test public void checkIncomingAccess() { @@ -32,17 +32,15 @@ public void checkIncomingAccess() { try { sequenceFlowValidator.checkIncoming(flowElementMap, sequenceFlow); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test sequenceFlow's checkIncoming, while incoming is too much. - * */ @Test public void checkTooMuchIncoming() { @@ -57,16 +55,14 @@ public void checkTooMuchIncoming() { try { sequenceFlowValidator.checkIncoming(flowElementMap, sequenceFlow); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_TOO_MANY_INCOMING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test sequenceFlow's checkOutgoing, while outgoing is normal. - * */ @Test public void checkOutgoingAccess() { @@ -78,16 +74,14 @@ public void checkOutgoingAccess() { try { sequenceFlowValidator.checkOutgoing(flowElementMap, sequenceFlow); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test sequenceFlow's outgoing, while outgoing is lack. - * */ @Test public void checkWithoutOutgoing() { @@ -100,10 +94,9 @@ public void checkWithoutOutgoing() { try { sequenceFlowValidator.checkOutgoing(flowElementMap, sequenceFlow); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_OUTGOING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/StartEventValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/StartEventValidatorTest.java index d85a6725..9e2137a4 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/StartEventValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/StartEventValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -16,11 +17,11 @@ public class StartEventValidatorTest extends BaseTest { - @Resource StartEventValidator startEventValidator; + @Resource + StartEventValidator startEventValidator; /** - * Test startEvent's incoming, whlile normal. - * + * Test startEvent's incoming, while normal. */ @Test public void checkIncomingAccess() { @@ -29,24 +30,24 @@ public void checkIncomingAccess() { map.put(startEvent.getKey(), startEvent); startEventValidator.checkIncoming(map, startEvent); } + /** - * Test startEvent's incoming, whlile incoming is too much. - * + * Test startEvent's incoming, when there are too many incomings. */ @Test public void checkTooManyIncoming() { - FlowElement startEventVaild = EntityBuilder.buildStartEvent(); + FlowElement startEvent = EntityBuilder.buildStartEvent(); List incomings = new ArrayList<>(); incomings.add("sequence"); - startEventVaild.setIncoming(incomings); + startEvent.setIncoming(incomings); Map map = new HashMap<>(); - map.put("startEvent", startEventVaild); - startEventValidator.checkIncoming(map, startEventVaild); + map.put("startEvent", startEvent); + // A warning log will be printed when the startEvent's incoming exists. + startEventValidator.checkIncoming(map, startEvent); } /** - * Test startEvent's incoming, whlile normal. - * + * Test startEvent's incoming, while normal. */ @Test public void checkOutgoingAccess() { @@ -57,32 +58,29 @@ public void checkOutgoingAccess() { try { startEventValidator.checkOutgoing(map, startEvent); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } + /** - * Test startEvent's incoming, whlile incoming is too much. - * + * Test startEvent's outgoing, when the outgoing don't exist. */ @Test - public void checkTooMuchOutgoing() { - FlowElement startEventVaild = EntityBuilder.buildStartEvent(); + public void checkEmptyOutgoing() { + FlowElement startEvent = EntityBuilder.buildStartEvent(); List outgoings = new ArrayList<>(); - startEventVaild.setOutgoing(outgoings); + startEvent.setOutgoing(outgoings); Map map = new HashMap<>(); - map.put("startEvent", startEventVaild); + map.put("startEvent", startEvent); boolean access = false; try { - startEventValidator.checkOutgoing(map, startEventVaild); + startEventValidator.checkOutgoing(map, startEvent); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_OUTGOING.getErrNo(), e.getErrNo()); } - + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/UserTaskValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/UserTaskValidatorTest.java index 69d25d94..3dd4b8ac 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/UserTaskValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/UserTaskValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -17,8 +18,7 @@ public class UserTaskValidatorTest extends BaseTest { UserTaskValidator userTaskValidator; /** - * Check userTask's incoming, whlile normal. - * + * Check userTask's incoming, while normal. */ @Test public void checkIncomingAccess() { @@ -29,15 +29,14 @@ public void checkIncomingAccess() { try { userTaskValidator.checkIncoming(map, userTask); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } + /** * Check userTask's incoming, while incoming is lack. - * */ @Test public void checkWithoutIncoming() { @@ -49,17 +48,15 @@ public void checkWithoutIncoming() { try { userTaskValidator.checkIncoming(map, userTask); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_INCOMING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** - * Check userTask's outgoing, whlile normal. - * + * Check userTask's outgoing, while normal. */ @Test public void checkOutgoingAccess() { @@ -70,19 +67,17 @@ public void checkOutgoingAccess() { try { userTaskValidator.checkOutgoing(map, userTask); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Check userTask's outgoing, while outgoing is lack. - * */ @Test - public void checkWithoutOutgoing() { + public void checkEmptyOutgoing() { FlowElement userTask = EntityBuilder.buildUserTask(); userTask.setOutgoing(null); Map map = new HashMap<>(); @@ -91,10 +86,9 @@ public void checkWithoutOutgoing() { try { userTaskValidator.checkOutgoing(map, userTask); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_OUTGOING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/resources/application.properties b/engine/src/test/resources/application.properties index 776e7724..429f5cd2 100644 --- a/engine/src/test/resources/application.properties +++ b/engine/src/test/resources/application.properties @@ -1,14 +1,19 @@ +# h2 +spring.datasource.url=jdbc:h2:mem:test +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=root +spring.datasource.password= + spring.datasource.dynamic.primary=engine spring.datasource.dynamic.datasource.engine.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.dynamic.datasource.engine.username=username spring.datasource.dynamic.datasource.engine.password=password -spring.datasource.dynamic.datasource.engine.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.dynamic.datasource.engine.url=jdbc:mysql://127.0.0.1:3306/t_engine?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&autoReconnect=true +spring.datasource.dynamic.datasource.engine.driver-class-name=org.h2.Driver +spring.datasource.dynamic.datasource.engine.url=jdbc:h2:mem:t_engine;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE -mybatis.configuration.map-underscore-to-camel-case=true -logging.config=classpath:logback-spring.xml +# DDL SQL +spring.datasource.schema=classpath:script/turbo-mysql-h2-ddl.sql -hook.url=http://127.0.0.1:8031/globalInfo/refresh -hook.timeout=3000 +logging.config=classpath:logback-spring.xml diff --git a/engine/src/test/resources/script/turbo-mysql-h2-ddl.sql b/engine/src/test/resources/script/turbo-mysql-h2-ddl.sql new file mode 100644 index 00000000..1005a3d1 --- /dev/null +++ b/engine/src/test/resources/script/turbo-mysql-h2-ddl.sql @@ -0,0 +1,116 @@ +CREATE SCHEMA IF NOT EXISTS turbo; + +CREATE TABLE IF NOT EXISTS `em_flow_definition` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', + `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `flow_model` mediumtext COMMENT '表单定义', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.初始态 2.编辑中 3.已下线)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', + `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_module_id` (`flow_module_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程定义表'; + +CREATE TABLE IF NOT EXISTS `em_flow_deployment` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', + `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `flow_model` mediumtext COMMENT '表单定义', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.已部署 3.已下线)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', + `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_deploy_id` (`flow_deploy_id`), + KEY `idx_flow_module_id` (`flow_module_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程部署表'; + +CREATE TABLE IF NOT EXISTS `ei_flow_instance` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.执行完成 2.执行中 3.执行终止(强制终止))', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_instance_id` (`flow_instance_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程执行实例表'; + +CREATE TABLE IF NOT EXISTS `ei_node_instance` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `source_node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '上一个节点执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `source_node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '上一个流程节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_node_instance_id` (`node_instance_id`), + KEY `idx_fiid_sniid_nk` (`flow_instance_id`,`source_node_instance_id`,`node_key`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行实例表'; + +CREATE TABLE IF NOT EXISTS `ei_node_instance_log` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.系统执行 2.任务提交 3.任务撤销)', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行记录表'; + +CREATE TABLE IF NOT EXISTS `ei_instance_data` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `instance_data` longtext COMMENT '数据列表json', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.实例初始化 2.系统执行 3.系统主动获取 4.上游更新 5.任务提交 6.任务撤回)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_instance_data_id` (`instance_data_id`), + KEY `idx_flow_instance_id` (`flow_instance_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行记录表'; + +-- 在ei_instance_data表中,如果需要存储表情符号, MySQL的建表语句需要切换utf8mb4 \ No newline at end of file From 406f7e4103305ad83477a9f2dbc08b0eed0268db Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 30 May 2023 17:05:57 +0800 Subject: [PATCH 08/24] Improve demo code --- demo/pom.xml | 2 - .../demo/spi/TestExpressionCalculator.java | 42 +++++++++++++++++++ .../src/test/resources/application.properties | 6 +-- 3 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java diff --git a/demo/pom.xml b/demo/pom.xml index 80424b4b..3675e2ca 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -21,7 +21,6 @@ 1.5.10.RELEASE 1.0.2-SNAPSHOT - 1.4.200 @@ -44,7 +43,6 @@ com.h2database h2 - 1.4.200 test diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java new file mode 100644 index 00000000..e7ccc5e7 --- /dev/null +++ b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java @@ -0,0 +1,42 @@ +package com.didiglobal.turbo.demo.spi; + +import com.didiglobal.turbo.engine.exception.ProcessException; +import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator; +import com.google.common.collect.Maps; +import org.springframework.util.Assert; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TestExpressionCalculator implements ExpressionCalculator { + + @Override + public Boolean calculate(String expression, Map dataMap) throws ProcessException { + // 扩展表达式计算方式 + + // 执行正则表达式或者其他语言脚本等,如 python + Pattern compile = Pattern.compile(expression); + Matcher data = compile.matcher((String) dataMap.get("data")); + return data.matches(); + } + + + /** + * test + * + * @param args + */ + public static void main(String[] args) { + TestExpressionCalculator testExpressionCalculator = new TestExpressionCalculator(); + String expression = "[0-9]"; + Map dataMap = Maps.newHashMap(); + dataMap.put("data", "1"); + try { + Boolean result = testExpressionCalculator.calculate(expression, dataMap); + Assert.isTrue(result, "test fail"); + } catch (ProcessException e) { + e.printStackTrace(); + } + } +} diff --git a/demo/src/test/resources/application.properties b/demo/src/test/resources/application.properties index 5da0c6bf..6212bae9 100644 --- a/demo/src/test/resources/application.properties +++ b/demo/src/test/resources/application.properties @@ -1,4 +1,4 @@ -# ????? +# h2 spring.datasource.url=jdbc:h2:mem:test spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=root @@ -12,10 +12,10 @@ spring.datasource.dynamic.datasource.engine.driver-class-name=org.h2.Driver spring.datasource.dynamic.datasource.engine.url=jdbc:h2:mem:t_engine;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE -# DDL?? +# DDL SQL spring.datasource.schema=classpath:script/turbo-mysql-h2-ddl.sql -# DML?? +# DML SQL spring.datasource.data=classpath:script/turbo-mysql-h2-dml.sql logging.config=classpath:logback-spring.xml From 2421f9c7eeca5eddb14d0b91e82fe6b31caae466 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 30 May 2023 17:09:54 +0800 Subject: [PATCH 09/24] Optimize code --- .../java/com/didiglobal/turbo/engine/common/ErrorEnum.java | 4 ++-- .../didiglobal/turbo/engine/validator/EndEventValidator.java | 2 +- .../turbo/engine/validator/SequenceFlowValidator.java | 4 ++-- .../turbo/engine/validator/StartEventValidator.java | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java index 662485c6..913edf87 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java @@ -29,8 +29,8 @@ public enum ErrorEnum { EMPTY_SEQUENCE_OUTGOING(3209, "Empty sequence outgoing"), TOO_MANY_DEFAULT_SEQUENCE(3210, "Too many default sequence"), MODEL_UNKNOWN_ELEMENT_KEY(3211, "Unknown element key"), - ELEMENT_TOO_MUCH_INCOMING(3212, "Too many incoming"), - ELEMENT_TOO_MUCH_OUTGOING(3213, "Too many outgoing"), + ELEMENT_TOO_MANY_INCOMING(3212, "Too many incoming"), + ELEMENT_TOO_MANY_OUTGOING(3213, "Too many outgoing"), ELEMENT_LACK_INCOMING(3214, "Element lack incoming"), ELEMENT_LACK_OUTGOING(3215, "Element lack outgoing"), diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/validator/EndEventValidator.java b/engine/src/main/java/com/didiglobal/turbo/engine/validator/EndEventValidator.java index b9bd67e3..965eb008 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/validator/EndEventValidator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/validator/EndEventValidator.java @@ -25,7 +25,7 @@ protected void checkOutgoing(Map flowElementMap, FlowElemen List outgoing = flowElement.getOutgoing(); if (CollectionUtils.isNotEmpty(outgoing)) { - recordElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_OUTGOING); + recordElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_OUTGOING); } } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidator.java b/engine/src/main/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidator.java index bb6aec51..64cb63ea 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidator.java @@ -17,7 +17,7 @@ public void checkIncoming(Map flowElementMap, FlowElement f List incomingList = flowElement.getIncoming(); if (incomingList.size() >1) { - throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_INCOMING); + throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_INCOMING); } } @@ -27,7 +27,7 @@ public void checkOutgoing(Map flowElementMap, FlowElement f List outgoingList = flowElement.getOutgoing(); if (outgoingList.size() > 1) { - throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_OUTGOING); + throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_OUTGOING); } } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/validator/StartEventValidator.java b/engine/src/main/java/com/didiglobal/turbo/engine/validator/StartEventValidator.java index 02044a00..e5631d41 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/validator/StartEventValidator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/validator/StartEventValidator.java @@ -15,7 +15,7 @@ public class StartEventValidator extends ElementValidator { protected static final Logger LOGGER = LoggerFactory.getLogger(StartEventValidator.class); /** - * CheckIncoming: check userTask's incoming, warn while incoming is not empty. + * CheckIncoming: check startEvent's incoming, warn while incoming is not empty. * * @param flowElementMap, flowElement */ @@ -24,7 +24,7 @@ public void checkIncoming(Map flowElementMap, FlowElement f List incoming = flowElement.getIncoming(); if (CollectionUtils.isNotEmpty(incoming)) { - recordElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_INCOMING); + recordElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_INCOMING); } } } From 6d49d50b2f70524fd1396b06f17a1bca66d09bed Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 30 May 2023 17:10:40 +0800 Subject: [PATCH 10/24] Introducing the h2 database for testing --- engine/pom.xml | 5 +++++ pom.xml | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/engine/pom.xml b/engine/pom.xml index 20b05675..b3541c13 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -88,6 +88,11 @@ lombok provided + + com.h2database + h2 + test + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 92d3d5e6..47b4955f 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,7 @@ 2.3.7 31.0.1-jre 1.18.26 + 1.4.200 @@ -143,6 +144,12 @@ ${lombok.version} provided + + com.h2database + h2 + ${h2.version} + test + From 4ccf7ea476c42a5bea5af56ab55dcc6c26f7098c Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 30 May 2023 19:40:47 +0800 Subject: [PATCH 11/24] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d28b6894..2ad9d962 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,7 @@ spring.datasource.dynamic.datasource.engine.url=jdbc:mysql://127.0.0.1:3306/db_e ``` -## 4. 根据demo开始你的Turbo之旅吧 +## 2. 根据demo开始你的Turbo之旅吧 根据上文提到的turbo支持的特性,给出了两个例子,其中整体的流程如下图所示: @@ -235,7 +235,7 @@ Demo2:请假流程 注:例子使用两个service是为了封装sop,在实际开发中sop是有前端页面传递进入,并非是必须再次开发。 -## 5. Turbo与LogicFlow交互demo +## 3. Turbo与LogicFlow交互demo LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。使用LogicFlow与Turbo接口交互可实现流程图创建,编辑,保存,发布功能,发布完成流程图即可参考第四部分文档,执行流程。 @@ -249,6 +249,6 @@ LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、 代码提供基本用法示例,使用方可以根据自己的业务场景参考使用 -## 6. 联系我们 +## 4. 联系我们 ### 加入微信群 添加微信号:logic-flow 加入turbo用户群 From 3f17b2a348d21ae8d2b4f3bcc50370e7547a33c9 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Fri, 2 Jun 2023 17:13:49 +0800 Subject: [PATCH 12/24] Enhanced expression calculator, supports coexistence of multiple calculators --- .../demo/spi/TestExpressionCalculator.java | 5 +++ .../turbo/engine/common/Constants.java | 1 + .../turbo/engine/common/ErrorEnum.java | 2 ++ .../engine/exception/TurboException.java | 2 +- .../engine/executor/ElementExecutor.java | 7 ++-- .../turbo/engine/spi/TurboServiceLoader.java | 18 +++++----- .../spi/calulator/ExpressionCalculator.java | 7 ++++ .../ExpressionCalculatorFactory.java | 33 +++++++++++++++---- .../calulator/GroovyExpressionCalculator.java | 9 +++++ .../turbo/engine/util/FlowModelUtil.java | 6 ++++ 10 files changed, 70 insertions(+), 20 deletions(-) diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java index e7ccc5e7..11bc2fe8 100644 --- a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java +++ b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java @@ -11,6 +11,11 @@ public class TestExpressionCalculator implements ExpressionCalculator { + @Override + public String getType() { + return "test"; + } + @Override public Boolean calculate(String expression, Map dataMap) throws ProcessException { // 扩展表达式计算方式 diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/Constants.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/Constants.java index 333892a8..f2095431 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/Constants.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/Constants.java @@ -9,6 +9,7 @@ public class Constants { public static final class ELEMENT_PROPERTIES { public static final String NAME = "name"; public static final String CONDITION = "conditionsequenceflow"; + public static final String CONDITION_TYPE = "conditiontypesequenceflow"; public static final String DEFAULT_CONDITION = "defaultConditions"; public static final String HOOK_INFO_IDS = "hookInfoIds"; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java index 913edf87..5cf8282e 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java @@ -53,6 +53,8 @@ public enum ErrorEnum { SAVE_FLOW_INSTANCE_FAILED(4016, "Save flowInstance failed"), SAVE_INSTANCE_DATA_FAILED(4017, "Save instanceData failed"), GROOVY_CALCULATE_FAILED(4018, "Groovy calculate failed"), + NOT_FOUND_EXPRESSION_CALCULATOR(4019, "Not found expression calculator"), + //5000~5999 系统错误 //保留错误码 diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/exception/TurboException.java b/engine/src/main/java/com/didiglobal/turbo/engine/exception/TurboException.java index 0022696e..53acb910 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/exception/TurboException.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/exception/TurboException.java @@ -4,7 +4,7 @@ import java.text.MessageFormat; -public class TurboException extends Exception { +public class TurboException extends RuntimeException { private static final String ERROR_MSG_FORMAT = "{0}({1})"; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java index 9da7dc33..710b4a79 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java @@ -296,7 +296,8 @@ private FlowElement calculateOutgoing(FlowElement flowElement, Map instanceDataMap) throws ProcessException { + protected boolean processCondition(String type, String expression, Map instanceDataMap) throws ProcessException { Map dataMap = InstanceDataUtil.parseInstanceDataMap(instanceDataMap); - return ExpressionCalculatorFactory.getExpressionCalculator().calculate(expression, dataMap); + return ExpressionCalculatorFactory.getExpressionCalculator(type).calculate( expression, dataMap); } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java index d59a7013..0908e5e5 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java @@ -13,8 +13,8 @@ /** * turbo service loader * - * @author lijinghao * @param the type of service + * @author lijinghao */ public class TurboServiceLoader { @@ -25,7 +25,7 @@ public class TurboServiceLoader { @Getter private final Collection services; - private TurboServiceLoader(final Class serviceInterface){ + private TurboServiceLoader(final Class serviceInterface) { this.serviceInterface = serviceInterface; validate(); services = load(); @@ -41,24 +41,24 @@ private Collection load() { private void validate() { Preconditions.checkNotNull(serviceInterface, "SPI interface is null."); - Preconditions.checkArgument(serviceInterface.isInterface(), "SPI interface `%s` is not interface.", serviceInterface); + Preconditions.checkArgument(serviceInterface.isInterface(), + "SPI interface `%s` is not interface.", serviceInterface); } @SuppressWarnings("unchecked") - public static Collection getServiceInterfaces(final Class serviceInterface){ + public static Collection getServiceInterfaces(final Class serviceInterface) { TurboServiceLoader result = LOADERS.get(serviceInterface); - return (Collection) (result != null ? result.getServiceInterfaces(): LOADERS.computeIfAbsent(serviceInterface, TurboServiceLoader::new).getServiceInterfaces()); - + return (Collection) (result != null ? result.getServiceInterfaces() + : LOADERS.computeIfAbsent(serviceInterface, TurboServiceLoader::new).getServiceInterfaces()); } private Collection getServiceInterfaces() { - return serviceInterface.getAnnotation(SingletonSPI.class) == null ? createNewServiceInstances() : getSingletonServiceInstances(); - + return serviceInterface.getAnnotation(SingletonSPI.class) == null ? createNewServiceInstances() + : getSingletonServiceInstances(); } private Collection getSingletonServiceInstances() { return services; - } @SneakyThrows(ReflectiveOperationException.class) diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java index 93de2097..14b9e7fa 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java @@ -11,6 +11,13 @@ @SingletonSPI public interface ExpressionCalculator { + /** + * 获取表达式计算器类型 + * + * @return + */ + String getType(); + /** * Execute the conditional expression and get the result of the evaluation * diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java index d1f40d75..b0e9c8a8 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java @@ -1,9 +1,11 @@ package com.didiglobal.turbo.engine.spi.calulator; +import com.didiglobal.turbo.engine.common.ErrorEnum; +import com.didiglobal.turbo.engine.exception.TurboException; import com.didiglobal.turbo.engine.spi.TurboServiceLoader; +import org.apache.commons.lang3.StringUtils; -import java.util.Collection; -import java.util.Optional; +import java.util.*; /** * expression calculator factory @@ -13,22 +15,39 @@ public class ExpressionCalculatorFactory { /** - * expression calculator + * default expression calculator */ - private static final ExpressionCalculator EXPRESSION_CALCULATOR; + private static final ExpressionCalculator DEFAULT_EXPRESSION_CALCULATOR; + + /** + * all calculators + */ + private static final Map CALCULATORS = new LinkedHashMap<>(); static { Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); - // In the order in which the services are loaded, take the first implementation + serviceInterfaces.forEach(service -> CALCULATORS.put(service.getType(), service)); + // In the order in which the services are loaded, take the first implementation as default Optional optional = serviceInterfaces.stream().findFirst(); if (optional.isPresent()) { - EXPRESSION_CALCULATOR = optional.get(); + DEFAULT_EXPRESSION_CALCULATOR = optional.get(); } else { throw new RuntimeException("spi load exception: not found Implementation class of interface ExpressionCalculator"); } } public static ExpressionCalculator getExpressionCalculator() { - return EXPRESSION_CALCULATOR; + return DEFAULT_EXPRESSION_CALCULATOR; + } + + public static ExpressionCalculator getExpressionCalculator(String type) { + if(StringUtils.isBlank(type)){ + return DEFAULT_EXPRESSION_CALCULATOR; + } + if(!CALCULATORS.containsKey(type)){ + throw new TurboException(ErrorEnum.NOT_FOUND_EXPRESSION_CALCULATOR, + String.format("Not found expression calculator for %s", type)); + } + return CALCULATORS.get(type); } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java index 90e85354..3fa4f38c 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java @@ -13,11 +13,20 @@ /** * Implementation of calculator that uses script based on `Groovy` + *

+ * Expressions can be wrapped with ${} or written without anything + * ep: + * ${key_test > 0} or key_test > 0 */ public class GroovyExpressionCalculator implements ExpressionCalculator { private static final Logger LOGGER = LoggerFactory.getLogger(GroovyExpressionCalculator.class); + @Override + public String getType() { + return "groovy"; + } + @Override public Boolean calculate(String expression, Map dataMap) throws ProcessException { if (expression.startsWith("${") && expression.endsWith("}")) { diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/FlowModelUtil.java b/engine/src/main/java/com/didiglobal/turbo/engine/util/FlowModelUtil.java index f79e33a3..bf0c8402 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/FlowModelUtil.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/util/FlowModelUtil.java @@ -107,6 +107,12 @@ public static String getConditionFromSequenceFlow(FlowElement flowElement) { return (String) properties.get(Constants.ELEMENT_PROPERTIES.CONDITION); } + public static String getCalculatorTypeFromSequenceFlow(FlowElement flowElement) { + Map properties = flowElement.getProperties(); + Object type = properties.get(Constants.ELEMENT_PROPERTIES.CONDITION_TYPE); + return type == null ? StringUtils.EMPTY : (String) type; + } + public static boolean isDefaultCondition(FlowElement flowElement) { Map properties = flowElement.getProperties(); String isDefaultStr = (String) properties.get(Constants.ELEMENT_PROPERTIES.DEFAULT_CONDITION); From 9c777f6aeb99e4b394ce964ac0fe20aec4893734 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Fri, 2 Jun 2023 17:22:56 +0800 Subject: [PATCH 13/24] Enhanced expression calculator, supports coexistence of multiple calculators --- .../engine/spi/calulator/ExpressionCalculatorFactory.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java index b0e9c8a8..79f800eb 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java @@ -36,10 +36,6 @@ public class ExpressionCalculatorFactory { } } - public static ExpressionCalculator getExpressionCalculator() { - return DEFAULT_EXPRESSION_CALCULATOR; - } - public static ExpressionCalculator getExpressionCalculator(String type) { if(StringUtils.isBlank(type)){ return DEFAULT_EXPRESSION_CALCULATOR; @@ -50,4 +46,8 @@ public static ExpressionCalculator getExpressionCalculator(String type) { } return CALCULATORS.get(type); } + + public static boolean contains(String type){ + return CALCULATORS.containsKey(type); + } } From fedf65c5eeb9628d8719a198ba02d7b9dd22347c Mon Sep 17 00:00:00 2001 From: lijinghao Date: Fri, 2 Jun 2023 17:23:33 +0800 Subject: [PATCH 14/24] add test for spi --- .../engine/spi/TurboServiceLoaderTest.java | 23 +++++++ .../ExpressionCalculatorFactoryTest.java | 33 ++++++++++ .../GroovyExpressionCalculatorTest.java | 60 +++++++++++++++++++ .../PatternExpressionCalculator.java | 25 ++++++++ .../calulator/TestExpressionCalculator.java | 25 ++++++++ .../spi/generator/IdGenerateFactoryTest.java | 16 +++++ .../generator/StrongUuidGeneratorTest.java} | 11 ++-- .../engine/util/ExpressionCalculatorTest.java | 29 --------- ....engine.spi.calulator.ExpressionCalculator | 2 + 9 files changed, 188 insertions(+), 36 deletions(-) create mode 100644 engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java create mode 100644 engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactoryTest.java create mode 100644 engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculatorTest.java create mode 100644 engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/PatternExpressionCalculator.java create mode 100644 engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java create mode 100644 engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactoryTest.java rename engine/src/test/java/com/didiglobal/turbo/engine/{util/IdGeneratorTest.java => spi/generator/StrongUuidGeneratorTest.java} (64%) delete mode 100644 engine/src/test/java/com/didiglobal/turbo/engine/util/ExpressionCalculatorTest.java create mode 100644 engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java new file mode 100644 index 00000000..2b74bca3 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java @@ -0,0 +1,23 @@ +package com.didiglobal.turbo.engine.spi; + +import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.generator.IdGenerator; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collection; + +public class TurboServiceLoaderTest { + + @Test + public void assertExpressionCalculatorExists(){ + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); + Assert.assertTrue(serviceInterfaces.size() > 0); + } + + @Test + public void assertIdGeneratorExists(){ + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(IdGenerator.class); + Assert.assertTrue(serviceInterfaces.size() > 0); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactoryTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactoryTest.java new file mode 100644 index 00000000..0d278af4 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactoryTest.java @@ -0,0 +1,33 @@ +package com.didiglobal.turbo.engine.spi.calulator; + +import org.junit.Assert; +import org.junit.Test; + +public class ExpressionCalculatorFactoryTest { + + @Test + public void assertGroovyExpressionCalculatorExists() { + Assert.assertTrue(ExpressionCalculatorFactory.contains("groovy")); + Assert.assertTrue(ExpressionCalculatorFactory.contains("pattern")); + Assert.assertTrue(ExpressionCalculatorFactory.contains("test")); + } + + + @Test + public void assertNotExists() { + Assert.assertFalse(ExpressionCalculatorFactory.contains("Tn3UI7")); + } + + @Test + public void assertExpressionCalculatorExistsWithNoType(){ + ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); + Assert.assertNotNull(defaultExpressionCalculator); + } + + @Test + public void assertDefaultExpressionCalculatorNotGroovy(){ + ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); + Assert.assertFalse(defaultExpressionCalculator instanceof GroovyExpressionCalculator); + } + +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculatorTest.java new file mode 100644 index 00000000..aa7a1fe9 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculatorTest.java @@ -0,0 +1,60 @@ +package com.didiglobal.turbo.engine.spi.calulator; + +import com.didiglobal.turbo.engine.exception.ProcessException; +import com.google.common.collect.Maps; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class GroovyExpressionCalculatorTest { + + @Test + public void testCompare(){ + String expression = "${key_long < key_int}"; + Assert.assertFalse(ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, getData())); + } + + @Test + public void testCalculate(){ + String expression = "${key_long + key_int == 223}"; + Assert.assertTrue(ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, getData())); + } + + @Test + public void testList(){ + String expression = "key_list.contains(1)"; + Assert.assertTrue(ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, getData())); + } + + @Test + public void testNoSuchProperty(){ + String expression = "key_none.contains(1)"; + Boolean result = false; + try { + result = ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, getData()); + } catch (ProcessException e) { + // do nothing + } + Assert.assertFalse(result); + } + + + public Map getData(){ + Map data = Maps.newHashMap(); + data.put("key_string", "test string"); + data.put("key_long", 123L); + data.put("key_int", 100); + data.put("key_double", 10.1d); + data.put("key_float", 20.2); + data.put("key_boolean", false); + data.put("key_list", getList()); + return data; + } + + private List getList() { + return Arrays.asList(1,2,3,4,5); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/PatternExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/PatternExpressionCalculator.java new file mode 100644 index 00000000..40721c60 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/PatternExpressionCalculator.java @@ -0,0 +1,25 @@ +package com.didiglobal.turbo.engine.spi.calulator; + +import com.didiglobal.turbo.engine.exception.ProcessException; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * test pattern calculator + */ +public class PatternExpressionCalculator implements ExpressionCalculator { + + @Override + public String getType() { + return "pattern"; + } + + @Override + public Boolean calculate(String expression, Map dataMap) throws ProcessException { + Pattern compile = Pattern.compile(expression); + Matcher data = compile.matcher((String) dataMap.get("data")); + return data.matches(); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java new file mode 100644 index 00000000..0d36e27d --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java @@ -0,0 +1,25 @@ +package com.didiglobal.turbo.engine.spi.calulator; + +import com.didiglobal.turbo.engine.exception.ProcessException; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * test calculator + */ +public class TestExpressionCalculator implements ExpressionCalculator { + + @Override + public String getType() { + return "test"; + } + + @Override + public Boolean calculate(String expression, Map dataMap) throws ProcessException { + Pattern compile = Pattern.compile(expression); + Matcher data = compile.matcher((String) dataMap.get("data")); + return data.matches(); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactoryTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactoryTest.java new file mode 100644 index 00000000..b7b1995e --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactoryTest.java @@ -0,0 +1,16 @@ +package com.didiglobal.turbo.engine.spi.generator; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +public class IdGenerateFactoryTest { + + @Test + public void assertExists() { + IdGenerator idGenerator = IdGenerateFactory.getIdGenerator(); + Assert.assertNotNull(idGenerator); + Assert.assertTrue(StringUtils.isNotBlank(idGenerator.getNextId())); + } + +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGeneratorTest.java similarity index 64% rename from engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java rename to engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGeneratorTest.java index dd555855..20767b5a 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGeneratorTest.java @@ -1,15 +1,12 @@ -package com.didiglobal.turbo.engine.util; +package com.didiglobal.turbo.engine.spi.generator; -import com.didiglobal.turbo.engine.spi.generator.IdGenerateFactory; -import com.didiglobal.turbo.engine.spi.generator.IdGenerator; -import com.didiglobal.turbo.engine.spi.generator.StrongUuidGenerator; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class IdGeneratorTest { +public class StrongUuidGeneratorTest { - private static final Logger LOGGER = LoggerFactory.getLogger(IdGeneratorTest.class); + private static final Logger LOGGER = LoggerFactory.getLogger(StrongUuidGeneratorTest.class); private final IdGenerator idGenerator = IdGenerateFactory.getIdGenerator(); @@ -20,7 +17,7 @@ public void testDoExecute() { for (int i = 0; i < count; i++) { String nextId = idGenerator.getNextId(); if (LOGGER.isDebugEnabled()) { - LOGGER.info(nextId); + LOGGER.debug(nextId); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/ExpressionCalculatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/ExpressionCalculatorTest.java deleted file mode 100644 index 544d1216..00000000 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/ExpressionCalculatorTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.didiglobal.turbo.engine.util; - -import com.didiglobal.turbo.engine.exception.ProcessException; -import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator; -import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculatorFactory; -import com.google.common.collect.Maps; -import org.junit.Assert; -import org.junit.Test; - -import java.util.Map; - -/** - * @author lijinghao - * @version v1.0 - * @date 2023/5/30 2:55 PM - */ -public class ExpressionCalculatorTest { - - private final ExpressionCalculator expressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(); - - @Test - public void testExpressionCalculator() throws ProcessException { - String expression = "str.length() > 2"; - Map data = Maps.newHashMap(); - data.put("str", "1234"); - Boolean result = expressionCalculator.calculate(expression, data); - Assert.assertTrue(result); - } -} diff --git a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator new file mode 100644 index 00000000..926fa58a --- /dev/null +++ b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator @@ -0,0 +1,2 @@ +com.didiglobal.turbo.engine.spi.calulator.PatternExpressionCalculator +com.didiglobal.turbo.engine.spi.calulator.TestExpressionCalculator \ No newline at end of file From 06edbdf3842852d9b71784b8ae1c7678aac0bd30 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Fri, 2 Jun 2023 18:07:10 +0800 Subject: [PATCH 15/24] add test for spi --- .../demo/spi/TestExpressionCalculator.java | 19 ++++++++++--------- .../turbo/demo/spi/TestIdGenerator.java | 2 +- ....engine.spi.calulator.ExpressionCalculator | 1 + .../calulator/TestExpressionCalculator.java | 9 ++++++--- ....engine.spi.calulator.ExpressionCalculator | 2 +- 5 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java index 11bc2fe8..1db64da1 100644 --- a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java +++ b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java @@ -2,15 +2,18 @@ import com.didiglobal.turbo.engine.exception.ProcessException; import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculatorFactory; import com.google.common.collect.Maps; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.util.Assert; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class TestExpressionCalculator implements ExpressionCalculator { + private static final Logger LOGGER = LoggerFactory.getLogger(TestExpressionCalculator.class); + @Override public String getType() { return "test"; @@ -18,15 +21,13 @@ public String getType() { @Override public Boolean calculate(String expression, Map dataMap) throws ProcessException { - // 扩展表达式计算方式 - - // 执行正则表达式或者其他语言脚本等,如 python - Pattern compile = Pattern.compile(expression); - Matcher data = compile.matcher((String) dataMap.get("data")); - return data.matches(); + // You can customize the implementation, + // and the code here serves as an example of extending the calculation expression + // Because all calculations in the demo use groovy, the groovy method will also be used here + LOGGER.info("enter TestExpressionCalculator, but use groovy for test"); + return ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, dataMap); } - /** * test * diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java index ebfcf098..e0c78f2c 100644 --- a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java +++ b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java @@ -7,7 +7,7 @@ public class TestIdGenerator implements IdGenerator { @Override public String getNextId() { - // 通过这种方式扩展自己的ID生成器 + // Expand your ID generator in this way return RandomStringUtils.randomAlphabetic(20); } } diff --git a/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator new file mode 100644 index 00000000..01fc9434 --- /dev/null +++ b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator @@ -0,0 +1 @@ +com.didiglobal.turbo.demo.spi.TestExpressionCalculator \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java index 0d36e27d..e8d323d0 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java @@ -1,6 +1,8 @@ package com.didiglobal.turbo.engine.spi.calulator; import com.didiglobal.turbo.engine.exception.ProcessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Map; import java.util.regex.Matcher; @@ -11,6 +13,8 @@ */ public class TestExpressionCalculator implements ExpressionCalculator { + private static final Logger LOGGER = LoggerFactory.getLogger(TestExpressionCalculator.class); + @Override public String getType() { return "test"; @@ -18,8 +22,7 @@ public String getType() { @Override public Boolean calculate(String expression, Map dataMap) throws ProcessException { - Pattern compile = Pattern.compile(expression); - Matcher data = compile.matcher((String) dataMap.get("data")); - return data.matches(); + LOGGER.info("enter TestExpressionCalculator, but use groovy for test"); + return ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, dataMap); } } diff --git a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator index 926fa58a..39c60bbe 100644 --- a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator +++ b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator @@ -1,2 +1,2 @@ +com.didiglobal.turbo.engine.spi.calulator.TestExpressionCalculator com.didiglobal.turbo.engine.spi.calulator.PatternExpressionCalculator -com.didiglobal.turbo.engine.spi.calulator.TestExpressionCalculator \ No newline at end of file From bc4f61ae58d2340c50db2bb497866f6bd1334cc8 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Mon, 5 Jun 2023 11:08:50 +0800 Subject: [PATCH 16/24] del invalid class --- .../turbo/engine/common/RedisConstants.java | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/common/RedisConstants.java diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/RedisConstants.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/RedisConstants.java deleted file mode 100644 index 9ec48ae2..00000000 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/RedisConstants.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.didiglobal.turbo.engine.common; - -public class RedisConstants { - - public static final String REDIS_PREFIX = "ior:"; //basic - - //k=flowDeployId; v=deployId+flowModuleId+tenantId+flowModel - public static final String FLOW_INFO = REDIS_PREFIX + "flow_info_"; - - //k=flowInstanceId; v=flowInstanceId+deployId+status - public static final String FLOW_INSTANCE = REDIS_PREFIX + "flow_instance_"; - - public static final int FLOW_EXPIRED_SECOND = 30 * 24 * 60 * 60; //30 days - - public static final int FLOW_INSTANCE_EXPIRED_SECOND = 24 * 60 * 60; //1 day -} From f3b691b33c4bb4b14bd09265113b7e9ed1165f16 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Mon, 5 Jun 2023 11:09:50 +0800 Subject: [PATCH 17/24] optimize comments --- .../turbo/engine/common/ErrorEnum.java | 16 +++---- .../engine/common/FlowDefinitionStatus.java | 23 ++++++++-- .../engine/common/FlowDeploymentStatus.java | 18 ++++++-- .../engine/common/FlowInstanceStatus.java | 8 ++-- .../turbo/engine/common/FlowModuleStatus.java | 8 ++-- .../turbo/engine/common/InstanceDataType.java | 46 ++++++++++++++++--- .../engine/common/NodeInstanceStatus.java | 10 ++-- .../turbo/engine/common/NodeInstanceType.java | 8 ++-- .../turbo/engine/common/ProcessStatus.java | 13 ++++-- .../turbo/engine/common/RuntimeContext.java | 6 ++- .../turbo/engine/hook/HookService.java | 7 --- .../turbo/engine/model/FlowElement.java | 27 +++++++++-- .../engine/processor/RuntimeProcessor.java | 4 +- .../ExpressionCalculatorFactory.java | 16 +++++-- .../processor/RuntimeProcessorTest.java | 4 +- 15 files changed, 150 insertions(+), 64 deletions(-) diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java index 5cf8282e..73f0aa1a 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java @@ -2,16 +2,16 @@ public enum ErrorEnum { - //1000~1999 非阻断性错误码 + // 1000~1999, non blocking error code SUCCESS(1000, "Success"), REENTRANT_WARNING(1001, "Reentrant warning"), COMMIT_SUSPEND(1002, "Commit task suspend"), ROLLBACK_SUSPEND(1003, "Rollback task suspend"), - //2000~2999 通用业务错误 + // 2000~2999, general business error PARAM_INVALID(2001, "Invalid param"), - //3000~3999 流程定义错误 + // 3000~3999, process definition error DEFINITION_INSERT_INVALID(3001, "Definition insert failed"), DEFINITION_UPDATE_INVALID(3002, "Definition update failed"), @@ -34,11 +34,11 @@ public enum ErrorEnum { ELEMENT_LACK_INCOMING(3214, "Element lack incoming"), ELEMENT_LACK_OUTGOING(3215, "Element lack outgoing"), - //4000~4999 流程执行错误 + // 4000~4999, process definition error COMMIT_FAILED(4001, "Commit task failed"), ROLLBACK_FAILED(4002, "Rollback task failed"), - COMMIT_REJECTRD(4003, "Commit rejected, flow is terminate"), - ROLLBACK_REJECTRD(4004, "Rollback rejected, non-running flowInstance to rollback"), + COMMIT_REJECTED(4003, "Commit rejected, flow is terminate"), + ROLLBACK_REJECTED(4004, "Rollback rejected, non-running flowInstance to rollback"), NO_NODE_TO_ROLLBACK(4005, "No node to rollback"), NO_USER_TASK_TO_ROLLBACK(4006, "No userTask to rollback"), GET_FLOW_DEPLOYMENT_FAILED(4007, "Get flowDeployment failed"), @@ -56,8 +56,8 @@ public enum ErrorEnum { NOT_FOUND_EXPRESSION_CALCULATOR(4019, "Not found expression calculator"), - //5000~5999 系统错误 - //保留错误码 + // 5000~5999, system error + // reserved error code SYSTEM_ERROR(5000, "System error"), FAILED(5001, "Failed"); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDefinitionStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDefinitionStatus.java index 88a19700..973f1f47 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDefinitionStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDefinitionStatus.java @@ -1,8 +1,23 @@ package com.didiglobal.turbo.engine.common; public class FlowDefinitionStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int INIT = 1; //流程创建, 初始化 - public static final int EDITING = 2; //编辑中 - public static final int DISABLED = 3; //已下线, 暂未使用 + /** + * Db default status + */ + public static final int DEFAULT = 0; + + /** + * Initialize state during process creation + */ + public static final int INIT = 1; + + /** + * Editing + */ + public static final int EDITING = 2; + + /** + * Offline, not currently in use + */ + public static final int DISABLED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDeploymentStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDeploymentStatus.java index 40e24020..6ad80ec8 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDeploymentStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDeploymentStatus.java @@ -1,7 +1,19 @@ package com.didiglobal.turbo.engine.common; public class FlowDeploymentStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int DEPLOYED = 1; //已部署 - public static final int DISABLED = 3; //已下线, 暂未使用 + + /** + * Db default status + */ + public static final int DEFAULT = 0; + + /** + * Deployed + */ + public static final int DEPLOYED = 1; + + /** + * Offline, not currently in use + */ + public static final int DISABLED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowInstanceStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowInstanceStatus.java index 5f5b299c..780eef3a 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowInstanceStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowInstanceStatus.java @@ -1,8 +1,8 @@ package com.didiglobal.turbo.engine.common; public class FlowInstanceStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int COMPLETED = 1; //执行完成 - public static final int RUNNING = 2; //执行中 - public static final int TERMINATED = 3; //已终止 + public static final int DEFAULT = 0; + public static final int COMPLETED = 1; + public static final int RUNNING = 2; + public static final int TERMINATED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowModuleStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowModuleStatus.java index 65ecea16..53cca392 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowModuleStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowModuleStatus.java @@ -1,8 +1,8 @@ package com.didiglobal.turbo.engine.common; public class FlowModuleStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int EDITING = 1; //编辑中 - public static final int DEPLOYED = 2; //已部署 - public static final int DISABLED = 3; //已下线, 暂未使用 + public static final int DEFAULT = 0; + public static final int EDITING = 1; + public static final int DEPLOYED = 2; + public static final int DISABLED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/InstanceDataType.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/InstanceDataType.java index 81881eee..e4af8231 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/InstanceDataType.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/InstanceDataType.java @@ -1,11 +1,43 @@ package com.didiglobal.turbo.engine.common; +/** + * Type of instance data recording + */ public class InstanceDataType { - public static final int DEFAULT = 0; //数据库默认值 - public static final int INIT = 1; //实例初始化 - public static final int EXECUTE = 2; //系统执行 - public static final int HOOK = 3; //系统主动获取 - public static final int UPDATE = 4; //上游更新 - public static final int COMMIT = 5; //任务提交 - public static final int ROLLBACK = 6; //任务回滚(暂时无用, 回滚时不产生新数据, 只修改数据版本号(dbId)) + /** + * Default + */ + public static final int DEFAULT = 0; + + /** + * Instance initialization + */ + public static final int INIT = 1; + + /** + * Flow execute + */ + public static final int EXECUTE = 2; + + /** + * Active acquisition by the system + */ + public static final int HOOK = 3; + + /** + * Invoker actively updates + */ + public static final int UPDATE = 4; + + /** + * Submit Task + */ + public static final int COMMIT = 5; + + /** + * Rollback Task + * Not used. No new data is generated during rollback, + * only the data version number (dbId) is modified + */ + public static final int ROLLBACK = 6; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceStatus.java index c76992c3..c292a438 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceStatus.java @@ -1,9 +1,9 @@ package com.didiglobal.turbo.engine.common; public class NodeInstanceStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int COMPLETED = 1; //处理成功 - public static final int ACTIVE = 2; //处理中 - public static final int FAILED = 3; //处理失败 - public static final int DISABLED = 4; //处理已撤销 + public static final int DEFAULT = 0; + public static final int COMPLETED = 1; + public static final int ACTIVE = 2; + public static final int FAILED = 3; + public static final int DISABLED = 4; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceType.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceType.java index 546f330d..c6006a09 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceType.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceType.java @@ -1,8 +1,8 @@ package com.didiglobal.turbo.engine.common; public class NodeInstanceType { - public static final int DEFAULT = 0; //数据库默认值 - public static final int EXECUTE = 1; //系统执行 - public static final int COMMIT = 2; //任务提交 - public static final int ROLLBACK = 3; //任务撤销 + public static final int DEFAULT = 0; + public static final int EXECUTE = 1; + public static final int COMMIT = 2; + public static final int ROLLBACK = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/ProcessStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/ProcessStatus.java index 1cf89d66..70a2ee42 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/ProcessStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/ProcessStatus.java @@ -1,7 +1,14 @@ package com.didiglobal.turbo.engine.common; public class ProcessStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int SUCCESS = 1; //已完成 - public static final int FAILED = 3; //已撤销 + public static final int DEFAULT = 0; + /** + * Processing completed + */ + public static final int SUCCESS = 1; + + /** + * Processing revoked + */ + public static final int FAILED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/RuntimeContext.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/RuntimeContext.java index e2046a8a..783f6ee2 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/RuntimeContext.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/RuntimeContext.java @@ -21,8 +21,10 @@ public class RuntimeContext { //2.1 flowInstance info private String flowInstanceId; private int flowInstanceStatus; - private NodeInstanceBO suspendNodeInstance; //point to the userTaskInstance to commit/rollback - private List nodeInstanceList; //processed nodeInstance list + //point to the userTaskInstance to commit/rollback + private NodeInstanceBO suspendNodeInstance; + //processed nodeInstance list + private List nodeInstanceList; //2.2 current info private FlowElement currentNodeModel; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java b/engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java index 2cc7df6d..3aed1369 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java @@ -4,13 +4,6 @@ import java.util.List; -/** - * HookService - * - * @author lijinghao - * @version v1.0 - * @date 2023/2/16 6:59 PM - */ public interface HookService { /** diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/model/FlowElement.java b/engine/src/main/java/com/didiglobal/turbo/engine/model/FlowElement.java index 4907f662..9a72a297 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/model/FlowElement.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/model/FlowElement.java @@ -6,12 +6,31 @@ import java.util.Map; public class FlowElement { - private String key; // 流程内元素唯一key resourceId - private int type; // stencil 类型 - private List outgoing; - private Map properties; // 配置属性 + /** + * Unique key in flow element, resourceId + */ + private String key; + + /** + * The type of element + */ + private int type; + + /** + * List of elements before the current element + */ private List incoming; + /** + * List of elements following the current element + */ + private List outgoing; + + /** + * Element configuration attributes, which can be used to extend + */ + private Map properties; + public String getKey() { return key; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/processor/RuntimeProcessor.java b/engine/src/main/java/com/didiglobal/turbo/engine/processor/RuntimeProcessor.java index 50e3836a..f3dfe2f4 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/processor/RuntimeProcessor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/processor/RuntimeProcessor.java @@ -130,7 +130,7 @@ public CommitTaskResult commit(CommitTaskParam commitTaskParam) { //3.check status if (flowInstanceBO.getStatus() == FlowInstanceStatus.TERMINATED) { LOGGER.warn("commit failed: flowInstance has been completed.||commitTaskParam={}", commitTaskParam); - throw new ProcessException(ErrorEnum.COMMIT_REJECTRD); + throw new ProcessException(ErrorEnum.COMMIT_REJECTED); } if (flowInstanceBO.getStatus() == FlowInstanceStatus.COMPLETED) { LOGGER.warn("commit: reentrant process.||commitTaskParam={}", commitTaskParam); @@ -205,7 +205,7 @@ public RollbackTaskResult rollback(RollbackTaskParam rollbackTaskParam) { if (flowInstanceBO.getStatus() != FlowInstanceStatus.RUNNING) { LOGGER.warn("rollback failed: invalid status to rollback.||rollbackTaskParam={}||status={}", rollbackTaskParam, flowInstanceBO.getStatus()); - throw new ProcessException(ErrorEnum.ROLLBACK_REJECTRD); + throw new ProcessException(ErrorEnum.ROLLBACK_REJECTED); } String flowDeployId = flowInstanceBO.getFlowDeployId(); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java index 79f800eb..b071aa1a 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java @@ -9,8 +9,6 @@ /** * expression calculator factory - * - * @author lijinghao */ public class ExpressionCalculatorFactory { @@ -36,18 +34,26 @@ public class ExpressionCalculatorFactory { } } + /** + * Get the calculator by type + *

+ * If no type is passed in, use the first calculator loaded by SPI + * + * @param type type of calculator + * @return ExpressionCalculator + */ public static ExpressionCalculator getExpressionCalculator(String type) { - if(StringUtils.isBlank(type)){ + if (StringUtils.isBlank(type)) { return DEFAULT_EXPRESSION_CALCULATOR; } - if(!CALCULATORS.containsKey(type)){ + if (!CALCULATORS.containsKey(type)) { throw new TurboException(ErrorEnum.NOT_FOUND_EXPRESSION_CALCULATOR, String.format("Not found expression calculator for %s", type)); } return CALCULATORS.get(type); } - public static boolean contains(String type){ + public static boolean contains(String type) { return CALCULATORS.containsKey(type); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java index 63fe412f..249a140d 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java @@ -152,7 +152,7 @@ public void testCommitTerminatedFlowInstance() { commitTaskParam.setVariables(variables); CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); - Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_REJECTRD.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_REJECTED.getErrNo()); } // UserTask <- ExclusiveGateway <- UserTask : Commit old UserTask @@ -291,7 +291,7 @@ public void testRollbackFromEndEvent() { RollbackTaskResult rollbackTaskResult = runtimeProcessor.rollback(rollbackTaskParam); LOGGER.info("testRollback.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.ROLLBACK_REJECTRD.getErrNo()); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.ROLLBACK_REJECTED.getErrNo()); } @Test From 1a70fcda65f56c92ebe79ad658c13d7165ff2120 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Mon, 5 Jun 2023 11:40:45 +0800 Subject: [PATCH 18/24] optimize test --- .../didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java | 6 +++--- .../com/didiglobal/turbo/engine/util/EntityBuilder.java | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java index 62c904a8..981ba583 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java @@ -18,14 +18,14 @@ public class NodeInstanceDAOTest extends BaseTest { @Test public void insert(){ - NodeInstancePO nodeInstancePO = EntityBuilder.buildNodeInstancePO(); + NodeInstancePO nodeInstancePO = EntityBuilder.buildDynamicNodeInstancePO(); int result = nodeInstanceDAO.insert(nodeInstancePO); Assert.assertEquals(1, result); } @Test public void insertOrUpdateList(){ - NodeInstancePO nodeInstancePO = EntityBuilder.buildNodeInstancePO(); + NodeInstancePO nodeInstancePO = EntityBuilder.buildDynamicNodeInstancePO(); nodeInstanceDAO.insert(nodeInstancePO); nodeInstancePO = nodeInstanceDAO.selectByNodeInstanceId(nodeInstancePO.getFlowInstanceId(), nodeInstancePO.getNodeInstanceId()); List nodeInstancePOList = new ArrayList<>(); @@ -38,7 +38,7 @@ public void insertOrUpdateList(){ @Test public void updateStatus() { - NodeInstancePO nodeInstancePO = EntityBuilder.buildNodeInstancePO(); + NodeInstancePO nodeInstancePO = EntityBuilder.buildDynamicNodeInstancePO(); nodeInstanceDAO.insert(nodeInstancePO); nodeInstanceDAO.updateStatus(nodeInstancePO, NodeInstanceStatus.COMPLETED); diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/EntityBuilder.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/EntityBuilder.java index 42ce7f1e..8d3f04a0 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/EntityBuilder.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/util/EntityBuilder.java @@ -386,7 +386,7 @@ public static FlowInstancePO buildFlowInstancePO() { public static FlowInstancePO buildDynamicFlowInstancePO() { FlowInstancePO flowInstancePO = EntityBuilder.buildFlowInstancePO(); - flowInstancePO.setFlowInstanceId("testFlowInstanceId_" + System.currentTimeMillis() + new Random().nextInt()); + flowInstancePO.setFlowInstanceId("testFlowInstanceId_" + UUID.randomUUID()); return flowInstancePO; } @@ -409,8 +409,8 @@ public static NodeInstancePO buildNodeInstancePO() { public static NodeInstancePO buildDynamicNodeInstancePO() { NodeInstancePO nodeInstancePO = buildNodeInstancePO(); - nodeInstancePO.setNodeInstanceId("testNodeInstanceId_" + UUID.randomUUID().toString()); - nodeInstancePO.setSourceNodeInstanceId("testSourceNodeInstanceId_" + UUID.randomUUID().toString()); + nodeInstancePO.setNodeInstanceId("testNodeInstanceId_" + UUID.randomUUID()); + nodeInstancePO.setSourceNodeInstanceId("testSourceNodeInstanceId_" + UUID.randomUUID()); return nodeInstancePO; } @@ -461,7 +461,7 @@ public static InstanceDataPO buildInstanceDataPO() { public static InstanceDataPO buildDynamicInstanceDataPO() { InstanceDataPO instanceDataPO = buildInstanceDataPO(); - instanceDataPO.setInstanceDataId("testInstanceDataId_" + System.currentTimeMillis() + new Random().nextInt()); + instanceDataPO.setInstanceDataId("testInstanceDataId_" + UUID.randomUUID()); return instanceDataPO; } From 85df30a67ce614b87fb8147fada3e98138a9aea4 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Mon, 5 Jun 2023 15:41:47 +0800 Subject: [PATCH 19/24] fix package name --- .../didiglobal/turbo/demo/spi/TestExpressionCalculator.java | 4 ++-- ...diglobal.turbo.engine.spi.calculator.ExpressionCalculator} | 0 .../com/didiglobal/turbo/engine/executor/ElementExecutor.java | 2 +- .../spi/{calulator => calculator}/ExpressionCalculator.java | 2 +- .../ExpressionCalculatorFactory.java | 2 +- .../{calulator => calculator}/GroovyExpressionCalculator.java | 2 +- ...idiglobal.turbo.engine.spi.calculator.ExpressionCalculator | 1 + ...didiglobal.turbo.engine.spi.calulator.ExpressionCalculator | 1 - .../didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java | 2 +- .../ExpressionCalculatorFactoryTest.java | 2 +- .../GroovyExpressionCalculatorTest.java | 2 +- .../PatternExpressionCalculator.java | 2 +- .../{calulator => calculator}/TestExpressionCalculator.java | 4 +--- ...idiglobal.turbo.engine.spi.calculator.ExpressionCalculator | 2 ++ ...didiglobal.turbo.engine.spi.calulator.ExpressionCalculator | 2 -- 15 files changed, 14 insertions(+), 16 deletions(-) rename demo/src/main/resources/META-INF/services/{com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator => com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator} (100%) rename engine/src/main/java/com/didiglobal/turbo/engine/spi/{calulator => calculator}/ExpressionCalculator.java (93%) rename engine/src/main/java/com/didiglobal/turbo/engine/spi/{calulator => calculator}/ExpressionCalculatorFactory.java (97%) rename engine/src/main/java/com/didiglobal/turbo/engine/spi/{calulator => calculator}/GroovyExpressionCalculator.java (97%) create mode 100644 engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator delete mode 100644 engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator rename engine/src/test/java/com/didiglobal/turbo/engine/spi/{calulator => calculator}/ExpressionCalculatorFactoryTest.java (95%) rename engine/src/test/java/com/didiglobal/turbo/engine/spi/{calulator => calculator}/GroovyExpressionCalculatorTest.java (97%) rename engine/src/test/java/com/didiglobal/turbo/engine/spi/{calulator => calculator}/PatternExpressionCalculator.java (92%) rename engine/src/test/java/com/didiglobal/turbo/engine/spi/{calulator => calculator}/TestExpressionCalculator.java (86%) create mode 100644 engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator delete mode 100644 engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java index 1db64da1..9eca54ac 100644 --- a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java +++ b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java @@ -1,8 +1,8 @@ package com.didiglobal.turbo.demo.spi; import com.didiglobal.turbo.engine.exception.ProcessException; -import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator; -import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculatorFactory; +import com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculatorFactory; import com.google.common.collect.Maps; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator similarity index 100% rename from demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator rename to demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java index 710b4a79..9a75c929 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java @@ -12,7 +12,7 @@ import com.didiglobal.turbo.engine.exception.SuspendException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.model.InstanceData; -import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculatorFactory; +import com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculatorFactory; import com.didiglobal.turbo.engine.util.FlowModelUtil; import com.didiglobal.turbo.engine.util.InstanceDataUtil; import org.apache.commons.lang3.StringUtils; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java similarity index 93% rename from engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java index 14b9e7fa..eb54922e 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java @@ -1,4 +1,4 @@ -package com.didiglobal.turbo.engine.spi.calulator; +package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.exception.ProcessException; import com.didiglobal.turbo.engine.spi.SingletonSPI; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java similarity index 97% rename from engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java index b071aa1a..9eb86c5f 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java @@ -1,4 +1,4 @@ -package com.didiglobal.turbo.engine.spi.calulator; +package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.TurboException; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculator.java similarity index 97% rename from engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculator.java index 3fa4f38c..07b8abd9 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculator.java @@ -1,4 +1,4 @@ -package com.didiglobal.turbo.engine.spi.calulator; +package com.didiglobal.turbo.engine.spi.calculator; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; diff --git a/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator new file mode 100644 index 00000000..b62c1691 --- /dev/null +++ b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator @@ -0,0 +1 @@ +com.didiglobal.turbo.engine.spi.calculator.GroovyExpressionCalculator \ No newline at end of file diff --git a/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator deleted file mode 100644 index 50bd6f00..00000000 --- a/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator +++ /dev/null @@ -1 +0,0 @@ -com.didiglobal.turbo.engine.spi.calulator.GroovyExpressionCalculator \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java index 2b74bca3..f1ccbed3 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java @@ -1,6 +1,6 @@ package com.didiglobal.turbo.engine.spi; -import com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator; import com.didiglobal.turbo.engine.spi.generator.IdGenerator; import org.junit.Assert; import org.junit.Test; diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactoryTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java similarity index 95% rename from engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactoryTest.java rename to engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java index 0d278af4..39a009bd 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/ExpressionCalculatorFactoryTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java @@ -1,4 +1,4 @@ -package com.didiglobal.turbo.engine.spi.calulator; +package com.didiglobal.turbo.engine.spi.calculator; import org.junit.Assert; import org.junit.Test; diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculatorTest.java similarity index 97% rename from engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculatorTest.java rename to engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculatorTest.java index aa7a1fe9..2aa82e76 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/GroovyExpressionCalculatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculatorTest.java @@ -1,4 +1,4 @@ -package com.didiglobal.turbo.engine.spi.calulator; +package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.exception.ProcessException; import com.google.common.collect.Maps; diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/PatternExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java similarity index 92% rename from engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/PatternExpressionCalculator.java rename to engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java index 40721c60..f558c99e 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/PatternExpressionCalculator.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java @@ -1,4 +1,4 @@ -package com.didiglobal.turbo.engine.spi.calulator; +package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.exception.ProcessException; diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java similarity index 86% rename from engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java rename to engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java index e8d323d0..beb2f6be 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calulator/TestExpressionCalculator.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java @@ -1,12 +1,10 @@ -package com.didiglobal.turbo.engine.spi.calulator; +package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.exception.ProcessException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * test calculator diff --git a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator new file mode 100644 index 00000000..97cc0fe6 --- /dev/null +++ b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator @@ -0,0 +1,2 @@ +com.didiglobal.turbo.engine.spi.calculator.TestExpressionCalculator +com.didiglobal.turbo.engine.spi.calculator.PatternExpressionCalculator diff --git a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator deleted file mode 100644 index 39c60bbe..00000000 --- a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calulator.ExpressionCalculator +++ /dev/null @@ -1,2 +0,0 @@ -com.didiglobal.turbo.engine.spi.calulator.TestExpressionCalculator -com.didiglobal.turbo.engine.spi.calulator.PatternExpressionCalculator From 2b190dab3d9db6899326fc91d8d1105e8a4e7ef7 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Mon, 5 Jun 2023 18:22:54 +0800 Subject: [PATCH 20/24] Support for setting default expression evaluators --- .../turbo/demo/DemoApplication.java | 2 -- .../ExpressionCalculatorFactory.java | 24 ++++++++++++++++++- .../ExpressionCalculatorFactoryTest.java | 24 +++++++++++++++++-- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/DemoApplication.java b/demo/src/main/java/com/didiglobal/turbo/demo/DemoApplication.java index a929cc66..5c84f18b 100644 --- a/demo/src/main/java/com/didiglobal/turbo/demo/DemoApplication.java +++ b/demo/src/main/java/com/didiglobal/turbo/demo/DemoApplication.java @@ -2,8 +2,6 @@ import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.didiglobal.turbo.engine.annotation.EnableTurboEngine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java index 9eb86c5f..0f0129bf 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java @@ -15,13 +15,15 @@ public class ExpressionCalculatorFactory { /** * default expression calculator */ - private static final ExpressionCalculator DEFAULT_EXPRESSION_CALCULATOR; + private static ExpressionCalculator DEFAULT_EXPRESSION_CALCULATOR; /** * all calculators */ private static final Map CALCULATORS = new LinkedHashMap<>(); + private static boolean reset = false; + static { Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); serviceInterfaces.forEach(service -> CALCULATORS.put(service.getType(), service)); @@ -34,6 +36,26 @@ public class ExpressionCalculatorFactory { } } + /** + * Reset default expression calculator, only supports once. + * + * @param type type of calculator + * @return ExpressionCalculator + */ + public static void resetDefaultExpressionCalculator(String type) { + if (reset && !StringUtils.equals(type, DEFAULT_EXPRESSION_CALCULATOR.getType())) { + throw new TurboException(ErrorEnum.FAILED.getErrNo(), "the default expression calculator has already been reset"); + } + + if (StringUtils.isBlank(type) || !CALCULATORS.containsKey(type)) { + throw new TurboException(ErrorEnum.NOT_FOUND_EXPRESSION_CALCULATOR, + String.format("Not found expression calculator for %s", type)); + } + + DEFAULT_EXPRESSION_CALCULATOR = CALCULATORS.get(type); + reset = true; + } + /** * Get the calculator by type *

diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java index 39a009bd..280ff320 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java @@ -19,15 +19,35 @@ public void assertNotExists() { } @Test - public void assertExpressionCalculatorExistsWithNoType(){ + public void assertExpressionCalculatorExistsWithNoType() { ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); Assert.assertNotNull(defaultExpressionCalculator); } @Test - public void assertDefaultExpressionCalculatorNotGroovy(){ + public void assertDefaultExpressionCalculatorNotGroovy() { ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); Assert.assertFalse(defaultExpressionCalculator instanceof GroovyExpressionCalculator); } + @Test + public void assertDefaultExpressionCalculatorResetToGroovy() { + ExpressionCalculatorFactory.resetDefaultExpressionCalculator("groovy"); + ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); + Assert.assertTrue(defaultExpressionCalculator instanceof GroovyExpressionCalculator); + } + + @Test + public void assertDefaultExpressionCalculatorResetFail() { + try { + ExpressionCalculatorFactory.resetDefaultExpressionCalculator("groovy"); + // reset fail + ExpressionCalculatorFactory.resetDefaultExpressionCalculator("test"); + } catch (Exception e) { + // noting + } + ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); + Assert.assertTrue(defaultExpressionCalculator instanceof GroovyExpressionCalculator); + + } } From 18d440283529a09452b8b45b4c5696f7cc231a2e Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 27 Jun 2023 19:52:59 +0800 Subject: [PATCH 21/24] update default spi --- .../didiglobal/turbo/engine/spi/SPIOrder.java | 21 +++++++++++++ .../turbo/engine/spi/SingletonSPI.java | 17 ---------- .../turbo/engine/spi/TurboServiceLoader.java | 30 ++++++++---------- .../spi/calculator/ExpressionCalculator.java | 2 -- .../ExpressionCalculatorFactory.java | 31 +------------------ .../spi/generator/IdGenerateFactory.java | 16 +--------- .../engine/spi/generator/IdGenerator.java | 3 -- .../spi/generator/StrongUuidGenerator.java | 3 +- .../ExpressionCalculatorFactoryTest.java | 17 ++-------- .../PatternExpressionCalculator.java | 1 + .../calculator/TestExpressionCalculator.java | 2 ++ ...engine.spi.calculator.ExpressionCalculator | 2 +- 12 files changed, 44 insertions(+), 101 deletions(-) create mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/SPIOrder.java delete mode 100644 engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/SPIOrder.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SPIOrder.java new file mode 100644 index 00000000..f4382d9a --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SPIOrder.java @@ -0,0 +1,21 @@ +package com.didiglobal.turbo.engine.spi; + +import java.lang.annotation.*; + +/** + * Used to specify SPI order. + * @author lijinghao + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface SPIOrder { + + /** + * The smallest order will be used as the default implementation, + * and if the orders are the same, + * the outermost loaded one will be used as the default implementation + * + * @return order value + */ + int value() default Integer.MAX_VALUE; +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java deleted file mode 100644 index bc7697f0..00000000 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/SingletonSPI.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.didiglobal.turbo.engine.spi; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -/** - * @author lijinghao - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface SingletonSPI { - - -} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java index 0908e5e5..8c2c37bf 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java @@ -2,12 +2,8 @@ import com.google.common.base.Preconditions; import lombok.Getter; -import lombok.SneakyThrows; -import java.util.Collection; -import java.util.LinkedList; -import java.util.Map; -import java.util.ServiceLoader; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** @@ -53,22 +49,22 @@ public static Collection getServiceInterfaces(final Class serviceInter } private Collection getServiceInterfaces() { - return serviceInterface.getAnnotation(SingletonSPI.class) == null ? createNewServiceInstances() - : getSingletonServiceInstances(); - } - - private Collection getSingletonServiceInstances() { return services; } - @SneakyThrows(ReflectiveOperationException.class) - @SuppressWarnings("unchecked") - private Collection createNewServiceInstances() { - Collection result = new LinkedList<>(); - for (Object each : services) { - result.add((T) each.getClass().getDeclaredConstructor().newInstance()); + public static T getDefaultService(Class tClass) { + Collection serviceInterfaces = getServiceInterfaces(tClass); + if (serviceInterfaces.size() == 0) { + throw new RuntimeException("spi load exception: not found Implementation class of interface " + tClass.getName()); + } else if (serviceInterfaces.size() == 1) { + return serviceInterfaces.stream().findFirst().get(); + } else { + // Find the implementation to be used + Optional optionalIdGenerator = serviceInterfaces.stream() + .filter(s -> null != s.getClass().getAnnotation(SPIOrder.class)) + .min(Comparator.comparingInt(o -> o.getClass().getAnnotation(SPIOrder.class).value())); + return optionalIdGenerator.orElseGet(() -> serviceInterfaces.stream().findFirst().get()); } - return result; } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java index eb54922e..2fafe477 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java @@ -1,14 +1,12 @@ package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.exception.ProcessException; -import com.didiglobal.turbo.engine.spi.SingletonSPI; import java.util.Map; /** * turbo outgoing condition calculator */ -@SingletonSPI public interface ExpressionCalculator { /** diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java index 0f0129bf..64acbe6a 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java @@ -15,45 +15,16 @@ public class ExpressionCalculatorFactory { /** * default expression calculator */ - private static ExpressionCalculator DEFAULT_EXPRESSION_CALCULATOR; + private static final ExpressionCalculator DEFAULT_EXPRESSION_CALCULATOR = TurboServiceLoader.getDefaultService(ExpressionCalculator.class); /** * all calculators */ private static final Map CALCULATORS = new LinkedHashMap<>(); - private static boolean reset = false; - static { Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); serviceInterfaces.forEach(service -> CALCULATORS.put(service.getType(), service)); - // In the order in which the services are loaded, take the first implementation as default - Optional optional = serviceInterfaces.stream().findFirst(); - if (optional.isPresent()) { - DEFAULT_EXPRESSION_CALCULATOR = optional.get(); - } else { - throw new RuntimeException("spi load exception: not found Implementation class of interface ExpressionCalculator"); - } - } - - /** - * Reset default expression calculator, only supports once. - * - * @param type type of calculator - * @return ExpressionCalculator - */ - public static void resetDefaultExpressionCalculator(String type) { - if (reset && !StringUtils.equals(type, DEFAULT_EXPRESSION_CALCULATOR.getType())) { - throw new TurboException(ErrorEnum.FAILED.getErrNo(), "the default expression calculator has already been reset"); - } - - if (StringUtils.isBlank(type) || !CALCULATORS.containsKey(type)) { - throw new TurboException(ErrorEnum.NOT_FOUND_EXPRESSION_CALCULATOR, - String.format("Not found expression calculator for %s", type)); - } - - DEFAULT_EXPRESSION_CALCULATOR = CALCULATORS.get(type); - reset = true; } /** diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java index d4507736..d38bdb18 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java @@ -2,9 +2,6 @@ import com.didiglobal.turbo.engine.spi.TurboServiceLoader; -import java.util.Collection; -import java.util.Optional; - /** * id generate factory * @@ -15,18 +12,7 @@ public class IdGenerateFactory { /** * id generator */ - private static final IdGenerator ID_GENERATOR; - - static { - Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(IdGenerator.class); - // In the order in which the services are loaded, take the first implementation - Optional optional = serviceInterfaces.stream().findFirst(); - if (optional.isPresent()) { - ID_GENERATOR = optional.get(); - } else { - throw new RuntimeException("spi load exception: not found Implementation class of interface IdGenerator"); - } - } + private static final IdGenerator ID_GENERATOR = TurboServiceLoader.getDefaultService(IdGenerator.class); public static IdGenerator getIdGenerator() { return ID_GENERATOR; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java index ce172acd..da248d48 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java @@ -1,11 +1,8 @@ package com.didiglobal.turbo.engine.spi.generator; -import com.didiglobal.turbo.engine.spi.SingletonSPI; - /** * turbo id generator */ -@SingletonSPI public interface IdGenerator { /** diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java index bc5ca4aa..b6519b17 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.spi.generator; +import com.didiglobal.turbo.engine.spi.SPIOrder; import com.fasterxml.uuid.EthernetAddress; import com.fasterxml.uuid.Generators; import com.fasterxml.uuid.impl.TimeBasedGenerator; @@ -7,6 +8,7 @@ /** * Implementation of UUID generator that uses time/location based generation method */ +@SPIOrder public final class StrongUuidGenerator implements IdGenerator { private static volatile TimeBasedGenerator timeBasedGenerator; @@ -29,5 +31,4 @@ private void initGenerator() { public String getNextId() { return timeBasedGenerator.generate().toString(); } - } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java index 280ff320..40ae5e84 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java @@ -31,23 +31,10 @@ public void assertDefaultExpressionCalculatorNotGroovy() { } @Test - public void assertDefaultExpressionCalculatorResetToGroovy() { - ExpressionCalculatorFactory.resetDefaultExpressionCalculator("groovy"); + public void assertDefaultExpressionCalculatorIsTest() { ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); - Assert.assertTrue(defaultExpressionCalculator instanceof GroovyExpressionCalculator); + Assert.assertTrue(defaultExpressionCalculator instanceof TestExpressionCalculator); } - @Test - public void assertDefaultExpressionCalculatorResetFail() { - try { - ExpressionCalculatorFactory.resetDefaultExpressionCalculator("groovy"); - // reset fail - ExpressionCalculatorFactory.resetDefaultExpressionCalculator("test"); - } catch (Exception e) { - // noting - } - ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); - Assert.assertTrue(defaultExpressionCalculator instanceof GroovyExpressionCalculator); - } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java index f558c99e..bbd3ab02 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java @@ -1,6 +1,7 @@ package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.exception.ProcessException; +import com.didiglobal.turbo.engine.spi.SPIOrder; import java.util.Map; import java.util.regex.Matcher; diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java index beb2f6be..3f6edba5 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java @@ -1,6 +1,7 @@ package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.exception.ProcessException; +import com.didiglobal.turbo.engine.spi.SPIOrder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,6 +10,7 @@ /** * test calculator */ +@SPIOrder(0) public class TestExpressionCalculator implements ExpressionCalculator { private static final Logger LOGGER = LoggerFactory.getLogger(TestExpressionCalculator.class); diff --git a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator index 97cc0fe6..ef39e164 100644 --- a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator +++ b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator @@ -1,2 +1,2 @@ -com.didiglobal.turbo.engine.spi.calculator.TestExpressionCalculator com.didiglobal.turbo.engine.spi.calculator.PatternExpressionCalculator +com.didiglobal.turbo.engine.spi.calculator.TestExpressionCalculator From dba66d191e986781a21b1d18752b49b09255a7af Mon Sep 17 00:00:00 2001 From: lijinghao Date: Tue, 27 Jun 2023 20:22:35 +0800 Subject: [PATCH 22/24] update verion --- demo/pom.xml | 6 +++--- engine/pom.xml | 4 ++-- pom.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/demo/pom.xml b/demo/pom.xml index ca043846..80d8d404 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -6,13 +6,13 @@ com.didiglobal.turbo turbo - 1.1.1-SNAPSHOT + 1.1.2-SNAPSHOT 4.0.0 demo - 1.1.1-SNAPSHOT + 1.1.2-SNAPSHOT jar @@ -20,7 +20,7 @@ 1.8 1.5.10.RELEASE - 1.1.1-SNAPSHOT + 1.1.2-SNAPSHOT diff --git a/engine/pom.xml b/engine/pom.xml index eaacc83e..b038625f 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -5,13 +5,13 @@ 4.0.0 engine - 1.1.1-SNAPSHOT + 1.1.2-SNAPSHOT jar turbo com.didiglobal.turbo - 1.1.1-SNAPSHOT + 1.1.2-SNAPSHOT 2.3.7 diff --git a/pom.xml b/pom.xml index a7c5884c..ef7360e3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.didiglobal.turbo turbo pom - 1.1.1-SNAPSHOT + 1.1.2-SNAPSHOT turbo Turbo is a light-weight flow engine framework, support BPMN2.0 https://www.github.com/didi/turbo From e1e7a6852c2546432c2478c553a7c3c8a050d290 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Wed, 28 Jun 2023 11:34:54 +0800 Subject: [PATCH 23/24] Adjusting the factory to lazy loading mode --- .../spi/calculator/ExpressionCalculator.java | 4 +-- .../ExpressionCalculatorFactory.java | 33 +++++++++++++++---- .../spi/generator/IdGenerateFactory.java | 15 +++++++-- .../ExpressionCalculatorFactoryTest.java | 3 -- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java index 2fafe477..2d0d6563 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java @@ -10,9 +10,9 @@ public interface ExpressionCalculator { /** - * 获取表达式计算器类型 + * Get expression calculator Type * - * @return + * @return expression calculator Type */ String getType(); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java index 64acbe6a..5dbb20ab 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java @@ -5,7 +5,9 @@ import com.didiglobal.turbo.engine.spi.TurboServiceLoader; import org.apache.commons.lang3.StringUtils; -import java.util.*; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; /** * expression calculator factory @@ -15,18 +17,32 @@ public class ExpressionCalculatorFactory { /** * default expression calculator */ - private static final ExpressionCalculator DEFAULT_EXPRESSION_CALCULATOR = TurboServiceLoader.getDefaultService(ExpressionCalculator.class); + private volatile static ExpressionCalculator DEFAULT_EXPRESSION_CALCULATOR; /** * all calculators */ private static final Map CALCULATORS = new LinkedHashMap<>(); - static { + public static void load() { Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); serviceInterfaces.forEach(service -> CALCULATORS.put(service.getType(), service)); } + public static void loadDefault() { + if (DEFAULT_EXPRESSION_CALCULATOR == null) { + synchronized (ExpressionCalculatorFactory.class) { + if (DEFAULT_EXPRESSION_CALCULATOR == null) { + DEFAULT_EXPRESSION_CALCULATOR = TurboServiceLoader.getDefaultService(ExpressionCalculator.class); + } + } + } + } + + public static boolean contains(String type) { + return CALCULATORS.containsKey(type); + } + /** * Get the calculator by type *

@@ -37,16 +53,19 @@ public class ExpressionCalculatorFactory { */ public static ExpressionCalculator getExpressionCalculator(String type) { if (StringUtils.isBlank(type)) { + loadDefault(); return DEFAULT_EXPRESSION_CALCULATOR; } - if (!CALCULATORS.containsKey(type)) { + + if (CALCULATORS.isEmpty()) { + load(); + } + + if (!contains(type)) { throw new TurboException(ErrorEnum.NOT_FOUND_EXPRESSION_CALCULATOR, String.format("Not found expression calculator for %s", type)); } return CALCULATORS.get(type); } - public static boolean contains(String type) { - return CALCULATORS.containsKey(type); - } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java index d38bdb18..d95014dd 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java @@ -4,17 +4,26 @@ /** * id generate factory - * - * @author lijinghao */ public class IdGenerateFactory { /** * id generator */ - private static final IdGenerator ID_GENERATOR = TurboServiceLoader.getDefaultService(IdGenerator.class); + private volatile static IdGenerator ID_GENERATOR; public static IdGenerator getIdGenerator() { + loadDefault(); return ID_GENERATOR; } + + private static void loadDefault() { + if (ID_GENERATOR == null) { + synchronized (IdGenerateFactory.class) { + if (ID_GENERATOR == null) { + ID_GENERATOR = TurboServiceLoader.getDefaultService(IdGenerator.class); + } + } + } + } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java index 40ae5e84..0e42135d 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java @@ -12,7 +12,6 @@ public void assertGroovyExpressionCalculatorExists() { Assert.assertTrue(ExpressionCalculatorFactory.contains("test")); } - @Test public void assertNotExists() { Assert.assertFalse(ExpressionCalculatorFactory.contains("Tn3UI7")); @@ -35,6 +34,4 @@ public void assertDefaultExpressionCalculatorIsTest() { ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); Assert.assertTrue(defaultExpressionCalculator instanceof TestExpressionCalculator); } - - } From be146e47688f53dce1dbcd996e0bdff209f415b8 Mon Sep 17 00:00:00 2001 From: lijinghao Date: Wed, 28 Jun 2023 14:40:03 +0800 Subject: [PATCH 24/24] doc: add spi user guide --- docs/UserGuide.md | 118 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index fda59c5f..b83b807c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -20,7 +20,7 @@ Turbo是Didi公司开发的轻量级的Java实现的流程引擎 流程定义的内容,可以完整描述一个流程的定义,由FlowElement列表的json组成。下面是一个Demo的例子: -``` +```json { "flowElementList": [ { @@ -101,7 +101,7 @@ Turbo是Didi公司开发的轻量级的Java实现的流程引擎 **构造** -``` +```java StartEvent startEvent = new StartEvent(); // 设置唯一键 startEvent.setKey("StartEvent_1r83q1z"); @@ -128,7 +128,7 @@ startEvent.setOutgoing(outgoings); **构造** -``` +```java EndEvent endEvent = new EndEvent(); // 设置唯一键 endEvent.setKey("EndEvent_0z30kyv"); @@ -163,7 +163,7 @@ endEvent.setIncoming(incomings); **构造** -``` +```java ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); // 设置唯一键 exclusiveGateway.setKey("ExclusiveGateway_0yq2l0s"); @@ -224,7 +224,7 @@ exclusiveGateway.setProperties(properties); **构造** -``` +```java UserTask userTask = new UserTask(); // 设置唯一键 userTask.setKey("UserTask_1eglyg7"); @@ -267,7 +267,7 @@ userTask.setOutgoing(utOutgoings); **构造** -``` +```java CallActivity callActivity = new CallActivity(); // 设置唯一键 callActivity.setKey("CallActivity_0ofi5hg"); @@ -327,7 +327,7 @@ callActivity.setProperties(caProperties); **构造** -``` +```java SequenceFlow sequenceFlow1 = new SequenceFlow(); // 设置唯一键 sequenceFlow1.setKey("SequenceFlow_1lc9xoo"); @@ -369,3 +369,107 @@ sequenceFlow1.setProperties(properties); **约束规则** 顺序流只能有一个入口和一个出口。 + + +# 三、SPI扩展使用手册 + +## 1. Turbo SPI 概述 + +### 扩展性设计理念 +可扩展性是任何一个系统所追求的,对于 Turbo 来说同样使用。 + +#### 什么是可扩展性 +可扩展性是一个重要的设计理念,旨在确保在现有的架构或设计基础之上,当未来因某些方面发生变化时,我们能够以更小的改动来实现系统的增强或变更,同时尽量避免对现有代码的修改。 + +#### 可扩展性的优点 +可扩展性的优点主要表现在模块化设计以及模块之间的松耦合关系,它符合开闭原则,对扩展开放,对修改关闭。即可以在不修改现有代码的情况下,通过添加新的实现来扩展系统功能。 + +#### 扩展实现方式 +一般来说,系统会采用 Factory、IoC、OSGI 等方式管理扩展(插件)生命周期。考虑到后期 Turbo 会剥离Spring,不想强依赖 Spring 等 IoC 容器。所以选择最简单的 Factory 方式管理扩展(插件)。在 Turbo 中,所有内部实现和第三方实现都是平等的。 + +#### Turbo中的可扩展性 +- 平等对待第三方实现,在 Turbo 中,所有内部实现和第三方实现都是平等的,用户可以基于自身业务需求,替换 Turbo 中提供的原生实现。 +- 每个扩展点都只都相对独立,可最大化复用。用户如有扩展需求,只需要对关注的扩展点进行扩展就好,降低了扩展难度。 + +### Turbo 扩展特性 +在 Turbo 中,我们使用的是JDK标准的SPI扩展点发现机制,降低用户扩展难度;目前我们提供了针对 ID生成器 和 表达式计算器 的扩展点,后续将增加更多的可扩展点,以满足广大用户需求。 + +#### Turbo 扩展加载逻辑 +Turbo的加载逻辑相对比较简单,采用了懒加载的形式,在使用时会通过ServiceLoader加载并实例化对应实现,并进行缓存。加载过程可能会损耗一些性能,因此确认不使用的实现可以不进行配置。 + +#### Turbo 中 SPI默认实现说明 +Turbo 支持多种实现并存,但在使用时可能只使用其中一个,因此使用哪一个需要确定。一般情况下,是根据SPI的配置加载顺序来决定的,但某些情况下可能存在顺序的不确定性。在 Turbo 中我们提供了 @SPIOrder 注解,使用其value最小的作为默认实现。只有当存在多个对应注解且value值相同时,会按照加载顺序,使用列表中的第一个。 + + +## 2. Turbo扩展使用说明 + +### ID生成器扩展说明 +ID生成器基于 `IdGenerator` 接口实现,接口中仅存在一个方法,即 `genNextId()`;Turbo提供了默认实现`StrongUuidGenerator`,如果使用方想用其他形式ID生成方式,只需要在自己的项目目录下,实现 `IdGenerator` 接口,并按照SPI配置方式进行配置即可;另外,如果存在多个实现,仅会有一个实现是有效的(参考: Turbo 中 SPI默认实现说明)。 + +代码示例: +```java +package com.didiglobal.turbo.demo.spi; + +import com.didiglobal.turbo.engine.spi.generator.IdGenerator; +import org.apache.commons.lang3.RandomStringUtils; + +public class TestIdGenerator implements IdGenerator { + @Override + public String getNextId() { + // Expand your ID generator + return RandomStringUtils.randomAlphabetic(20); + } +} +``` + +配置示例: +```text +├── src +│ ├── main +│ │ ├── java +│ │ │ └── com +│ │ │ └── didiglobal +│ │ │ └── turbo +│ │ │ └── demo +│ │ │ ├── spi +│ │ │ │ └── TestIdGenerator.java +│ │ └── resources +│ │ ├── META-INF +│ │ │ └── services +│ │ │ └── com.didiglobal.turbo.engine.spi.generator.IdGenerator + + +# 文件内容: +com.didiglobal.turbo.demo.spi.TestIdGenerator +``` + +### 表达式计算器扩展说明 +在流程执行过程中,遇到存在多个出口时,会根据出口顺序流上的表达式来进行判断,最终走向哪一个分支。 +Turbo 中默认支持了 `Groovy` 语言的表达式计算器,同时支持用户自行扩展。进行扩展时, 只需要实现 `ExpressionCalculator` 接口,并根据上下文数据返回对应的结果。如果需要在流程图中支持多种表达式计算器,除了需要给出对应的实现外,仍需要在对应的顺序流的属性信息中添加 `conditiontypesequenceflow` 属性,来确定使用哪种类型的表达式计算器。如果不添加该属性,则使用默认的实现。 + +model 示例: +```json +{ + "flowElementList":[ + ... + + { + "incoming":[ + "UserTask_0cx5f72" + ], + "outgoing":[ + "UserTask_15qhuilv" + ], + "type":1, + "properties":{ + "conditionsequenceflow":"${type==1}", + "conditiontypesequenceflow":"groovy" + }, + "key":"SequenceFlow_0ebra7c" + } + + ... + ] +} +``` +说明: 如果仅使用单一的表达式计算器(配置默认实现),则 `conditiontypesequenceflow` 可以省略。