• 开源工作流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);
    		}
    	}
    
  • 相关阅读:
    兼容ie6:zindex
    分割网址/链接/url变量
    JS:给select添加option选项
    如果用QQ邮箱订阅一个网站或博客?
    input无边框
    有些标签的innerHTML属性是只读的
    满屏透明层
    文本框光标不居中?
    PHP:json_decode解析JSON数据
    开放平台/API
  • 原文地址:https://www.cnblogs.com/mzhanker/p/2075585.html
Copyright © 2020-2023  润新知