diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/common/enums/BpmErrorCode.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/common/enums/BpmErrorCode.java index bd87fe714..2fe6cb7de 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/common/enums/BpmErrorCode.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/common/enums/BpmErrorCode.java @@ -55,6 +55,7 @@ public enum BpmErrorCode implements IProjectRespCode { FORM_DEFINITION_PARSER_ERROR("08002", "表单定义内容解析出错"), // ========== form Instance 09-001 ========== // ========== flowable Engine 10-001 ========== + ENGINE_EXECUTION_LOST_ID_ERROR("10001", "Execution 丢失"), // // ========== 流程模型 01-001 ========== diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java index 00063ce97..3fbc0d665 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessInstanceServiceImpl.java @@ -205,7 +205,7 @@ public class BpmnProcessInstanceServiceImpl implements BpmnProcessInstanceServic return true; } log.error("[updateProcessDefinitionState][流程定义({}) 修改未知状态({})]", processDefinitionId, status); - return null; + return false; } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/ExpressionConditionCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/ExpressionConditionCmd.java index f5a8f1260..fd9a40cb0 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/ExpressionConditionCmd.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/ExpressionConditionCmd.java @@ -1,5 +1,6 @@ package cn.axzo.workflow.core.service.support; +import cn.axzo.workflow.core.common.exception.WorkflowEngineException; import cn.azxo.framework.common.utils.StringUtils; import org.flowable.common.engine.api.delegate.Expression; import org.flowable.common.engine.impl.interceptor.Command; @@ -7,10 +8,10 @@ import org.flowable.common.engine.impl.interceptor.CommandContext; import org.flowable.engine.RuntimeService; import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.flowable.engine.impl.persistence.entity.ExecutionEntity; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl; import java.io.Serializable; -import java.util.Map; + +import static cn.axzo.workflow.core.common.enums.BpmErrorCode.ENGINE_EXECUTION_LOST_ID_ERROR; /** * 流程定义内部的表达式评估命令器 @@ -24,17 +25,13 @@ public class ExpressionConditionCmd implements Command, Serializable { protected final String processInstanceId; protected final String exp; - protected Map variableMap; - public ExpressionConditionCmd(RuntimeService runtimeService, ProcessEngineConfigurationImpl processEngineConfiguration, - String processInstanceId, String exp, - Map variableMap) { + String processInstanceId, String exp) { this.runtimeService = runtimeService; this.processEngineConfiguration = processEngineConfiguration; this.processInstanceId = processInstanceId; this.exp = exp; - this.variableMap = variableMap; } @Override @@ -42,11 +39,12 @@ public class ExpressionConditionCmd implements Command, Serializable { Expression expression = processEngineConfiguration.getExpressionManager().createExpression(this.exp); ExecutionEntity executionEntity; if (StringUtils.isNotBlank(this.processInstanceId)) { - executionEntity = - (ExecutionEntity) runtimeService.createProcessInstanceQuery().processInstanceId(this.processInstanceId).includeProcessVariables().singleResult(); + executionEntity = (ExecutionEntity) runtimeService.createProcessInstanceQuery() + .processInstanceId(this.processInstanceId).includeProcessVariables().singleResult(); } else { - executionEntity = new ExecutionEntityImpl(); - executionEntity.setVariables(variableMap); + // 不能单纯的 new ExecutionEntityImpl, 后续在调用 setVariables 时, + // 引擎用了很多 ExecutionEntityImpl 的其他属性,这些属性都是在 new 不会自动生成的 + throw new WorkflowEngineException(ENGINE_EXECUTION_LOST_ID_ERROR); } Object value = expression.getValue(executionEntity); return value != null && "true".equals(value.toString()); diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/FlowNodeForecastService.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/FlowNodeForecastService.java index 87128c6c6..181dae15f 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/FlowNodeForecastService.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/FlowNodeForecastService.java @@ -1,15 +1,19 @@ package cn.axzo.workflow.core.service.support; +import cn.axzo.workflow.core.common.exception.WorkflowEngineException; import cn.axzo.workflow.core.service.support.forecast.AbstractForecast; import cn.axzo.workflow.core.service.support.forecast.Forecast; import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.StartEvent; import org.flowable.engine.RepositoryService; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.runtime.ProcessInstance; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.ResolvableType; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.util.ArrayList; @@ -20,11 +24,13 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import static cn.axzo.workflow.core.common.enums.BpmErrorCode.PROCESS_INSTANCE_NOT_EXISTS; + /** * 审批实例的运行节点预测/推断 *

* 一个流程定义中所有的节点都是 FlowElement 类型,而 FlowElement 是引擎中的一个基类, 如果要完整推测审批流程执行顺序不亚于重写一套流程执行引擎 - * 所以这里仅按照业务所需的节点类型进行处理. + * 所以这里仅按照业务所需的节点类型进行处理.并且每个节点都未处理出口是多个的情况,目前仅支持单出口! *

* 全量的接入类型如下: *

@@ -84,25 +90,33 @@ import java.util.Optional;
 @Service
 public class FlowNodeForecastService implements InitializingBean {
 
-    public final static Map FORECAST_MAP = new HashMap<>();
+    public final static Map, AbstractForecast> FORECAST_MAP = new HashMap<>();
     @Resource
     private RepositoryService repositoryService;
     @Resource
-    private List forecasts;
+    private RuntimeService runtimeService;
+    @Resource
+    private List> forecasts;
 
     /**
-     * 执行流程预测
+     * 执行运行中的流程预测
      * 

- * 某个实例的 bpmnModel 可以通过该方式得到: - *

-     * HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
-     * BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
-     * 
+ * 已完成的流程可以直接查询流程审批记录就行 * - * @param bpmnModel 指定流程定义配置元数据 - * @param variableMap 指定流程实例的全量变量表 + * @param processInstanceId 指定运行时的流程实例 ID */ - public List performProcessForecasting(BpmnModel bpmnModel, Map variableMap) { + public List performProcessForecasting(String processInstanceId) { + if (!StringUtils.hasLength(processInstanceId)) { + throw new WorkflowEngineException(PROCESS_INSTANCE_NOT_EXISTS); + } + + ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId) + .includeProcessVariables().singleResult(); + if (Objects.isNull(instance)) { + throw new WorkflowEngineException(PROCESS_INSTANCE_NOT_EXISTS); + } + BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId()); + // 保持推测出来的节点执行顺序的容器 List orderNodes = new ArrayList<>(); // 流程定义中所有的FlowElement @@ -113,17 +127,17 @@ public class FlowNodeForecastService implements InitializingBean { addOrderFlowNodes(orderNodes, startNode); }); - startForecasting(orderNodes, variableMap); + startForecasting(orderNodes, instance); return orderNodes; } - private void startForecasting(List orderNodes, Map variableMap) { + private void startForecasting(List orderNodes, ProcessInstance instance) { getLastNode(orderNodes).ifPresent(flowElement -> forecasts.forEach(i -> { if (i.support(flowElement)) { - List list = i.nextFlowElement(flowElement, variableMap); + List list = i.nextFlowElement(flowElement, instance); if (!CollectionUtils.isEmpty(list)) { addOrderFlowNodes(orderNodes, list.get(0)); - startForecasting(orderNodes, variableMap); + startForecasting(orderNodes, instance); } } })); @@ -162,7 +176,7 @@ public class FlowNodeForecastService implements InitializingBean { forecasts.forEach(i -> { Class rawClass = ResolvableType.forClass(i.getClass(), Forecast.class) .getSuperType().getGenerics()[0].getRawClass(); - FORECAST_MAP.put(rawClass, (AbstractForecast) i); + FORECAST_MAP.put(rawClass, (AbstractForecast) i); }); } } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/AbstractForecast.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/AbstractForecast.java index db7930ad9..182fe2c76 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/AbstractForecast.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/AbstractForecast.java @@ -1,6 +1,9 @@ package cn.axzo.workflow.core.service.support.forecast; +import cn.axzo.workflow.core.service.support.forecast.impl.SequenceFlowForecasting; +import cn.axzo.workflow.core.service.support.spring.FlowableConditionEvaluatorAware; import org.flowable.bpmn.model.FlowElement; +import org.flowable.engine.runtime.ProcessInstance; import org.springframework.util.CollectionUtils; import java.util.ArrayList; @@ -13,7 +16,7 @@ import java.util.stream.Collectors; import static cn.axzo.workflow.core.service.support.FlowNodeForecastService.FORECAST_MAP; /** - * TODO + * 抽象的流程预测 * * @author wangli * @since 2023/10/10 10:55 @@ -22,48 +25,33 @@ public abstract class AbstractForecast implements Forecas private FlowableConditionEvaluator conditionEvaluator; - /** - * 将节点来源强制转换成目标节点类型 - * - * @param sourceFlowElements - * @return - */ - private List cast(List sourceFlowElements) { - if (CollectionUtils.isEmpty(sourceFlowElements)) { - return Collections.emptyList(); - } - List convertList = new ArrayList<>(sourceFlowElements.size()); - sourceFlowElements.forEach(i -> convertList.add((T) i)); - return convertList; - } - @Override - public final List nextFlowElement(FlowElement sourceFlowElement, Map variableMap) { - return forecastNextNodes(getOutgoing((T) sourceFlowElement), variableMap); + public final List nextFlowElement(FlowElement sourceFlowElement, ProcessInstance instance) { + return forecastNextNodes(getOutgoing((T) sourceFlowElement), instance); } protected abstract List getOutgoing(T flowElement); /** - * 计算出口节点,此时的入参 sourceFlowElement 已经不等会泛型类 + * 计算出口节点,此时的入参 sourceFlowElement 已经不等于泛型类 * * @param sourceFlowElements 当前节点的出口节点集合 - * @param variableMap 流程实例变量 + * @param instance 流程实例 * @return */ - protected final List forecastNextNodes(List sourceFlowElements, Map variableMap) { + private List forecastNextNodes(List sourceFlowElements, + ProcessInstance instance) { if (CollectionUtils.isEmpty(sourceFlowElements)) { return Collections.emptyList(); } - Map, ? extends List> elementGroup = + Map, List> elementGroup = sourceFlowElements.stream().collect(Collectors.groupingBy(FlowElement::getClass, Collectors.toList())); - List result = new ArrayList(); + List result = new ArrayList<>(); elementGroup.forEach((k, v) -> { AbstractForecast forecast = FORECAST_MAP.get(k); if (Objects.nonNull(forecast)) { - result.addAll(forecast.calcRealOutgoingNodes(v, variableMap)); + result.addAll(forecast.calcRealOutgoingNodes(v, instance)); } }); return result; @@ -73,10 +61,10 @@ public abstract class AbstractForecast implements Forecas * 由于每个节点的下级节点是多个,且有可能是不同类型, 在预测下级节点时,需要将同类型的节点传递给对应类型的预测器来计算 * * @param flowElements - * @param variableMap + * @param instance * @return */ - public List calcRealOutgoingNodes(List flowElements, Map variableMap) { + public List calcRealOutgoingNodes(List flowElements, ProcessInstance instance) { return Collections.emptyList(); } @@ -85,7 +73,15 @@ public abstract class AbstractForecast implements Forecas this.conditionEvaluator = conditionEvaluator; } - protected final Boolean conditionOn(String exp, Map variableMap) { - return conditionEvaluator.conditionOn(exp, variableMap); + /** + * 提供给所有实现类的通用调用引擎评估节点可能存在的条件表达式 + * + * @param exp 表达式 + * @param processInstanceId 实例 ID + * @return + * @see SequenceFlowForecasting#calcRealOutgoingNodes(List, ProcessInstance) 参考这里的用法 + */ + protected final Boolean conditionOn(String exp, String processInstanceId) { + return conditionEvaluator.conditionOn(exp, processInstanceId); } } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/FlowableConditionEvaluator.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/FlowableConditionEvaluator.java index b24efe1af..0c2e0e640 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/FlowableConditionEvaluator.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/FlowableConditionEvaluator.java @@ -7,8 +7,6 @@ import org.flowable.engine.RuntimeService; import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.springframework.stereotype.Component; -import java.util.Map; - /** * 基于 Flowable 引擎能力的表达式评估器 * @@ -26,13 +24,14 @@ public class FlowableConditionEvaluator { /** * 计算表达式真假, 需结合引擎能力 * - * @param exp 条件表达式 - * @param variables 流程变量 + * @param exp 条件表达式 + * @param variables 流程变量 + * @param processInstanceId 流程实例 ID (可与 variables 参入二选一, 如果都传,则直接用实例 ID 去引擎中查真实的变量表) * @return true Or false */ - public Boolean conditionOn(String exp, Map variables) { + public Boolean conditionOn(String exp, String processInstanceId) { return managementService.executeCommand(new ExpressionConditionCmd(runtimeService, - processEngineConfiguration, null, exp, variables)); + processEngineConfiguration, processInstanceId, exp)); } } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/Forecast.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/Forecast.java index 9cb588a09..8aa20d3db 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/Forecast.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/Forecast.java @@ -1,9 +1,9 @@ package cn.axzo.workflow.core.service.support.forecast; import org.flowable.bpmn.model.FlowElement; +import org.flowable.engine.runtime.ProcessInstance; import java.util.List; -import java.util.Map; /** * 流程节点顺序预测接口 @@ -19,7 +19,7 @@ public interface Forecast { * @param t Flowable 的子类 * @return */ - Boolean support(FlowElement t); + Boolean support(FlowElement flowElement); /** * 通过给定的源 FlowElement 结合 Flowable 的条件评估器去计算符合条件的下一级节点 @@ -27,9 +27,9 @@ public interface Forecast { * 由于标准的 BPMN 协议中很多节点都是允许多条路并行走的, 所以接口返回模型定义为 List 集合, * 但实际上, 按照现在的业务定义, 只允许存在 0 或 1 个下一级节点. * - * @param sourceFlowElement 上级节点 - * @param variableMap 流程运行实例的完全变量 + * @param sourceFlowElement 当前节点, 实现类中该方法则是通过 getOutgoing 获取出口节点集合, 并调用对应类型中的 calcRealOutgoingNodes 查找真正的下级节点 + * @param instance 流程运行实例 * @return */ - List nextFlowElement(FlowElement sourceFlowElement, Map variableMap); + List nextFlowElement(FlowElement sourceFlowElement, ProcessInstance instance); } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/EndEventForecasting.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/EndEventForecasting.java index f298c62c0..7578ad42f 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/EndEventForecasting.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/EndEventForecasting.java @@ -3,15 +3,15 @@ package cn.axzo.workflow.core.service.support.forecast.impl; import cn.axzo.workflow.core.service.support.forecast.AbstractForecast; import org.flowable.bpmn.model.EndEvent; import org.flowable.bpmn.model.FlowElement; +import org.flowable.engine.runtime.ProcessInstance; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.Collections; import java.util.List; -import java.util.Map; /** - * TODO + * 结束节点 * * @author wangli * @since 2023/10/10 18:58 @@ -29,11 +29,10 @@ public class EndEventForecasting extends AbstractForecast { } @Override - public List calcRealOutgoingNodes(List flowElements, - Map variableMap) { + public List calcRealOutgoingNodes(List flowElements, ProcessInstance instance) { if (CollectionUtils.isEmpty(flowElements)) { return Collections.emptyList(); } - return super.calcRealOutgoingNodes(flowElements, variableMap); + return super.calcRealOutgoingNodes(flowElements, instance); } } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/ExclusiveGatewayForecasting.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/ExclusiveGatewayForecasting.java new file mode 100644 index 000000000..ae29b885d --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/ExclusiveGatewayForecasting.java @@ -0,0 +1,42 @@ +package cn.axzo.workflow.core.service.support.forecast.impl; + +import cn.axzo.workflow.core.service.support.forecast.AbstractForecast; +import org.flowable.bpmn.model.ExclusiveGateway; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.engine.runtime.ProcessInstance; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collections; +import java.util.List; + +/** + * 排他网关 + * + * @author wangli + * @since 2023/10/11 09:57 + */ +@Component +public class ExclusiveGatewayForecasting extends AbstractForecast { + @Override + public Boolean support(FlowElement flowElement) { + return flowElement instanceof ExclusiveGateway; + } + + @Override + protected List getOutgoing(ExclusiveGateway flowElement) { + return flowElement.getOutgoingFlows(); + } + + @Override + public List calcRealOutgoingNodes(List flowElements, + ProcessInstance instance) { + if (CollectionUtils.isEmpty(flowElements)) { + return Collections.emptyList(); + } + if (flowElements.size() == 1) { + return flowElements; + } + return super.calcRealOutgoingNodes(flowElements, instance); + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/SequenceFlowForecasting.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/SequenceFlowForecasting.java index 2756057d7..b48a026a6 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/SequenceFlowForecasting.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/SequenceFlowForecasting.java @@ -4,13 +4,13 @@ import cn.axzo.workflow.core.service.support.forecast.AbstractForecast; import com.google.common.collect.Lists; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.SequenceFlow; +import org.flowable.engine.runtime.ProcessInstance; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; /** @@ -34,7 +34,7 @@ public class SequenceFlowForecasting extends AbstractForecast { @Override public List calcRealOutgoingNodes(List flowElements, - Map variableMap) { + ProcessInstance instance) { if (CollectionUtils.isEmpty(flowElements)) { return Collections.emptyList(); } @@ -42,7 +42,7 @@ public class SequenceFlowForecasting extends AbstractForecast { // 评估顺序流集合中条件为 true 的顺序流 List executableFlows = flowElements.stream().filter(i -> StringUtils.hasLength(i.getConditionExpression())) - .filter(i -> conditionOn(i.getConditionExpression(), variableMap)).collect(Collectors.toList()); + .filter(i -> conditionOn(i.getConditionExpression(), instance.getId())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(executableFlows) && executableFlows.size() == 1) { return Lists.newArrayList(executableFlows.get(0)); } @@ -53,6 +53,6 @@ public class SequenceFlowForecasting extends AbstractForecast { if (!CollectionUtils.isEmpty(defaultFlows) && defaultFlows.size() == 1) { return Lists.newArrayList(defaultFlows.get(0)); } - return super.calcRealOutgoingNodes(flowElements, variableMap); + return super.calcRealOutgoingNodes(flowElements, instance); } } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/StartEventForecasting.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/StartEventForecasting.java index 58a996e29..c967a71e7 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/StartEventForecasting.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/StartEventForecasting.java @@ -26,5 +26,4 @@ public class StartEventForecasting extends AbstractForecast { return flowElement.getOutgoingFlows(); } - } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/UserTaskForecasting.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/UserTaskForecasting.java index 61bc31aaa..a4697838c 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/UserTaskForecasting.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/impl/UserTaskForecasting.java @@ -3,12 +3,12 @@ package cn.axzo.workflow.core.service.support.forecast.impl; import cn.axzo.workflow.core.service.support.forecast.AbstractForecast; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.UserTask; +import org.flowable.engine.runtime.ProcessInstance; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.Collections; import java.util.List; -import java.util.Map; /** * 用户任务节点预测 @@ -29,14 +29,13 @@ public class UserTaskForecasting extends AbstractForecast { } @Override - public List calcRealOutgoingNodes(List flowElements, - Map variableMap) { + public List calcRealOutgoingNodes(List flowElements, ProcessInstance instance) { if (CollectionUtils.isEmpty(flowElements)) { return Collections.emptyList(); } if (flowElements.size() == 1) { return flowElements; } - return super.calcRealOutgoingNodes(flowElements, variableMap); + return super.calcRealOutgoingNodes(flowElements, instance); } } diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/FlowableConditionEvaluatorAware.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/spring/FlowableConditionEvaluatorAware.java similarity index 73% rename from workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/FlowableConditionEvaluatorAware.java rename to workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/spring/FlowableConditionEvaluatorAware.java index af4e6e46c..4d6bcfc03 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/forecast/FlowableConditionEvaluatorAware.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/spring/FlowableConditionEvaluatorAware.java @@ -1,4 +1,6 @@ -package cn.axzo.workflow.core.service.support.forecast; +package cn.axzo.workflow.core.service.support.spring; + +import cn.axzo.workflow.core.service.support.forecast.FlowableConditionEvaluator; /** * 按照 Spring 规范提供一个 Flowable Condition Evaluator 的 Aware diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/spring/FlowableConditionEvaluatorAwareProcessor.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/spring/FlowableConditionEvaluatorAwareProcessor.java new file mode 100644 index 000000000..7f0fdcbd7 --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/support/spring/FlowableConditionEvaluatorAwareProcessor.java @@ -0,0 +1,28 @@ +package cn.axzo.workflow.core.service.support.spring; + +import cn.axzo.workflow.core.service.support.forecast.FlowableConditionEvaluator; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.stereotype.Component; + +/** + * 自定义的 Aware 模式的接口处理类 + * + * @author wangli + * @since 2023/10/11 10:23 + */ +@Component +public class FlowableConditionEvaluatorAwareProcessor implements BeanPostProcessor { + + private final FlowableConditionEvaluator conditionEvaluator; + + public FlowableConditionEvaluatorAwareProcessor(FlowableConditionEvaluator conditionEvaluator) {this.conditionEvaluator = conditionEvaluator;} + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof FlowableConditionEvaluatorAware) { + ((FlowableConditionEvaluatorAware) bean).setConditionEvaluator(conditionEvaluator); + } + return bean; + } +} diff --git a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/TestController.java b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/TestController.java index 039d20f05..83ae91001 100644 --- a/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/TestController.java +++ b/workflow-engine-server/src/main/java/cn/axzo/workflow/server/controller/web/TestController.java @@ -2,11 +2,9 @@ package cn.axzo.workflow.server.controller.web; import cn.axzo.workflow.core.service.support.FlowNodeForecastService; import lombok.extern.slf4j.Slf4j; -import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.FlowElement; import org.flowable.engine.HistoryService; import org.flowable.engine.RepositoryService; -import org.flowable.engine.history.HistoricProcessInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -37,11 +35,8 @@ public class TestController { @GetMapping("/test") public void test(@RequestParam String processInstanceId) { - HistoricProcessInstance instance = - historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); - BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId()); - List flowElements = forecastService.performProcessForecasting(bpmnModel, - instance.getProcessVariables()); + + List flowElements = forecastService.performProcessForecasting(processInstanceId); System.out.println("flowElements = " + flowElements); }