1 package com.famousPro.process.service.impl;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.activiti.engine.FormService;
9 import org.activiti.engine.HistoryService;
10 import org.activiti.engine.RepositoryService;
11 import org.activiti.engine.RuntimeService;
12 import org.activiti.engine.TaskService;
13 import org.activiti.engine.history.HistoricActivityInstance;
14 import org.activiti.engine.impl.RepositoryServiceImpl;
15 import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
16 import org.activiti.engine.impl.persistence.entity.TaskEntity;
17 import org.activiti.engine.impl.pvm.PvmTransition;
18 import org.activiti.engine.impl.pvm.process.ActivityImpl;
19 import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
20 import org.activiti.engine.impl.pvm.process.TransitionImpl;
21 import org.activiti.engine.runtime.ProcessInstance;
22 import org.activiti.engine.task.Task;
23
24 import com.famousPro.common.service.impl.BaseServiceImp;
25 import com.famousPro.common.util.IDGenerator;
26 import com.famousPro.common.util.StringUtil;
27 import com.famousPro.process.service.ProcessCoreService;
28 import com.famousPro.process.service.ProcessOtherService;
29
30 /**
31 * 流程操作核心类<br>
32 * 此核心类主要处理:流程通过、驳回、会签、转办、中止、挂起等核心操作<br>
33 *
34 * @author wangfuwei
35 *
36 */
37 public class ProcessCoreServiceImpl
extends BaseServiceImp
implements
38 ProcessCoreService {
39 protected RepositoryService repositoryService;
40
41 protected RuntimeService runtimeService;
42
43 protected TaskService taskService;
44
45 protected FormService formService;
46
47 protected HistoryService historyService;
48
49 protected ProcessOtherService processOtherService;
50
51 /**
52 * 根据当前任务ID,查询可以驳回的任务节点
53 *
54 * @param taskId
55 * 当前任务ID
56 */
57 public List<ActivityImpl> findBackAvtivity(String taskId)
throws Exception {
58 List<ActivityImpl> rtnList =
null;
59 if (processOtherService.isJointTask(taskId)) {
// 会签任务节点,不允许驳回
60 rtnList =
new ArrayList<ActivityImpl>
();
61 }
else {
62 rtnList =
iteratorBackActivity(taskId, findActivitiImpl(taskId,
63 null),
new ArrayList<ActivityImpl>
(),
64 new ArrayList<ActivityImpl>
());
65 }
66 return reverList(rtnList);
67 }
68
69 /**
70 * 审批通过(驳回直接跳回功能需后续扩展)
71 *
72 * @param taskId
73 * 当前任务ID
74 * @param variables
75 * 流程存储参数
76 * @throws Exception
77 */
78 public void passProcess(String taskId, Map<String, Object>
variables)
79 throws Exception {
80 List<Task> tasks =
taskService.createTaskQuery().parentTaskId(taskId)
81 .taskDescription("jointProcess"
).list();
82 for (Task task : tasks) {
// 级联结束本节点发起的会签任务
83 commitProcess(task.getId(),
null,
null);
84 }
85 commitProcess(taskId, variables,
null);
86 }
87
88 /**
89 * 驳回流程
90 *
91 * @param taskId
92 * 当前任务ID
93 * @param activityId
94 * 驳回节点ID
95 * @param variables
96 * 流程存储参数
97 * @throws Exception
98 */
99 public void backProcess(String taskId, String activityId,
100 Map<String, Object> variables)
throws Exception {
101 if (StringUtil.isNull(activityId)) {
102 throw new Exception("驳回目标节点ID为空!"
);
103 }
104
105 // 查询本节点发起的会签任务,并结束
106 List<Task> tasks =
taskService.createTaskQuery().parentTaskId(taskId)
107 .taskDescription("jointProcess"
).list();
108 for (Task task : tasks) {
109 commitProcess(task.getId(),
null,
null);
110 }
111
112 // 查找所有并行任务节点,同时驳回
113 List<Task> taskList =
findTaskListByKey(findProcessInstanceByTaskId(
114 taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
115 for (Task task : taskList) {
116 commitProcess(task.getId(), variables, activityId);
117 }
118 }
119
120 /**
121 * 取回流程
122 *
123 * @param taskId
124 * 当前任务ID
125 * @param activityId
126 * 取回节点ID
127 * @throws Exception
128 */
129 public void callBackProcess(String taskId, String activityId)
130 throws Exception {
131 if (StringUtil.isNull(activityId)) {
132 throw new Exception("目标节点ID为空!"
);
133 }
134
135 // 查找所有并行任务节点,同时取回
136 List<Task> taskList =
findTaskListByKey(findProcessInstanceByTaskId(
137 taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
138 for (Task task : taskList) {
139 commitProcess(task.getId(),
null, activityId);
140 }
141 }
142
143 /**
144 * 中止流程(特权人直接审批通过等)
145 *
146 * @param taskId
147 */
148 public void endProcess(String taskId)
throws Exception {
149 ActivityImpl endActivity = findActivitiImpl(taskId, "end"
);
150 commitProcess(taskId,
null, endActivity.getId());
151 }
152
153 /**
154 * 会签操作
155 *
156 * @param taskId
157 * 当前任务ID
158 * @param userCodes
159 * 会签人账号集合
160 * @throws Exception
161 */
162 public void jointProcess(String taskId, List<String>
userCodes)
163 throws Exception {
164 for (String userCode : userCodes) {
165 TaskEntity task =
(TaskEntity) taskService.newTask(IDGenerator
166 .generateID());
167 task.setAssignee(userCode);
168 task.setName(findTaskById(taskId).getName() + "-会签"
);
169 task.setProcessDefinitionId(findProcessDefinitionEntityByTaskId(
170 taskId).getId());
171 task.setProcessInstanceId(findProcessInstanceByTaskId(taskId)
172 .getId());
173 task.setParentTaskId(taskId);
174 task.setDescription("jointProcess"
);
175 taskService.saveTask(task);
176 }
177 }
178
179 /**
180 * 转办流程
181 *
182 * @param taskId
183 * 当前任务节点ID
184 * @param userCode
185 * 被转办人Code
186 */
187 public void transferAssignee(String taskId, String userCode) {
188 taskService.setAssignee(taskId, userCode);
189 }
190
191 /**
192 * ***************************************************************************************************************************************************<br>
193 * ************************************************以下为流程会签操作核心逻辑******************************************************************************<br>
194 * ***************************************************************************************************************************************************<br>
195 */
196
197 /**
198 * ***************************************************************************************************************************************************<br>
199 * ************************************************以上为流程会签操作核心逻辑******************************************************************************<br>
200 * ***************************************************************************************************************************************************<br>
201 */
202
203 /**
204 * ***************************************************************************************************************************************************<br>
205 * ************************************************以下为流程转向操作核心逻辑******************************************************************************<br>
206 * ***************************************************************************************************************************************************<br>
207 */
208
209 /**
210 * @param taskId
211 * 当前任务ID
212 * @param variables
213 * 流程变量
214 * @param activityId
215 * 流程转向执行任务节点ID<br>
216 * 此参数为空,默认为提交操作
217 * @throws Exception
218 */
219 private void commitProcess(String taskId, Map<String, Object>
variables,
220 String activityId)
throws Exception {
221 if (variables ==
null) {
222 variables =
new HashMap<String, Object>
();
223 }
224 // 跳转节点为空,默认提交操作
225 if (StringUtil.isNull(activityId)) {
226 taskService.complete(taskId, variables);
227 }
else {
// 流程转向操作
228 turnTransition(taskId, activityId, variables);
229 }
230 }
231
232 /**
233 * 清空指定活动节点流向
234 *
235 * @param activityImpl
236 * 活动节点
237 * @return 节点流向集合
238 */
239 private List<PvmTransition>
clearTransition(ActivityImpl activityImpl) {
240 // 存储当前节点所有流向临时变量
241 List<PvmTransition> oriPvmTransitionList =
new ArrayList<PvmTransition>
();
242 // 获取当前节点所有流向,存储到临时变量,然后清空
243 List<PvmTransition> pvmTransitionList =
activityImpl
244 .getOutgoingTransitions();
245 for (PvmTransition pvmTransition : pvmTransitionList) {
246 oriPvmTransitionList.add(pvmTransition);
247 }
248 pvmTransitionList.clear();
249
250 return oriPvmTransitionList;
251 }
252
253 /**
254 * 还原指定活动节点流向
255 *
256 * @param activityImpl
257 * 活动节点
258 * @param oriPvmTransitionList
259 * 原有节点流向集合
260 */
261 private void restoreTransition(ActivityImpl activityImpl,
262 List<PvmTransition>
oriPvmTransitionList) {
263 // 清空现有流向
264 List<PvmTransition> pvmTransitionList =
activityImpl
265 .getOutgoingTransitions();
266 pvmTransitionList.clear();
267 // 还原以前流向
268 for (PvmTransition pvmTransition : oriPvmTransitionList) {
269 pvmTransitionList.add(pvmTransition);
270 }
271 }
272
273 /**
274 * 流程转向操作
275 *
276 * @param taskId
277 * 当前任务ID
278 * @param activityId
279 * 目标节点任务ID
280 * @param variables
281 * 流程变量
282 * @throws Exception
283 */
284 private void turnTransition(String taskId, String activityId,
285 Map<String, Object> variables)
throws Exception {
286 // 当前节点
287 ActivityImpl currActivity = findActivitiImpl(taskId,
null);
288 // 清空当前流向
289 List<PvmTransition> oriPvmTransitionList =
clearTransition(currActivity);
290
291 // 创建新流向
292 TransitionImpl newTransition =
currActivity.createOutgoingTransition();
293 // 目标节点
294 ActivityImpl pointActivity =
findActivitiImpl(taskId, activityId);
295 // 设置新流向的目标节点
296 newTransition.setDestination(pointActivity);
297
298 // 执行转向任务
299 taskService.complete(taskId, variables);
300 // 删除目标节点新流入
301 pointActivity.getIncomingTransitions().remove(newTransition);
302
303 // 还原以前流向
304 restoreTransition(currActivity, oriPvmTransitionList);
305 }
306
307 /**
308 * ***************************************************************************************************************************************************<br>
309 * ************************************************以上为流程转向操作核心逻辑******************************************************************************<br>
310 * ***************************************************************************************************************************************************<br>
311 */
312
313 /**
314 * ***************************************************************************************************************************************************<br>
315 * ************************************************以下为查询流程驳回节点核心逻辑***************************************************************************<br>
316 * ***************************************************************************************************************************************************<br>
317 */
318
319 /**
320 * 迭代循环流程树结构,查询当前节点可驳回的任务节点
321 *
322 * @param taskId
323 * 当前任务ID
324 * @param currActivity
325 * 当前活动节点
326 * @param rtnList
327 * 存储回退节点集合
328 * @param tempList
329 * 临时存储节点集合(存储一次迭代过程中的同级userTask节点)
330 * @return 回退节点集合
331 */
332 private List<ActivityImpl>
iteratorBackActivity(String taskId,
333 ActivityImpl currActivity, List<ActivityImpl>
rtnList,
334 List<ActivityImpl> tempList)
throws Exception {
335 // 查询流程定义,生成流程树结构
336 ProcessInstance processInstance =
findProcessInstanceByTaskId(taskId);
337
338 // 当前节点的流入来源
339 List<PvmTransition> incomingTransitions =
currActivity
340 .getIncomingTransitions();
341 // 条件分支节点集合,userTask节点遍历完毕,迭代遍历此集合,查询条件分支对应的userTask节点
342 List<ActivityImpl> exclusiveGateways =
new ArrayList<ActivityImpl>
();
343 // 并行节点集合,userTask节点遍历完毕,迭代遍历此集合,查询并行节点对应的userTask节点
344 List<ActivityImpl> parallelGateways =
new ArrayList<ActivityImpl>
();
345 // 遍历当前节点所有流入路径
346 for (PvmTransition pvmTransition : incomingTransitions) {
347 TransitionImpl transitionImpl =
(TransitionImpl) pvmTransition;
348 ActivityImpl activityImpl =
transitionImpl.getSource();
349 String type = (String) activityImpl.getProperty("type"
);
350 /**
351 * 并行节点配置要求:<br>
352 * 必须成对出现,且要求分别配置节点ID为:XXX_start(开始),XXX_end(结束)
353 */
354 if ("parallelGateway".equals(type)) {
// 并行路线
355 String gatewayId =
activityImpl.getId();
356 String gatewayType =
gatewayId.substring(gatewayId
357 .lastIndexOf("_") + 1
);
358 if ("START".equals(gatewayType.toUpperCase())) {
// 并行起点,停止递归
359 return rtnList;
360 }
else {
// 并行终点,临时存储此节点,本次循环结束,迭代集合,查询对应的userTask节点
361 parallelGateways.add(activityImpl);
362 }
363 }
else if ("startEvent".equals(type)) {
// 开始节点,停止递归
364 return rtnList;
365 }
else if ("userTask".equals(type)) {
// 用户任务
366 tempList.add(activityImpl);
367 }
else if ("exclusiveGateway".equals(type)) {
// 分支路线,临时存储此节点,本次循环结束,迭代集合,查询对应的userTask节点
368 currActivity =
transitionImpl.getSource();
369 exclusiveGateways.add(currActivity);
370 }
371 }
372
373 /**
374 * 迭代条件分支集合,查询对应的userTask节点
375 */
376 for (ActivityImpl activityImpl : exclusiveGateways) {
377 iteratorBackActivity(taskId, activityImpl, rtnList, tempList);
378 }
379
380 /**
381 * 迭代并行集合,查询对应的userTask节点
382 */
383 for (ActivityImpl activityImpl : parallelGateways) {
384 iteratorBackActivity(taskId, activityImpl, rtnList, tempList);
385 }
386
387 /**
388 * 根据同级userTask集合,过滤最近发生的节点
389 */
390 currActivity =
filterNewestActivity(processInstance, tempList);
391 if (currActivity !=
null) {
392 // 查询当前节点的流向是否为并行终点,并获取并行起点ID
393 String id =
findParallelGatewayId(currActivity);
394 if (StringUtil.isNull(id)) {
// 并行起点ID为空,此节点流向不是并行终点,符合驳回条件,存储此节点
395 rtnList.add(currActivity);
396 }
else {
// 根据并行起点ID查询当前节点,然后迭代查询其对应的userTask任务节点
397 currActivity =
findActivitiImpl(taskId, id);
398 }
399
400 // 清空本次迭代临时集合
401 tempList.clear();
402 // 执行下次迭代
403 iteratorBackActivity(taskId, currActivity, rtnList, tempList);
404 }
405 return rtnList;
406 }
407
408 /**
409 * 反向排序list集合,便于驳回节点按顺序显示
410 *
411 * @param list
412 * @return
413 */
414 private List<ActivityImpl> reverList(List<ActivityImpl>
list) {
415 List<ActivityImpl> rtnList =
new ArrayList<ActivityImpl>
();
416 // 由于迭代出现重复数据,排除重复
417 for (
int i = list.size(); i > 0; i--
) {
418 if (!rtnList.contains(list.get(i - 1
)))
419 rtnList.add(list.get(i - 1
));
420 }
421 return rtnList;
422 }
423
424 /**
425 * 根据当前节点,查询输出流向是否为并行终点,如果为并行终点,则拼装对应的并行起点ID
426 *
427 * @param activityImpl
428 * 当前节点
429 * @return
430 */
431 private String findParallelGatewayId(ActivityImpl activityImpl) {
432 List<PvmTransition> incomingTransitions =
activityImpl
433 .getOutgoingTransitions();
434 for (PvmTransition pvmTransition : incomingTransitions) {
435 TransitionImpl transitionImpl =
(TransitionImpl) pvmTransition;
436 activityImpl =
transitionImpl.getDestination();
437 String type = (String) activityImpl.getProperty("type"
);
438 if ("parallelGateway".equals(type)) {
// 并行路线
439 String gatewayId =
activityImpl.getId();
440 String gatewayType =
gatewayId.substring(gatewayId
441 .lastIndexOf("_") + 1
);
442 if ("END"
.equals(gatewayType.toUpperCase())) {
443 return gatewayId.substring(0, gatewayId.lastIndexOf("_"
))
444 + "_start"
;
445 }
446 }
447 }
448 return null;
449 }
450
451 /**
452 * 根据流入任务集合,查询最近一次的流入任务节点
453 *
454 * @param processInstance
455 * 流程实例
456 * @param tempList
457 * 流入任务集合
458 * @return
459 */
460 private ActivityImpl filterNewestActivity(ProcessInstance processInstance,
461 List<ActivityImpl>
tempList) {
462 while (tempList.size() > 0
) {
463 ActivityImpl activity_1 = tempList.get(0
);
464 HistoricActivityInstance activityInstance_1 =
findHistoricUserTask(
465 processInstance, activity_1.getId());
466 if (activityInstance_1 ==
null) {
467 tempList.remove(activity_1);
468 continue;
469 }
470
471 if (tempList.size() > 1
) {
472 ActivityImpl activity_2 = tempList.get(1
);
473 HistoricActivityInstance activityInstance_2 =
findHistoricUserTask(
474 processInstance, activity_2.getId());
475 if (activityInstance_2 ==
null) {
476 tempList.remove(activity_2);
477 continue;
478 }
479
480 if (activityInstance_1.getEndTime().before(
481 activityInstance_2.getEndTime())) {
482 tempList.remove(activity_1);
483 }
else {
484 tempList.remove(activity_2);
485 }
486 }
else {
487 break;
488 }
489 }
490 if (tempList.size() > 0
) {
491 return tempList.get(0
);
492 }
493 return null;
494 }
495
496 /**
497 * 查询指定任务节点的最新记录
498 *
499 * @param processInstance
500 * 流程实例
501 * @param activityId
502 * @return
503 */
504 private HistoricActivityInstance findHistoricUserTask(
505 ProcessInstance processInstance, String activityId) {
506 HistoricActivityInstance rtnVal =
null;
507 // 查询当前流程实例审批结束的历史节点
508 List<HistoricActivityInstance> historicActivityInstances =
historyService
509 .createHistoricActivityInstanceQuery().activityType("userTask"
)
510 .processInstanceId(processInstance.getId()).activityId(
511 activityId).finished()
512 .orderByHistoricActivityInstanceEndTime().desc().list();
513 if (historicActivityInstances.size() > 0
) {
514 rtnVal = historicActivityInstances.get(0
);
515 }
516
517 return rtnVal;
518 }
519
520 /**
521 * *******************************************************************************************************<br>
522 * ********************************以上为查询流程驳回节点核心逻辑***********************************************<br>
523 * ********************************************************************************************************<br>
524 */
525
526 /**
527 * ********************************************************************************<br>
528 * **********************以下为activiti 核心service
529 * set方法***************************<br>
530 * *********************************************************************************<br>
531 */
532 public void setFormService(FormService formService) {
533 this.formService =
formService;
534 }
535
536 public void setHistoryService(HistoryService historyService) {
537 this.historyService =
historyService;
538 }
539
540 public void setRepositoryService(RepositoryService repositoryService) {
541 this.repositoryService =
repositoryService;
542 }
543
544 public void setRuntimeService(RuntimeService runtimeService) {
545 this.runtimeService =
runtimeService;
546 }
547
548 public void setTaskService(TaskService taskService) {
549 this.taskService =
taskService;
550 }
551
552 /**
553 * ********************************************************************************<br>
554 * **********************以上为activiti 核心service
555 * set方法***************************<br>
556 * *********************************************************************************<br>
557 */
558
559 /**
560 * ********************************************************************************<br>
561 * **********************以下为根据 任务节点ID 获取流程各对象查询方法**********************<br>
562 * *********************************************************************************<br>
563 */
564
565 public void setProcessOtherService(ProcessOtherService processOtherService) {
566 this.processOtherService =
processOtherService;
567 }
568
569 /**
570 * 根据任务ID获得任务实例
571 *
572 * @param taskId
573 * 任务ID
574 * @return
575 * @throws Exception
576 */
577 private TaskEntity findTaskById(String taskId)
throws Exception {
578 TaskEntity task =
(TaskEntity) taskService.createTaskQuery().taskId(
579 taskId).singleResult();
580 if (task ==
null) {
581 throw new Exception("任务实例未找到!"
);
582 }
583 return task;
584 }
585
586 /**
587 * 根据流程实例ID和任务key值查询所有同级任务集合
588 *
589 * @param processInstanceId
590 * @param key
591 * @return
592 */
593 private List<Task>
findTaskListByKey(String processInstanceId, String key) {
594 return taskService.createTaskQuery().processInstanceId(
595 processInstanceId).taskDefinitionKey(key).list();
596 }
597
598 /**
599 * 根据任务ID获取对应的流程实例
600 *
601 * @param taskId
602 * 任务ID
603 * @return
604 * @throws Exception
605 */
606 private ProcessInstance findProcessInstanceByTaskId(String taskId)
607 throws Exception {
608 // 找到流程实例
609 ProcessInstance processInstance =
runtimeService
610 .createProcessInstanceQuery().processInstanceId(
611 findTaskById(taskId).getProcessInstanceId())
612 .singleResult();
613 if (processInstance ==
null) {
614 throw new Exception("流程实例未找到!"
);
615 }
616 return processInstance;
617 }
618
619 /**
620 * 根据任务ID获取流程定义
621 *
622 * @param taskId
623 * 任务ID
624 * @return
625 * @throws Exception
626 */
627 private ProcessDefinitionEntity findProcessDefinitionEntityByTaskId(
628 String taskId)
throws Exception {
629 // 取得流程定义
630 ProcessDefinitionEntity processDefinition =
(ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
631 .getDeployedProcessDefinition(findTaskById(taskId)
632 .getProcessDefinitionId());
633
634 if (processDefinition ==
null) {
635 throw new Exception("流程定义未找到!"
);
636 }
637
638 return processDefinition;
639 }
640
641 /**
642 * 根据任务ID和节点ID获取活动节点 <br>
643 *
644 * @param taskId
645 * 任务ID
646 * @param activityId
647 * 活动节点ID <br>
648 * 如果为null或"",则默认查询当前活动节点 <br>
649 * 如果为"end",则查询结束节点 <br>
650 *
651 * @return
652 * @throws Exception
653 */
654 private ActivityImpl findActivitiImpl(String taskId, String activityId)
655 throws Exception {
656 // 取得流程定义
657 ProcessDefinitionEntity processDefinition =
findProcessDefinitionEntityByTaskId(taskId);
658
659 // 获取当前活动节点ID
660 if (StringUtil.isNull(activityId)) {
661 activityId =
findTaskById(taskId).getTaskDefinitionKey();
662 }
663
664 // 根据流程定义,获取该流程实例的结束节点
665 if (activityId.toUpperCase().equals("END"
)) {
666 for (ActivityImpl activityImpl : processDefinition.getActivities()) {
667 List<PvmTransition> pvmTransitionList =
activityImpl
668 .getOutgoingTransitions();
669 if (pvmTransitionList.isEmpty()) {
670 return activityImpl;
671 }
672 }
673 }
674
675 // 根据节点ID,获取对应的活动节点
676 ActivityImpl activityImpl =
((ProcessDefinitionImpl) processDefinition)
677 .findActivity(activityId);
678
679 return activityImpl;
680 }
681
682 /**
683 * ********************************************************************************<br>
684 * **********************以上为根据 任务节点ID 获取流程各对象查询方法**********************<br>
685 * *********************************************************************************<br>
686 */
687 }
转载至:http://blog.csdn.net/rosten/article/details/38300267
转载于:https://www.cnblogs.com/lidaofei1991/articles/7146078.html