工作流引擎Activiti连线工具类

Posted by Clear Blog on December 23, 2017

最近工作中有用到工作流引擎Activiti, 因为需求方会配置很多种复杂的工作量,以及流程之间流转的触发条件也错综复杂, 用简单的可视化页面来拖拽生成工作流显然不可取,于是需要用代码来生成activiti所需要的图, 结合自己所需要的业务数据来进行存储。 我写了个工具类,在此做记录,后面方便重复使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import java.util.List;
import java.util.Map;

import org.activiti.bpmn.model.Process;
import org.springframework.util.CollectionUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.pingan.process.common.domain.ActivitiNodeBaseEntity;
import com.pingan.process.common.share.ActivitiConstants;
import com.pingan.process.common.share.CurrentRunTypeEnum;

/**
 * 创建工作流。画线模板方法
 *
 * @author xuguangwu
 */
public class ProcessTemplateUtil<T extends ActivitiNodeBaseEntity> {

	public void createSequenceBetweenNodes(List<T> activitiNodes, Process process, String prefix) {
		Map<Integer, List<ActivitiNodeBaseEntity>> shuffleResultMap = shuffleNodes(activitiNodes);
		shuffleResultMap.forEach((partIndex, partList) -> {
			if (partList.size() > 1) {// 并行环节列表
				process.addFlowElement(ActivitiUtils.createParallelGateway(ActivitiConstants.PARALLEL_GATEWAY + partIndex));
				process.addFlowElement(ActivitiUtils.createParallelGateway(ActivitiConstants.PARALLEL_GATEWAY + (partIndex + 1)));// 创建并行网关

				List<ActivitiNodeBaseEntity> preNodeList = shuffleResultMap.get(partIndex - 1);// 获取上一个集合
				List<ActivitiNodeBaseEntity> nextNodeList = shuffleResultMap.get(partIndex + 1);// 获取下一个集合
				if (CollectionUtils.isEmpty(preNodeList)) {
					if (partIndex == 0) {
						process.addFlowElement(ActivitiUtils.createSequenceFlow(ActivitiConstants.ACTIVITI_START_EVENT, ActivitiConstants.PARALLEL_GATEWAY + partIndex, ""));// 第一环节与下一环节并行
					}
				}
				if (CollectionUtils.isEmpty(nextNodeList)) {
					process.addFlowElement(ActivitiUtils.createSequenceFlow(ActivitiConstants.PARALLEL_GATEWAY + (partIndex + 1), // 并行事件直接到结束事件
							ActivitiConstants.ACTIVITI_END_EVENT, ""));
				}
				partList.forEach(tempChainNodeDO -> {
					process.addFlowElement(ActivitiUtils.createSequenceFlow(ActivitiConstants.PARALLEL_GATEWAY + partIndex, prefix + tempChainNodeDO.getId(), ""));
				});
				partList.forEach(tempChainNodeDO -> {
					process.addFlowElement(ActivitiUtils.createSequenceFlow(prefix + tempChainNodeDO.getId(), ActivitiConstants.PARALLEL_GATEWAY + (partIndex + 1), ""));
				});
			} else {// 串行
				partList.forEach(tempActivitiNodeDO -> {
					List<ActivitiNodeBaseEntity> preNodeList = shuffleResultMap.get(partIndex - 1);// 获取上一个集合
					List<ActivitiNodeBaseEntity> nextNodeList = shuffleResultMap.get(partIndex + 1);// 获取下一个集合
					if (CollectionUtils.isEmpty(preNodeList)) {
						process.addFlowElement(ActivitiUtils.createSequenceFlow(ActivitiConstants.ACTIVITI_START_EVENT, prefix + tempActivitiNodeDO.getId(), ""));// 第一环节与下一环节为串行
					} else if (preNodeList.size() == 1) {
						process.addFlowElement(ActivitiUtils.createSequenceFlow(prefix + preNodeList.get(0).getId(), prefix + tempActivitiNodeDO.getId(), ""));
					} else {
						process.addFlowElement(ActivitiUtils.createSequenceFlow(ActivitiConstants.PARALLEL_GATEWAY + partIndex, prefix + tempActivitiNodeDO.getId(), ""));
					}

					if (CollectionUtils.isEmpty(nextNodeList)) {
						process.addFlowElement(ActivitiUtils.createSequenceFlow(prefix + tempActivitiNodeDO.getId(), ActivitiConstants.ACTIVITI_END_EVENT, ""));// 第一环节与下一环节为串行
					} else if (nextNodeList.size() > 1) {
						process.addFlowElement(ActivitiUtils.createSequenceFlow(prefix + tempActivitiNodeDO.getId(), ActivitiConstants.PARALLEL_GATEWAY + (partIndex + 1), ""));
					}
				});
			}
		});
	}

	/**
	 * 梳理节点列表 将并发节点整合到一个list中,串行节点一个节点对应一个list。 map的key对应着顺序
	 * 
	 * @param activitiNodes
	 * @return
	 */
	private Map<Integer, List<ActivitiNodeBaseEntity>> shuffleNodes(List<T> activitiNodes) {
		int partIndex = 0;
		boolean parallelLoop = false;
		List<ActivitiNodeBaseEntity> tempChainNodes = Lists.newArrayList();
		Map<Integer, List<ActivitiNodeBaseEntity>> chainNodeMap = Maps.newHashMap();
		boolean parentParallelFlag = false;// 上个环节到当前环节是否为并行
		for (int m = 0; m < activitiNodes.size(); m++) {
			if (!parallelLoop) {
				tempChainNodes = Lists.newArrayList();
			}
			ActivitiNodeBaseEntity activitiNodeDO = activitiNodes.get(m);
			Integer relation = activitiNodeDO.getCurrentRunType();// com.pingan.pufpms.process.common.share.CurrentRunTypeEnum
			if ((relation == null && parentParallelFlag == true)) {
				tempChainNodes.add(activitiNodeDO);
				parallelLoop = true;
			} else if (relation != null && ((!parentParallelFlag && relation == CurrentRunTypeEnum.PARALLEL.getType()) || (parentParallelFlag && relation == CurrentRunTypeEnum.PARALLEL.getType())
					|| parentParallelFlag && relation == CurrentRunTypeEnum.SERIAL.getType())) {// 并发环节
				tempChainNodes.add(activitiNodeDO);
				if(relation == CurrentRunTypeEnum.PARALLEL.getType()) {
					parallelLoop = true;
				}else if (relation == CurrentRunTypeEnum.SERIAL.getType()) {
					parallelLoop = false;
				}
				parentParallelFlag = true;
			} else {
				if (!CollectionUtils.isEmpty(tempChainNodes)) {
					chainNodeMap.put(partIndex++, tempChainNodes);
					tempChainNodes = Lists.newArrayList();
				}
				tempChainNodes.add(activitiNodeDO);
				parallelLoop = false;
			}
			if (!parallelLoop || ((m == activitiNodes.size() - 1) && parallelLoop)) {
				chainNodeMap.put(partIndex++, tempChainNodes);
			}
		}
		return chainNodeMap;
	}
}