http://blog.csdn.net/aochuanguying/article/details/7594197
- package com.famousPro.process.service.impl;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.activiti.engine.FormService;
- import org.activiti.engine.HistoryService;
- import org.activiti.engine.RepositoryService;
- import org.activiti.engine.RuntimeService;
- import org.activiti.engine.TaskService;
- import org.activiti.engine.history.HistoricActivityInstance;
- import org.activiti.engine.impl.RepositoryServiceImpl;
- import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
- import org.activiti.engine.impl.persistence.entity.TaskEntity;
- import org.activiti.engine.impl.pvm.PvmTransition;
- import org.activiti.engine.impl.pvm.process.ActivityImpl;
- import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
- import org.activiti.engine.impl.pvm.process.TransitionImpl;
- import org.activiti.engine.runtime.ProcessInstance;
- import org.activiti.engine.task.Task;
- import com.famousPro.common.service.impl.BaseServiceImp;
- import com.famousPro.common.util.IDGenerator;
- import com.famousPro.common.util.StringUtil;
- import com.famousPro.process.service.ProcessCoreService;
- import com.famousPro.process.service.ProcessOtherService;
- /**
- * 流程操作核心類
- * 此核心類主要處理:流程通過、駁回、會簽、轉辦、中止、掛起等核心操作
- *
- * @author wangfuwei
- *
- */
- publicclass ProcessCoreServiceImpl extends BaseServiceImp implements
- ProcessCoreService {
- protected RepositoryService repositoryService;
- protected RuntimeService runtimeService;
- protected TaskService taskService;
- protected FormService formService;
- protected HistoryService historyService;
- protected ProcessOtherService processOtherService;
- /**
- * 根據當前任務ID,查詢可以駁回的任務節點
- *
- * @param taskId
- * 當前任務ID
- */
- public List findBackAvtivity(String taskId) throws Exception {
- List rtnList = null ;
- if (processOtherService.isJointTask(taskId)) {// 會簽任務節點,不允許駁回
- rtnList = new ArrayList ();
- } else {
- rtnList = iteratorBackActivity(taskId, findActivitiImpl(taskId,
- null), new ArrayList (),
- new ArrayList ());
- }
- return reverList(rtnList);
- }
- /**
- * 審批通過(駁回直接跳回功能需后續擴展)
- *
- * @param taskId
- * 當前任務ID
- * @param variables
- * 流程存儲參數
- * @throws Exception
- */
- publicvoid passProcess(String taskId, Map <string, object> variables)
- throws Exception {
- List tasks = taskService.createTaskQuery().parentTaskId(taskId)
- .taskDescription("jointProcess").list();
- for (Task task : tasks) {// 級聯結束本節點發起的會簽任務
- commitProcess(task.getId(), null, null);
- }
- commitProcess(taskId, variables, null);
- }
- /**
- * 駁回流程
- *
- * @param taskId
- * 當前任務ID
- * @param activityId
- * 駁回節點ID
- * @param variables
- * 流程存儲參數
- * @throws Exception
- */
- publicvoid backProcess(String taskId, String activityId,
- Map <string, object> variables) throws Exception {
- if (StringUtil.isNull(activityId)) {
- thrownew Exception("駁回目標節點ID為空!");
- }
- // 查詢本節點發起的會簽任務,並結束
- List tasks = taskService.createTaskQuery().parentTaskId(taskId)
- .taskDescription("jointProcess").list();
- for (Task task : tasks) {
- commitProcess(task.getId(), null, null);
- }
- // 查找所有並行任務節點,同時駁回
- List taskList = findTaskListByKey(findProcessInstanceByTaskId(
- taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
- for (Task task : taskList) {
- commitProcess(task.getId(), variables, activityId);
- }
- }
- /**
- * 取回流程
- *
- * @param taskId
- * 當前任務ID
- * @param activityId
- * 取回節點ID
- * @throws Exception
- */
- publicvoid callBackProcess(String taskId, String activityId)
- throws Exception {
- if (StringUtil.isNull(activityId)) {
- thrownew Exception("目標節點ID為空!");
- }
- // 查找所有並行任務節點,同時取回
- List taskList = findTaskListByKey(findProcessInstanceByTaskId(
- taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
- for (Task task : taskList) {
- commitProcess(task.getId(), null, activityId);
- }
- }
- /**
- * 中止流程(特權人直接審批通過等)
- *
- * @param taskId
- */
- publicvoid endProcess(String taskId) throws Exception {
- ActivityImpl endActivity = findActivitiImpl(taskId, "end");
- commitProcess(taskId, null, endActivity.getId());
- }
- /**
- * 會簽操作
- *
- * @param taskId
- * 當前任務ID
- * @param userCodes
- * 會簽人賬號集合
- * @throws Exception
- */
- publicvoid jointProcess(String taskId, List userCodes)
- throws Exception {
- for (String userCode : userCodes) {
- TaskEntity task = (TaskEntity) taskService.newTask(IDGenerator
- .generateID());
- task.setAssignee(userCode);
- task.setName(findTaskById(taskId).getName() + "-會簽");
- task.setProcessDefinitionId(findProcessDefinitionEntityByTaskId(
- taskId).getId());
- task.setProcessInstanceId(findProcessInstanceByTaskId(taskId)
- .getId());
- task.setParentTaskId(taskId);
- task.setDescription("jointProcess");
- taskService.saveTask(task);
- }
- }
- /**
- * 轉辦流程
- *
- * @param taskId
- * 當前任務節點ID
- * @param userCode
- * 被轉辦人Code
- */
- publicvoid transferAssignee(String taskId, String userCode) {
- taskService.setAssignee(taskId, userCode);
- }
- /**
- * ***************************************************************************************************************************************************
- * ************************************************以下為流程會簽操作核心邏輯******************************************************************************
- * ***************************************************************************************************************************************************
- */
- /**
- * ***************************************************************************************************************************************************
- * ************************************************以上為流程會簽操作核心邏輯******************************************************************************
- * ***************************************************************************************************************************************************
- */
- /**
- * ***************************************************************************************************************************************************
- * ************************************************以下為流程轉向操作核心邏輯******************************************************************************
- * ***************************************************************************************************************************************************
- */
- /**
- * @param taskId
- * 當前任務ID
- * @param variables
- * 流程變量
- * @param activityId
- * 流程轉向執行任務節點ID
- * 此參數為空,默認為提交操作
- * @throws Exception
- */
- privatevoid commitProcess(String taskId, Map <string, object> variables,
- String activityId) throws Exception {
- if (variables == null) {
- variables = new HashMap <string, object>();
- }
- // 跳轉節點為空,默認提交操作
- if (StringUtil.isNull(activityId)) {
- taskService.complete(taskId, variables);
- } else {// 流程轉向操作
- turnTransition(taskId, activityId, variables);
- }
- }
- /**
- * 清空指定活動節點流向
- *
- * @param activityImpl
- * 活動節點
- * @return 節點流向集合
- */
- private List clearTransition(ActivityImpl activityImpl) {
- // 存儲當前節點所有流向臨時變量
- List oriPvmTransitionList = new ArrayList ();
- // 獲取當前節點所有流向,存儲到臨時變量,然后清空
- List pvmTransitionList = activityImpl
- .getOutgoingTransitions();
- for (PvmTransition pvmTransition : pvmTransitionList) {
- oriPvmTransitionList.add(pvmTransition);
- }
- pvmTransitionList.clear();
- return oriPvmTransitionList;
- }
- /**
- * 還原指定活動節點流向
- *
- * @param activityImpl
- * 活動節點
- * @param oriPvmTransitionList
- * 原有節點流向集合
- */
- privatevoid restoreTransition(ActivityImpl activityImpl,
- List oriPvmTransitionList) {
- // 清空現有流向
- List pvmTransitionList = activityImpl
- .getOutgoingTransitions();
- pvmTransitionList.clear();
- // 還原以前流向
- for (PvmTransition pvmTransition : oriPvmTransitionList) {
- pvmTransitionList.add(pvmTransition);
- }
- }
- /**
- * 流程轉向操作
- *
- * @param taskId
- * 當前任務ID
- * @param activityId
- * 目標節點任務ID
- * @param variables
- * 流程變量
- * @throws Exception
- */
- privatevoid turnTransition(String taskId, String activityId,
- Map <string, object> variables) throws Exception {
- // 當前節點
- ActivityImpl currActivity = findActivitiImpl(taskId, null);
- // 清空當前流向
- List oriPvmTransitionList = clearTransition(currActivity);
- // 創建新流向
- TransitionImpl newTransition = currActivity.createOutgoingTransition();
- // 目標節點
- ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);
- // 設置新流向的目標節點
- newTransition.setDestination(pointActivity);
- // 執行轉向任務
- taskService.complete(taskId, variables);
- // 刪除目標節點新流入
- pointActivity.getIncomingTransitions().remove(newTransition);
- // 還原以前流向
- restoreTransition(currActivity, oriPvmTransitionList);
- }
- /**
- * ***************************************************************************************************************************************************
- * ************************************************以上為流程轉向操作核心邏輯******************************************************************************
- * ***************************************************************************************************************************************************
- */
- /**
- * ***************************************************************************************************************************************************
- * ************************************************以下為查詢流程駁回節點核心邏輯***************************************************************************
- * ***************************************************************************************************************************************************
- */
- /**
- * 迭代循環流程樹結構,查詢當前節點可駁回的任務節點
- *
- * @param taskId
- * 當前任務ID
- * @param currActivity
- * 當前活動節點
- * @param rtnList
- * 存儲回退節點集合
- * @param tempList
- * 臨時存儲節點集合(存儲一次迭代過程中的同級userTask節點)
- * @return 回退節點集合
- */
- private List iteratorBackActivity(String taskId,
- ActivityImpl currActivity, List rtnList,
- List tempList) throws Exception {
- // 查詢流程定義,生成流程樹結構
- ProcessInstance processInstance = findProcessInstanceByTaskId(taskId);
- // 當前節點的流入來源
- List incomingTransitions = currActivity
- .getIncomingTransitions();
- // 條件分支節點集合,userTask節點遍歷完畢,迭代遍歷此集合,查詢條件分支對應的userTask節點
- List exclusiveGateways = new ArrayList ();
- // 並行節點集合,userTask節點遍歷完畢,迭代遍歷此集合,查詢並行節點對應的userTask節點
- List parallelGateways = new ArrayList ();
- // 遍歷當前節點所有流入路徑
- for (PvmTransition pvmTransition : incomingTransitions) {
- TransitionImpl transitionImpl = (TransitionImpl) pvmTransition;
- ActivityImpl activityImpl = transitionImpl.getSource();
- String type = (String) activityImpl.getProperty("type");
- /**
- * 並行節點配置要求:
- * 必須成對出現,且要求分別配置節點ID為:XXX_start(開始),XXX_end(結束)
- */
- if ("parallelGateway".equals(type)) {// 並行路線
- String gatewayId = activityImpl.getId();
- String gatewayType = gatewayId.substring(gatewayId
- .lastIndexOf("_") + 1);
- if ("START".equals(gatewayType.toUpperCase())) {// 並行起點,停止遞歸
- return rtnList;
- } else {// 並行終點,臨時存儲此節點,本次循環結束,迭代集合,查詢對應的userTask節點
- parallelGateways.add(activityImpl);
- }
- } elseif ("startEvent".equals(type)) {// 開始節點,停止遞歸
- return rtnList;
- } elseif ("userTask".equals(type)) {// 用戶任務
- tempList.add(activityImpl);
- } elseif ("exclusiveGateway".equals(type)) {// 分支路線,臨時存儲此節點,本次循環結束,迭代集合,查詢對應的userTask節點
- currActivity = transitionImpl.getSource();
- exclusiveGateways.add(currActivity);
- }
- }
- /**
- * 迭代條件分支集合,查詢對應的userTask節點
- */
- for (ActivityImpl activityImpl : exclusiveGateways) {
- iteratorBackActivity(taskId, activityImpl, rtnList, tempList);
- }
- /**
- * 迭代並行集合,查詢對應的userTask節點
- */
- for (ActivityImpl activityImpl : parallelGateways) {
- iteratorBackActivity(taskId, activityImpl, rtnList, tempList);
- }
- /**
- * 根據同級userTask集合,過濾最近發生的節點
- */
- currActivity = filterNewestActivity(processInstance, tempList);
- if (currActivity != null) {
- // 查詢當前節點的流向是否為並行終點,並獲取並行起點ID
- String id = findParallelGatewayId(currActivity);
- if (StringUtil.isNull(id)) {// 並行起點ID為空,此節點流向不是並行終點,符合駁回條件,存儲此節點
- rtnList.add(currActivity);
- } else {// 根據並行起點ID查詢當前節點,然后迭代查詢其對應的userTask任務節點
- currActivity = findActivitiImpl(taskId, id);
- }
- // 清空本次迭代臨時集合
- tempList.clear();
- // 執行下次迭代
- iteratorBackActivity(taskId, currActivity, rtnList, tempList);
- }
- return rtnList;
- }
- /**
- * 反向排序list集合,便於駁回節點按順序顯示
- *
- * @param list
- * @return
- */
- private List reverList(List list) {
- List rtnList = new ArrayList ();
- // 由於迭代出現重復數據,排除重復
- for (int i = list.size(); i > 0; i--) {
- if (!rtnList.contains(list.get(i - 1)))
- rtnList.add(list.get(i - 1));
- }
- return rtnList;
- }
- /**
- * 根據當前節點,查詢輸出流向是否為並行終點,如果為並行終點,則拼裝對應的並行起點ID
- *
- * @param activityImpl
- * 當前節點
- * @return
- */
- private String findParallelGatewayId(ActivityImpl activityImpl) {
- List incomingTransitions = activityImpl
- .getOutgoingTransitions();
- for (PvmTransition pvmTransition : incomingTransitions) {
- TransitionImpl transitionImpl = (TransitionImpl) pvmTransition;
- activityImpl = transitionImpl.getDestination();
- String type = (String) activityImpl.getProperty("type");
- if ("parallelGateway".equals(type)) {// 並行路線
- String gatewayId = activityImpl.getId();
- String gatewayType = gatewayId.substring(gatewayId
- .lastIndexOf("_") + 1);
- if ("END".equals(gatewayType.toUpperCase())) {
- return gatewayId.substring(0, gatewayId.lastIndexOf("_"))
- + "_start";
- }
- }
- }
- returnnull;
- }
- /**
- * 根據流入任務集合,查詢最近一次的流入任務節點
- *
- * @param processInstance
- * 流程實例
- * @param tempList
- * 流入任務集合
- * @return
- */
- private ActivityImpl filterNewestActivity(ProcessInstance processInstance,
- List tempList) {
- while (tempList.size() > 0) {
- ActivityImpl activity_1 = tempList.get(0);
- HistoricActivityInstance activityInstance_1 = findHistoricUserTask(
- processInstance, activity_1.getId());
- if (activityInstance_1 == null) {
- tempList.remove(activity_1);
- continue;
- }
- if (tempList.size() > 1) {
- ActivityImpl activity_2 = tempList.get(1);
- HistoricActivityInstance activityInstance_2 = findHistoricUserTask(
- processInstance, activity_2.getId());
- if (activityInstance_2 == null) {
- tempList.remove(activity_2);
- continue;
- }
- if (activityInstance_1.getEndTime().before(
- activityInstance_2.getEndTime())) {
- tempList.remove(activity_1);
- } else {
- tempList.remove(activity_2);
- }
- } else {
- break;
- }
- }
- if (tempList.size() > 0) {
- return tempList.get(0);
- }
- returnnull;
- }
- /**
- * 查詢指定任務節點的最新記錄
- *
- * @param processInstance
- * 流程實例
- * @param activityId
- * @return
- */
- private HistoricActivityInstance findHistoricUserTask(
- ProcessInstance processInstance, String activityId) {
- HistoricActivityInstance rtnVal = null;
- // 查詢當前流程實例審批結束的歷史節點
- List historicActivityInstances = historyService
- .createHistoricActivityInstanceQuery().activityType("userTask")
- .processInstanceId(processInstance.getId()).activityId(
- activityId).finished()
- .orderByHistoricActivityInstanceEndTime().desc().list();
- if (historicActivityInstances.size() > 0) {
- rtnVal = historicActivityInstances.get(0);
- }
- return rtnVal;
- }
- /**
- * *******************************************************************************************************
- * ********************************以上為查詢流程駁回節點核心邏輯***********************************************
- * ********************************************************************************************************
- */
- /**
- * ********************************************************************************
- * **********************以下為activiti 核心service
- * set方法***************************
- * *********************************************************************************
- */
- publicvoid setFormService(FormService formService) {
- this.formService = formService;
- }
- publicvoid setHistoryService(HistoryService historyService) {
- this.historyService = historyService;
- }
- publicvoid setRepositoryService(RepositoryService repositoryService) {
- this.repositoryService = repositoryService;
- }
- publicvoid setRuntimeService(RuntimeService runtimeService) {
- this.runtimeService = runtimeService;
- }
- publicvoid setTaskService(TaskService taskService) {
- this.taskService = taskService;
- }
- /**
- * ********************************************************************************
- * **********************以上為activiti 核心service
- * set方法***************************
- * *********************************************************************************
- */
- /**
- * ********************************************************************************
- * **********************以下為根據 任務節點ID 獲取流程各對象查詢方法**********************
- * *********************************************************************************
- */
- publicvoid setProcessOtherService(ProcessOtherService processOtherService) {
- this.processOtherService = processOtherService;
- }
- /**
- * 根據任務ID獲得任務實例
- *
- * @param taskId
- * 任務ID
- * @return
- * @throws Exception
- */
- private TaskEntity findTaskById(String taskId) throws Exception {
- TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(
- taskId).singleResult();
- if (task == null) {
- thrownew Exception("任務實例未找到!");
- }
- return task;
- }
- /**
- * 根據流程實例ID和任務key值查詢所有同級任務集合
- *
- * @param processInstanceId
- * @param key
- * @return
- */
- private List findTaskListByKey(String processInstanceId, String key) {
- return taskService.createTaskQuery().processInstanceId(
- processInstanceId).taskDefinitionKey(key).list();
- }
- /**
- * 根據任務ID獲取對應的流程實例
- *
- * @param taskId
- * 任務ID
- * @return
- * @throws Exception
- */
- private ProcessInstance findProcessInstanceByTaskId(String taskId)
- throws Exception {
- // 找到流程實例
- ProcessInstance processInstance = runtimeService
- .createProcessInstanceQuery().processInstanceId(
- findTaskById(taskId).getProcessInstanceId())
- .singleResult();
- if (processInstance == null) {
- thrownew Exception("流程實例未找到!");
- }
- return processInstance;
- }
- /**
- * 根據任務ID獲取流程定義
- *
- * @param taskId
- * 任務ID
- * @return
- * @throws Exception
- */
- private ProcessDefinitionEntity findProcessDefinitionEntityByTaskId(
- String taskId) throws Exception {
- // 取得流程定義
- ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
- .getDeployedProcessDefinition(findTaskById(taskId)
- .getProcessDefinitionId());
- if (processDefinition == null) {
- thrownew Exception("流程定義未找到!");
- }
- return processDefinition;
- }
- /**
- * 根據任務ID和節點ID獲取活動節點
- *
- * @param taskId
- * 任務ID
- * @param activityId
- * 活動節點ID
- * 如果為null或"",則默認查詢當前活動節點
- * 如果為"end",則查詢結束節點
- *
- * @return
- * @throws Exception
- */
- private ActivityImpl findActivitiImpl(String taskId, String activityId)
- throws Exception {
- // 取得流程定義
- ProcessDefinitionEntity processDefinition = findProcessDefinitionEntityByTaskId(taskId);
- // 獲取當前活動節點ID
- if (StringUtil.isNull(activityId)) {
- activityId = findTaskById(taskId).getTaskDefinitionKey();
- }
- // 根據流程定義,獲取該流程實例的結束節點
- if (activityId.toUpperCase().equals("END")) {
- for (ActivityImpl activityImpl : processDefinition.getActivities()) {
- List pvmTransitionList = activityImpl
- .getOutgoingTransitions();
- if (pvmTransitionList.isEmpty()) {
- return activityImpl;
- }
- }
- }
- // 根據節點ID,獲取對應的活動節點
- ActivityImpl activityImpl = ((ProcessDefinitionImpl) processDefinition)
- .findActivity(activityId);
- return activityImpl;
- }
- /**
- * ********************************************************************************
- * **********************以上為根據 任務節點ID 獲取流程各對象查詢方法**********************
- * *********************************************************************************
- */
- }