Activiti之流程通过、驳回、会签、转办、中止、挂起等核心操作封装(Activiti5.9)

http://blog.csdn.net/rosten/article/details/38300267

  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     }  
原文地址:https://www.cnblogs.com/sucia-panda/p/7065624.html