开源工作流Fireflow源码分析之拒收

   要了解拒收,看懂源代码,至少要先看几次作者的原文档说明,他对拒收的定义以及约束在哪里。

   拒收的含义是:当前操作者因为某种原因拒绝接收工作项,将已经发生的流转退回到前

驱环节。

   可以实现拒收的场景是:

/**
	 *拒收工单 
	 */
	public void rejectWorkItem(IWorkItem workItem, String comments)
			throws EngineException, KernelException {
		//取到工单对应的Activity
		Activity thisActivity = workItem.getTaskInstance().getActivity();
		//取到TaskInstance
		TaskInstance thisTaskInstance = (TaskInstance) workItem
				.getTaskInstance();
		//如果工单处于非活动状态,或者被挂起,则不允许reject
		if (workItem.getState() > 5 || workItem.getTaskInstance().isSuspended()) {
			throw new EngineException(
					thisTaskInstance.getProcessInstanceId(),
					thisTaskInstance.getWorkflowProcess(),
					thisTaskInstance.getTaskId(),
					"Reject operation refused!Current work item is completed or the correspond task instance is suspended!!");
		}
		// 拒收操作环节只可以含有一个task
		if (thisActivity.getTasks().size() > 1) {
			throw new EngineException(thisTaskInstance.getProcessInstanceId(),
					thisTaskInstance.getWorkflowProcess(), thisTaskInstance
							.getTaskId(),
					"Reject operation refused!The correspond activity has more than 1 tasks");
		}
		// 汇签Task不允许Reject,因为你不确定其它的人是否完成。。。
		if (FormTask.ALL.equals(thisTaskInstance.getAssignmentStrategy())) {
			throw new EngineException(thisTaskInstance.getProcessInstanceId(),
					thisTaskInstance.getWorkflowProcess(), thisTaskInstance
							.getTaskId(),
					"Reject operation refused!The assignment strategy is 'ALL'");
		}
        //处理拒收的边界问题,不能退回到开始节点
        if(thisTaskInstance.getFromActivityId().equals(IToken.FROM_START_NODE)){
                throw new EngineException(
                                thisTaskInstance.getProcessInstanceId(),
                                thisTaskInstance.getWorkflowProcess(),
                                thisTaskInstance.getTaskId(),
                                "Reject operation refused!Because the from activityId equals "+IToken.FROM_START_NODE );
        }
        //取到持久化处理器
		IPersistenceService persistenceService = this.rtCtx
				.getPersistenceService();
		List<ITaskInstance> siblingTaskInstancesList = null;

		siblingTaskInstancesList = persistenceService
				.findTaskInstancesForProcessInstanceByStepNumber(workItem
						.getTaskInstance().getProcessInstanceId(),
						thisTaskInstance.getStepNumber());

		// split情况下,每个分支上的环节不可以执行拒收操作
		if (siblingTaskInstancesList.size() > 1) {
			throw new EngineException(
					thisTaskInstance.getProcessInstanceId(),
					thisTaskInstance.getWorkflowProcess(),
					thisTaskInstance.getTaskId(),
					"Reject operation refused!Because the process instance has taken a split operation.");
		}

		// 检查From Activity中是否有ToolTask和SubflowTask,如果有tool或subflow也不允许拒收
		//注意这里,为什么可以从fromActivityID得到它的多个前驱activity,这个要看之后的synchroinizerInstance之汇聚算法
		List<String> fromActivityIdList = new ArrayList<String>();
		StringTokenizer tokenizer = new StringTokenizer(thisTaskInstance
				.getFromActivityId(), IToken.FROM_ACTIVITY_ID_SEPARATOR);
		while (tokenizer.hasMoreTokens()) {
			fromActivityIdList.add(tokenizer.nextToken());
		}
		WorkflowProcess workflowProcess = workItem.getTaskInstance()
				.getWorkflowProcess();
		for (int i = 0; i < fromActivityIdList.size(); i++) {
			String fromActivityId = (String) fromActivityIdList.get(i);
			Activity fromActivity = (Activity) workflowProcess
					.findWFElementById(fromActivityId);
			List<Task> fromTaskList = fromActivity.getTasks();
			for (int j = 0; j < fromTaskList.size(); j++) {
				Task task =  fromTaskList.get(j);
				//前驱环节的task类型是tool或subflow,则不可能拒收
				if (Task.TOOL.equals(task.getType())
						|| Task.SUBFLOW.equals(task.getType())) {
					throw new EngineException(
							thisTaskInstance.getProcessInstanceId(),
							thisTaskInstance.getWorkflowProcess(),
							thisTaskInstance.getTaskId(),
							"Reject operation refused!The previous activity contains tool-task or subflow-task");

				}
			}
		}
		// 取到工个流网实例
		INetInstance netInstance = rtCtx.getKernelManager().getNetInstance(
				workflowProcess.getId(),
				workItem.getTaskInstance().getVersion());
		if (netInstance == null) {
			throw new EngineException(thisTaskInstance.getProcessInstanceId(),
					thisTaskInstance.getWorkflowProcess(), thisTaskInstance
							.getTaskId(),
					"Not find the net instance for workflow process [id="
							+ workflowProcess.getId() + ", version="
							+ workItem.getTaskInstance().getVersion() + "]");
		}

		// 执行reject操作。
		//取到当前流程会话session
		IWorkflowSession session = ((IWorkflowSessionAware) workItem)
				.getCurrentWorkflowSession();
		//设置作了退回动作
		session.setWithdrawOrRejectOperationFlag(true);
		//当前步骤加1
		int newStepNumber = thisTaskInstance.getStepNumber() + 1;
		try {
			// 首先将本WorkItem和TaskInstance cancel掉。
			workItem.setComments(comments);
			((WorkItem) workItem).setState(IWorkItem.CANCELED);
			((WorkItem) workItem).setEndTime(rtCtx.getCalendarService()
					.getSysDate());
			rtCtx.getPersistenceService().saveOrUpdateWorkItem(workItem);
            //终止本任务
			persistenceService.abortTaskInstance(thisTaskInstance);

			// 删除本环节的token
			persistenceService.deleteTokensForNode(thisTaskInstance
					.getProcessInstanceId(), thisTaskInstance.getActivityId());

			IActivityInstance fromActivityInstance = null;
			for (int i = 0; i < fromActivityIdList.size(); i++) {
				
				String fromActivityId = (String) fromActivityIdList.get(i);
				Object obj = netInstance.getWFElementInstance(fromActivityId);
				fromActivityInstance = (IActivityInstance) obj;
				//生成一个新的token
				Token newToken = new Token();
				//设置状态
				((Token) newToken).setAlive(true);
				//设置当前节点id
				((Token) newToken).setNodeId(fromActivityId);
				//设置流程实例id
				newToken.setProcessInstanceId(thisTaskInstance
						.getProcessInstanceId());
				newToken.setProcessInstance(((TaskInstance) thisTaskInstance)
						.getAliveProcessInstance());
				newToken.setFromActivityId(thisTaskInstance.getActivityId());
				newToken.setStepNumber(newStepNumber);
				newToken.setValue(0);
				persistenceService.saveOrUpdateToken(newToken);
                //生成一个新的任务 
				this.createTaskInstances(newToken, fromActivityInstance);
                //如果需要打印trance
				if (rtCtx.isEnableTrace()) {
					ProcessInstanceTrace trace = new ProcessInstanceTrace();
					trace.setProcessInstanceId(thisTaskInstance
							.getProcessInstanceId());
					trace.setStepNumber(newStepNumber);
					trace.setType(ProcessInstanceTrace.REJECT_TYPE);
					trace.setFromNodeId(thisActivity.getId());
					trace.setToNodeId(fromActivityId);
					trace.setEdgeId("");
					rtCtx.getPersistenceService()
							.saveOrUpdateProcessInstanceTrace(trace);
				}
			}
			//下面的这些代码我认为是没有意义的.
            //得到前一个activity的一条输出边
			ITransitionInstance theLeavingTransitionInstance = (ITransitionInstance) fromActivityInstance
					.getLeavingTransitionInstances().get(0);
			//得到前一个同步器
			ISynchronizerInstance synchronizerInstance = (ISynchronizerInstance) theLeavingTransitionInstance
					.getLeavingNodeInstance();
			//if语句永远为真的,不会执行的。
			if (synchronizerInstance.getEnteringTransitionInstances().size() > fromActivityIdList
					.size()) {
				Token supplementToken = new Token();
				((Token) supplementToken).setAlive(false);
				((Token) supplementToken).setNodeId(synchronizerInstance
						.getSynchronizer().getId());
				supplementToken.setProcessInstanceId(thisTaskInstance
						.getProcessInstanceId());
				supplementToken
						.setProcessInstance(((TaskInstance) thisTaskInstance)
								.getAliveProcessInstance());
				supplementToken.setFromActivityId("EMPTY(created by reject)");
				supplementToken
						.setStepNumber(thisTaskInstance.getStepNumber() + 1);
				supplementToken.setValue(synchronizerInstance.getVolume()
						- theLeavingTransitionInstance.getWeight()
						* fromActivityIdList.size());
				persistenceService.saveOrUpdateToken(supplementToken);
			}
		} finally {
			session.setWithdrawOrRejectOperationFlag(false);
		}
	}
原文地址:https://www.cnblogs.com/mzhanker/p/2075585.html