前言
参考了flowable获取流程节点顺序,预测审批路径文章,加入了相容网关的内容,网关层级的用户节点列表,以及比较参数那一段的小问题。借鉴前人的轮子。
直接上代码
@Override
public AjaxResult getUserTask(String procDefId, Map<String, Object> variables) {
/**
* 首先拿到BpmnModel,所有流程定义信息都可以通过BpmnModel获取;若流程尚未发起,则用modelId查询最新部署的流程定义数据;
* 若流程已经发起,可以通过流程实例的processDefinitionId查询流程定义的历史数据。
* @param variableMap 流程变量,用于计算条件分支
*/
BpmnModel bpmnModel = repositoryService.getBpmnModel(procDefId);
// Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
List<FlowElement> flowElements = new ArrayList<>(bpmnModel.getMainProcess().getFlowElements());
List<FlowElement> passElements = new ArrayList<>();
List<List<FlowElement>> passElementList = new ArrayList<>();
Optional<FlowElement> startElementOpt = flowElements.stream().filter(flowElement -> flowElement instanceof StartEvent).findFirst();
startElementOpt.ifPresent(startElement -> {
flowElements.remove(startElement);
List<SequenceFlow> outgoingFlows = ((StartEvent) startElement).getOutgoingFlows();
String targetRef = outgoingFlows.get(0).getTargetRef();
// 根据ID找到FlowElement
FlowElement targetElementOfStartElement = getFlowElement(flowElements, targetRef);
if (targetElementOfStartElement instanceof UserTask) {
getPassElementList(passElementList,passElements, flowElements, targetElementOfStartElement, variables);
}
});
ArrayList resultList = new ArrayList<String>();
for (List<FlowElement> elementList:passElementList) {
ArrayList lists = new ArrayList<String>();
for (FlowElement passElement:elementList) {
String taskName = passElement.getName();
lists.add(taskName);
}
resultList.add(lists);
}
return AjaxResult.success("", resultList);
}
private FlowElement getFlowElement(Collection<FlowElement> flowElements, String targetRef) {
return flowElements.stream().filter(flowElement -> targetRef.equals(flowElement.getId())).findFirst().orElse(null);
}
/**
* 3. 我只用到了UserTask、ExclusiveGateway、ParallelGateway,所以代码里只列举了这三种,如果用到了其他的,可以再自己补充
*/
private void getPassElementList(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
// 任务节点
if (curFlowElement instanceof UserTask) {
this.dueUserTaskElement(passElementList,passElements, flowElements, curFlowElement, variableMap);
return;
}
// 排他网关
if (curFlowElement instanceof ExclusiveGateway) {
this.dueExclusiveGateway(passElementList,passElements, flowElements, curFlowElement, variableMap);
return;
}
// 并行网关
if(curFlowElement instanceof ParallelGateway){
this.dueParallelGateway(passElementList,passElements, flowElements, curFlowElement, variableMap);
}
// 相容网关
if(curFlowElement instanceof InclusiveGateway){
this.dueInclusiveGateway(passElementList,passElements, flowElements, curFlowElement, variableMap);
}
}
private void dueUserTaskElement(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
passElements.add(curFlowElement);
List<SequenceFlow> outgoingFlows = ((UserTask) curFlowElement).getOutgoingFlows();
String targetRef = outgoingFlows.get(0).getTargetRef();
if (outgoingFlows.size() > 1) {
// 找到表达式成立的sequenceFlow
List<SequenceFlow> sequenceFlow = getSequenceFlow(variableMap, outgoingFlows);
targetRef = sequenceFlow.get(0).getTargetRef();
}
// 根据ID找到FlowElement
FlowElement targetElement = getFlowElement(flowElements, targetRef);
this.getPassElementList(passElementList,passElements, flowElements, targetElement, variableMap);
}
private void dueExclusiveGateway(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
// 获取符合条件的sequenceFlow的目标FlowElement
List<SequenceFlow> exclusiveGatewayOutgoingFlows = ((ExclusiveGateway) curFlowElement).getOutgoingFlows();
flowElements.remove(curFlowElement);
// 找到表达式成立的sequenceFlow
List<SequenceFlow> sequenceFlow = getSequenceFlow(variableMap, exclusiveGatewayOutgoingFlows);
// 根据ID找到FlowElement
for (SequenceFlow seqFlow:sequenceFlow
) {
FlowElement targetElement = getFlowElement(flowElements, seqFlow.getTargetRef());
this.getPassElementList(passElementList,passElements, flowElements, targetElement, variableMap);
}
}
private void dueParallelGateway(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
FlowElement targetElement;
List<SequenceFlow> parallelGatewayOutgoingFlows = ((ParallelGateway) curFlowElement).getOutgoingFlows();
for(SequenceFlow sequenceFlow : parallelGatewayOutgoingFlows){
targetElement = getFlowElement(flowElements, sequenceFlow.getTargetRef());
this.getPassElementList(passElementList,passElements, flowElements, targetElement, variableMap);
}
}
private void dueInclusiveGateway(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
// 获取符合条件的sequenceFlow的目标FlowElement
List<SequenceFlow> inclusiveGatewayOutgoingFlows = ((InclusiveGateway) curFlowElement).getOutgoingFlows();
flowElements.remove(curFlowElement);
// 找到表达式成立的sequenceFlow
List<SequenceFlow> sequenceFlow = getSequenceFlow(variableMap, inclusiveGatewayOutgoingFlows);
passElementList.add(passElements);
passElements = new ArrayList<FlowElement>();
// 根据ID找到FlowElement
for (SequenceFlow seqFlow:sequenceFlow
) {
FlowElement targetElement = getFlowElement(flowElements, seqFlow.getTargetRef());
this.getPassElementList(passElementList,passElements, flowElements, targetElement, variableMap);
}
}
/**
* 4. 根据传入的变量,计算出表达式成立的那一条SequenceFlow
* @param variableMap
* @param outgoingFlows
* @return
*/
private List<SequenceFlow> getSequenceFlow(Map<String, Object> variableMap, List<SequenceFlow> outgoingFlows) {
List<SequenceFlow> sequenceFlowOpt = outgoingFlows.stream().filter(item -> {
try {
return this.getElValue(item.getConditionExpression(), variableMap);
} catch (Exception e) {
log.error(e.getMessage(), e);
return false;
}
}).collect(Collectors.toList());;
if(sequenceFlowOpt.size()==0){
outgoingFlows.get(0);
}
return sequenceFlowOpt;
}
private boolean getElValue(String exp, Map<String, Object> variableMap){
return managementService.executeCommand(new ExpressionCmd(runtimeService, processEngineConfiguration, null, exp, variableMap));
}
import org.apache.commons.lang3.StringUtils;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.impl.el.VariableContainerWrapper;
import org.flowable.common.engine.impl.interceptor.Command;
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;
public class ExpressionCmd implements Command<Boolean>, Serializable {
protected RuntimeService runtimeService;
protected ProcessEngineConfigurationImpl processEngineConfiguration;
protected String processInstanceId;
protected String exp;
protected Map<String, Object> variableMap;
public ExpressionCmd(RuntimeService runtimeService, ProcessEngineConfigurationImpl processEngineConfiguration, String processInstanceId, String exp, Map<String, Object> variableMap) {
this.runtimeService = runtimeService;
this.processEngineConfiguration = processEngineConfiguration;
this.processInstanceId = processInstanceId;
this.exp = exp;
this.variableMap = variableMap;
}
@Override
public Boolean execute(CommandContext commandContext) {
if(this.exp==null){
return false;
}
Expression expression = processEngineConfiguration.getExpressionManager().createExpression(this.exp);
Object value;
if(StringUtils.isNotBlank(this.processInstanceId)){
ExecutionEntity executionEntity = (ExecutionEntity) runtimeService.createProcessInstanceQuery().processInstanceId(this.processInstanceId).includeProcessVariables().singleResult();
value = expression.getValue(executionEntity);
}else {
VariableContainerWrapper variableContainerWrapper = new VariableContainerWrapper(variableMap);
value = expression.getValue(variableContainerWrapper);
}
return value != null && "true".equals(value.toString());
}
}
备注
适配的参数结构variables
{“type”:“4”
}