最近工作中有用到工作流引擎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;
}
}