update - 流程整体推测,兼容运行时和历史两种状态

This commit is contained in:
wangli 2024-04-15 10:56:49 +08:00
parent cbc44cd354
commit 488cc2242a
5 changed files with 29 additions and 22 deletions

View File

@ -6,8 +6,10 @@ 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.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.ResolvableType;
@ -19,7 +21,6 @@ import javax.annotation.Nullable;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -97,6 +98,8 @@ public class FlowNodeForecastService implements InitializingBean {
@Resource
private RepositoryService repositoryService;
@Resource
private HistoryService historyService;
@Resource
private RuntimeService runtimeService;
@Resource
private List<Forecast<? extends FlowElement>> forecasts;
@ -112,17 +115,24 @@ public class FlowNodeForecastService implements InitializingBean {
public List<FlowElement> performProcessForecasting(@Nullable String processInstanceId,
@Nullable ProcessInstance instance) {
if (Objects.nonNull(instance)) {
// Do nothing
processInstanceId = instance.getProcessInstanceId();
} else if (!StringUtils.hasLength(processInstanceId)) {
throw new WorkflowEngineException(PROCESS_INSTANCE_NOT_EXISTS);
} else {
instance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId)
instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
// .includeProcessVariables()
.singleResult();
}
if (Objects.isNull(instance)) {
return Collections.emptyList();
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
processInstanceId = processInstance.getId();
} else {
processInstanceId = instance.getProcessInstanceId();
}
BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
// 保持推测出来的节点执行顺序的容器
@ -135,17 +145,17 @@ public class FlowNodeForecastService implements InitializingBean {
addOrderFlowNodes(orderedNodes, startNode);
});
startForecasting(orderedNodes, instance);
startForecasting(orderedNodes, processInstanceId);
return orderedNodes;
}
private void startForecasting(List<FlowElement> orderNodes, ProcessInstance instance) {
private void startForecasting(List<FlowElement> orderNodes, String processInstanceId) {
getLastNode(orderNodes).ifPresent(flowElement -> forecasts.forEach(i -> {
if (i.support(flowElement)) {
List<FlowElement> list = i.nextFlowElement(flowElement, instance);
List<FlowElement> list = i.nextFlowElement(flowElement, processInstanceId);
if (!CollectionUtils.isEmpty(list)) {
addOrderFlowNodes(orderNodes, list.get(0));
startForecasting(orderNodes, instance);
startForecasting(orderNodes, processInstanceId);
}
}
}));

View File

@ -29,8 +29,8 @@ public abstract class AbstractForecast<T extends FlowElement> implements Forecas
private static final Logger log = LoggerFactory.getLogger(AbstractForecast.class);
@Override
public final List<FlowElement> nextFlowElement(FlowElement sourceFlowElement, ProcessInstance instance) {
return forecastNextNodes(getOutgoing((T) sourceFlowElement), instance);
public final List<FlowElement> nextFlowElement(FlowElement sourceFlowElement, String processInstanceId) {
return forecastNextNodes(getOutgoing((T) sourceFlowElement), processInstanceId);
}
protected abstract List<? extends FlowElement> getOutgoing(T flowElement);
@ -43,7 +43,7 @@ public abstract class AbstractForecast<T extends FlowElement> implements Forecas
* @return
*/
private List<FlowElement> forecastNextNodes(List<? extends FlowElement> sourceFlowElements,
ProcessInstance instance) {
String processInstanceId) {
if (CollectionUtils.isEmpty(sourceFlowElements)) {
return Collections.emptyList();
}
@ -54,7 +54,7 @@ public abstract class AbstractForecast<T extends FlowElement> implements Forecas
elementGroup.forEach((k, v) -> {
AbstractForecast forecast = FORECAST_MAP.get(k);
if (Objects.nonNull(forecast)) {
result.addAll(forecast.calcRealOutgoingNodes(v, instance));
result.addAll(forecast.calcRealOutgoingNodes(v, processInstanceId));
}
});
return result;
@ -67,7 +67,7 @@ public abstract class AbstractForecast<T extends FlowElement> implements Forecas
* @param instance
* @return
*/
public List<? extends FlowElement> calcRealOutgoingNodes(List<T> flowElements, ProcessInstance instance) {
public List<? extends FlowElement> calcRealOutgoingNodes(List<T> flowElements, String processInstanceId) {
if (!CollectionUtils.isEmpty(flowElements) && flowElements.size() == 1) {
return flowElements;
}

View File

@ -1,7 +1,6 @@
package cn.axzo.workflow.core.service.support.forecast;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.runtime.ProcessInstance;
import java.util.List;
@ -31,5 +30,5 @@ public interface Forecast<T extends FlowElement> {
* @param instance 流程运行实例
* @return
*/
List<FlowElement> nextFlowElement(FlowElement sourceFlowElement, ProcessInstance instance);
List<FlowElement> nextFlowElement(FlowElement sourceFlowElement, String processInstanceId);
}

View File

@ -3,7 +3,6 @@ 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;
@ -29,10 +28,10 @@ public class EndEventForecasting extends AbstractForecast<EndEvent> {
}
@Override
public List<? extends FlowElement> calcRealOutgoingNodes(List<EndEvent> flowElements, ProcessInstance instance) {
public List<? extends FlowElement> calcRealOutgoingNodes(List<EndEvent> flowElements, String processInstanceId) {
if (CollectionUtils.isEmpty(flowElements)) {
return Collections.emptyList();
}
return super.calcRealOutgoingNodes(flowElements, instance);
return super.calcRealOutgoingNodes(flowElements, processInstanceId);
}
}

View File

@ -4,7 +4,6 @@ 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;
@ -35,7 +34,7 @@ public class SequenceFlowForecasting extends AbstractForecast<SequenceFlow> {
@Override
public List<? extends FlowElement> calcRealOutgoingNodes(List<SequenceFlow> flowElements,
ProcessInstance instance) {
String processInstanceId) {
if (CollectionUtils.isEmpty(flowElements)) {
return Collections.emptyList();
}
@ -43,7 +42,7 @@ public class SequenceFlowForecasting extends AbstractForecast<SequenceFlow> {
// 评估顺序流集合中条件为 true 的顺序流
List<SequenceFlow> executableFlows =
flowElements.stream().filter(i -> StringUtils.hasLength(i.getConditionExpression()))
.filter(i -> conditionOn(i.getConditionExpression(), instance.getId())).collect(Collectors.toList());
.filter(i -> conditionOn(i.getConditionExpression(), processInstanceId)).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(executableFlows) && executableFlows.size() == 1) {
return Lists.newArrayList(executableFlows.get(0));
}
@ -54,6 +53,6 @@ public class SequenceFlowForecasting extends AbstractForecast<SequenceFlow> {
if (!CollectionUtils.isEmpty(defaultFlows) && defaultFlows.size() == 1) {
return Lists.newArrayList(defaultFlows.get(0));
}
return super.calcRealOutgoingNodes(flowElements, instance);
return super.calcRealOutgoingNodes(flowElements, processInstanceId);
}
}