Activiti之流程通过、驳回、会签、转办、中止、挂起等核心操作封装(Activiti5.9)
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