/** * Copyright 2007-2010 非也 * All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation。 * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses. * */ package org.fireflow.engine.modules.workitem.impl; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.fireflow.client.WorkflowQuery; import org.fireflow.client.WorkflowSession; import org.fireflow.client.WorkflowStatement; import org.fireflow.client.impl.WorkflowSessionLocalImpl; import org.fireflow.client.query.Restrictions; import org.fireflow.engine.context.AbsEngineModule; import org.fireflow.engine.context.RuntimeContext; import org.fireflow.engine.entity.repository.ProcessKey; import org.fireflow.engine.entity.runtime.ActivityInstance; import org.fireflow.engine.entity.runtime.ActivityInstanceState; import org.fireflow.engine.entity.runtime.LocalWorkItem; import org.fireflow.engine.entity.runtime.ProcessInstance; import org.fireflow.engine.entity.runtime.WorkItem; import org.fireflow.engine.entity.runtime.WorkItemProperty; import org.fireflow.engine.entity.runtime.WorkItemState; import org.fireflow.engine.entity.runtime.impl.AbsActivityInstance; import org.fireflow.engine.entity.runtime.impl.AbsWorkItem; import org.fireflow.engine.entity.runtime.impl.ActivityInstanceImpl; import org.fireflow.engine.entity.runtime.impl.LocalWorkItemImpl; import org.fireflow.engine.exception.EngineException; import org.fireflow.engine.exception.InvalidOperationException; import org.fireflow.engine.exception.ServiceInvocationException; import org.fireflow.engine.invocation.AssignmentHandler; import org.fireflow.engine.invocation.ServiceInvoker; import org.fireflow.engine.invocation.impl.DynamicAssignmentHandler; import org.fireflow.engine.modules.beanfactory.BeanFactory; import org.fireflow.engine.modules.calendar.CalendarService; import org.fireflow.engine.modules.event.EventBroadcaster; import org.fireflow.engine.modules.event.EventBroadcasterManager; import org.fireflow.engine.modules.instancemanager.ActivityInstanceManager; import org.fireflow.engine.modules.ousystem.User; import org.fireflow.engine.modules.ousystem.impl.FireWorkflowSystem; import org.fireflow.engine.modules.ousystem.impl.UserImpl; import org.fireflow.engine.modules.persistence.ActivityInstancePersister; import org.fireflow.engine.modules.persistence.PersistenceService; import org.fireflow.engine.modules.persistence.TokenPersister; import org.fireflow.engine.modules.persistence.WorkItemPersister; import org.fireflow.engine.modules.processlanguage.ProcessLanguageManager; import org.fireflow.engine.modules.workitem.WorkItemCenter; import org.fireflow.engine.modules.workitem.WorkItemManager; import org.fireflow.engine.modules.workitem.event.WorkItemEvent; import org.fireflow.engine.modules.workitem.event.WorkItemEventTrigger; import org.fireflow.model.InvalidModelException; import org.fireflow.model.binding.ResourceBinding; import org.fireflow.model.binding.ServiceBinding; import org.fireflow.model.resourcedef.WorkItemAssignmentStrategy; import org.fireflow.pvm.kernel.Token; import org.fireflow.pvm.kernel.TokenState; import org.fireflow.pvm.kernel.impl.TokenImpl; /** * * * @author 非也 * @version 2.0 */ public abstract class AbsWorkItemManager extends AbsEngineModule implements WorkItemManager,ServiceInvoker { private static Log log = LogFactory.getLog(AbsWorkItemManager.class); public WorkItemCenter getWorkItemCenter(){ return null; } //////////////////////////////////////////////////////////////////////////////////////// ////////////// 下面两个方法实现ServiceInvoker ////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// protected boolean isSkip(WorkflowSession session, ActivityInstance activityInstance, ServiceBinding serviceBinding, ResourceBinding resourceBinding, Object theActivityObj){ return false; } protected boolean isRedo(WorkflowSession session, ActivityInstance activityInstance, ServiceBinding serviceBinding, ResourceBinding resourceBinding, Object theActivityObj){ return false; } public boolean invoke(WorkflowSession session, ActivityInstance activityInstance, ServiceBinding serviceBinding, ResourceBinding resourceBinding, Object theActivityObj) throws ServiceInvocationException { RuntimeContext runtimeContext = ((WorkflowSessionLocalImpl)session).getRuntimeContext(); boolean assignDone = false; // 1、检查是否是重做,如果是重做则应用重做策略 if (isSkip(session,activityInstance,serviceBinding,resourceBinding,theActivityObj)){ WorkflowQuery<WorkItem> wiQuery = session.createWorkflowQuery(WorkItem.class); wiQuery.add(Restrictions.eq(WorkItemProperty.PROCESS_INSTANCE_ID, activityInstance.getProcessInstanceId())) .add(Restrictions.eq(WorkItemProperty.ACTIVITY_ID, activityInstance.getNodeId()));//只要有产生工作项,则认为已经被执行过一次 List<WorkItem> completedWorkItemList = wiQuery.list(); if (completedWorkItemList!=null && completedWorkItemList.size()>0){ return true;//true表示结束当前activity instance继续往前流转 } }else if (isRedo(session,activityInstance,serviceBinding,resourceBinding,theActivityObj)){ //先查找当前环节已经存在的工作项, //查询当前实例的,同一环节的,已经完成的工作项 WorkflowQuery<WorkItem> wiQuery = session.createWorkflowQuery(WorkItem.class); wiQuery.add(Restrictions.eq(WorkItemProperty.PROCESS_INSTANCE_ID, activityInstance.getProcessInstanceId())) .add(Restrictions.eq(WorkItemProperty.ACTIVITY_ID, activityInstance.getNodeId())) .add(Restrictions.eq(WorkItemProperty.STATE, WorkItemState.COMPLETED)); List<WorkItem> completedWorkItemList = wiQuery.list(); if (completedWorkItemList!=null || completedWorkItemList.size()>0){ //分配给上次完成本工作的人 List<User> owners = new ArrayList<User>(); for (WorkItem wi : completedWorkItemList){ UserImpl u = new UserImpl(); u.setId(wi.getOwnerId()); u.setName(wi.getOwnerName()); u.setDeptId(wi.getOwnerDeptId()); u.setDeptName(wi.getOwnerDeptName()); owners.add(u); } DynamicAssignmentHandler assignmentHandler = new DynamicAssignmentHandler(); assignmentHandler.setPotentialOwners(owners); assignmentHandler.setAssignmentStrategy(resourceBinding.getAssignmentStrategy()); assignmentHandler.assign(session, activityInstance,this,theActivityObj, serviceBinding, resourceBinding); return false;//return false表示该服务持续执行,需要引擎等待 } } // 2、检查有无设置DynamicAssignmentHandler AssignmentHandler _handler = ((WorkflowSessionLocalImpl) session) .consumeDynamicAssignmentHandler(activityInstance.getNodeId()); if (_handler != null) { _handler.assign(session, activityInstance, this, theActivityObj, serviceBinding, resourceBinding); return false;// return false表示该服务持续执行,需要引擎等待 } // 3、调用resourceBinding的设置进行workitem分配 if (resourceBinding != null) { String assignmentHandlerBeanName = resourceBinding .getAssignmentHandlerBeanName(); String assignmentHandlerClassName = resourceBinding .getAssignmentHandlerClassName(); BeanFactory beanFactory = runtimeContext .getDefaultEngineModule(BeanFactory.class); AssignmentHandler handler = null; if (!StringUtils.isEmpty(assignmentHandlerBeanName)) { // 3、检查是否有AssignmentHandlerBeanName handler = (AssignmentHandler) beanFactory .getBean(assignmentHandlerBeanName); } else if (!StringUtils.isEmpty(assignmentHandlerClassName)) { // 4、检查是否有AssignmentHandlerClassName handler = (AssignmentHandler) beanFactory .createBean(assignmentHandlerClassName); } if (handler != null) { handler.assign(session, activityInstance, this, theActivityObj, serviceBinding, resourceBinding); assignDone = true; } } if (!assignDone){ //TODO 分配给系统用户,并记录流程日志 //TODO 此处直接调用WorkItemManager,待优化 this.createWorkItem(session, ((WorkflowSessionLocalImpl)session).getCurrentProcessInstance(), activityInstance, FireWorkflowSystem.getInstance(), theActivityObj,null); } return false;//表示是异步调用 } /** * 默认的规则是:只要activityInstance有活动的workItem则不能够停止。<br/> * 可以定制该方法,以实现“按百分比决定活动是否结束”的业务需求。 */ public int determineActivityCloseStrategy(WorkflowSession session,ActivityInstance activityInstance, Object theActivity, ServiceBinding serviceBinding){ RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)session).getRuntimeContext(); PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, activityInstance.getProcessType()); WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister(); List<WorkItem> workItems = workItemPersister.findWorkItemsForActivityInstance(activityInstance.getId()); for (WorkItem wi : workItems){ if (wi.getState().getValue()<WorkItemState.DELIMITER.getValue()){ return ServiceInvoker.WAITING_FOR_CLOSE; } } return ServiceInvoker.CLOSE_ACTIVITY; } ////////////////////////////////////////////////////////////////////////////////// /** * 取消一个WorkItem * @param wi */ protected void abortWorkItem(WorkflowSession currentSession,WorkItem wi,Object thisActivity){ LocalWorkItemImpl workItem = (LocalWorkItemImpl)wi; if (wi.getState().getValue()>WorkItemState.DELIMITER.getValue())return; RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)currentSession).getRuntimeContext(); PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, workItem.getProcessType()); ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister(); ActivityInstance activityInstance = actInstPersister.fetch(ActivityInstanceImpl.class,workItem.getActivityInstanceId()); String processType = ""; if (activityInstance!=null){ processType = activityInstance.getProcessType(); } WorkItemPersister persister = persistenceService.getWorkItemPersister(); ((LocalWorkItemImpl)workItem).setState(WorkItemState.ABORTED); persister.saveOrUpdate(wi); //发布事件 this.fireWorkItemEvent(currentSession, wi, thisActivity, WorkItemEventTrigger.AFTER_WORKITEM_END); } /** * 将同一个ActivityInstance的WorkItem取消 * @param actInstId */ public void abortWorkfItemOfTheSameActInst(WorkflowSession currentSession,ActivityInstance actInst){ WorkflowQuery query = currentSession.createWorkflowQuery(WorkItem.class); query.add(Restrictions.eq(WorkItemProperty.ACTIVITY_INSTANCE_ID, actInst.getId())); List<WorkItem> workItemList = query.list(); Object thisActivity = null; try{ WorkflowStatement stmt = currentSession.createWorkflowStatement(); thisActivity = stmt.getWorkflowDefinitionElement(actInst); }catch(Exception e){ log.error(e.getMessage(),e); } if (workItemList!=null){ for (WorkItem wi : workItemList){ this.abortWorkItem(currentSession, wi,thisActivity); } } } /* (non-Javadoc) * @see org.fireflow.engine.service.form.WorkItemManager#claimWorkItem(java.lang.String, java.lang.String) */ public WorkItem claimWorkItem(WorkflowSession currentSession,WorkItem wi){ RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)currentSession).getRuntimeContext(); LocalWorkItemImpl workItem = (LocalWorkItemImpl)wi; PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, workItem.getProcessType()); ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister(); ActivityInstance activityInstance = actInstPersister.fetch(ActivityInstanceImpl.class, workItem.getActivityInstanceId()); WorkflowStatement __statement = currentSession.createWorkflowStatement(); Object thisActivity = null; try { thisActivity = __statement.getWorkflowDefinitionElement(activityInstance); } catch (InvalidModelException e) { log.error(e.getMessage(),e); } //这个事件估计没有什么实际意义 this.fireWorkItemEvent(currentSession, workItem, thisActivity, WorkItemEventTrigger.BEFORE_WORKITEM_CLAIMED); CalendarService calendarService = rtCtx.getEngineModule(CalendarService.class, activityInstance.getProcessType()); ActivityInstancePersister activityInstancePersister = persistenceService.getActivityInstancePersister(); WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister(); activityInstancePersister.lockActivityInstance(activityInstance.getId()); // 0、首先修改workitem的状态 ((AbsWorkItem) workItem).setState(WorkItemState.RUNNING); ((AbsWorkItem) workItem).setClaimedTime(calendarService.getSysDate()); workItemPersister.saveOrUpdate(workItem); // 1、如果不是会签,则删除其他的workitem if (WorkItemAssignmentStrategy.ASSIGN_TO_ANY.equals(workItem.getAssignmentStrategy())) { workItemPersister.deleteWorkItemsInInitializedState(activityInstance.getId(),workItem.getParentWorkItemId()); } // 2、将ActivityInstance的canBeWithdrawn字段改称false。即不允许被撤销 ((AbsActivityInstance)activityInstance).setCanBeWithdrawn(false); activityInstancePersister.saveOrUpdate(activityInstance); //发布事件 this.fireWorkItemEvent(currentSession, workItem, thisActivity, WorkItemEventTrigger.AFTER_WORKITEM_CLAIMED); return workItem; } public WorkItem disclaimWorkItem(WorkflowSession currentSession, WorkItem wi)throws InvalidOperationException{ LocalWorkItemImpl workItemToBeDisclaimed = (LocalWorkItemImpl)wi; RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)currentSession).getRuntimeContext(); PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, workItemToBeDisclaimed.getProcessType()); ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister(); ActivityInstance thisActivityInstance = actInstPersister.fetch(ActivityInstanceImpl.class, workItemToBeDisclaimed.getActivityInstanceId()); ProcessInstance thisProcessInstance = thisActivityInstance.getProcessInstance(currentSession); ((WorkflowSessionLocalImpl)currentSession).setCurrentProcessInstance(thisProcessInstance); WorkflowStatement localStatement = currentSession.createWorkflowStatement(); ProcessKey pKey = new ProcessKey(thisActivityInstance.getProcessId(),thisActivityInstance.getVersion(),thisActivityInstance.getProcessType()); CalendarService calendarService = rtCtx.getEngineModule(CalendarService.class, thisActivityInstance.getProcessType()); ProcessLanguageManager processService = rtCtx.getEngineModule(ProcessLanguageManager.class, thisActivityInstance.getProcessType()); Object theActivity = null; try{ theActivity = localStatement.getWorkflowDefinitionElement(thisActivityInstance); }catch(InvalidModelException e){ log.error(e); throw new InvalidOperationException(e); } ServiceBinding serviceBinding = null; try{ serviceBinding = processService.getServiceBinding(theActivity); }catch(InvalidModelException e){ log.error(e); throw new InvalidOperationException(e); } ResourceBinding resourceBinding = null; try{ resourceBinding = processService.getResourceBinding(theActivity); }catch(InvalidModelException e){ log.error(e); throw new InvalidOperationException(e); } try { ((AbsWorkItem)workItemToBeDisclaimed).setState(WorkItemState.DISCLAIMED); ((AbsWorkItem)workItemToBeDisclaimed).setEndTime(calendarService.getSysDate()); WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister(); workItemPersister.saveOrUpdate(workItemToBeDisclaimed); //发布事件 this.fireWorkItemEvent(currentSession, workItemToBeDisclaimed, theActivity, WorkItemEventTrigger.AFTER_WORKITEM_END); this.invoke(currentSession, thisActivityInstance,serviceBinding,resourceBinding, theActivity); return workItemToBeDisclaimed; } catch (ServiceInvocationException e) { // TODO Auto-generated catch block e.printStackTrace(); throw new EngineException(thisActivityInstance,e.getMessage()); } } /* (non-Javadoc) * @see org.fireflow.engine.service.form.WorkItemManager#completeWorkItemAndJumpTo(org.fireflow.engine.entity.runtime.WorkItem, java.lang.String, java.lang.String) */ public WorkItem completeWorkItemAndJumpTo(WorkflowSession currentSession, WorkItem wi, String targetActivityId) throws InvalidOperationException{ LocalWorkItemImpl workItemToBeCompleted = (LocalWorkItemImpl)wi; WorkflowSessionLocalImpl localSession = (WorkflowSessionLocalImpl)currentSession; RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)currentSession).getRuntimeContext(); PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, workItemToBeCompleted.getProcessType()); CalendarService calendarService = rtCtx.getEngineModule(CalendarService.class, workItemToBeCompleted.getProcessType()); ActivityInstanceManager activityInstanceManager = rtCtx.getEngineModule(ActivityInstanceManager.class, workItemToBeCompleted.getProcessType()); WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister(); ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister(); ActivityInstance thisActivityInstance = actInstPersister.fetch(ActivityInstanceImpl.class, workItemToBeCompleted.getActivityInstanceId()); if (workItemToBeCompleted.getParentWorkItemId() != null && !workItemToBeCompleted.getParentWorkItemId().trim().equals("") && !workItemToBeCompleted.getParentWorkItemId().trim().equals( WorkItem.NO_PARENT_WORKITEM)) { String reassignType = workItemToBeCompleted.getReassignType(); if (reassignType == null || reassignType.trim().equals("") || reassignType.trim().equals(WorkItem.REASSIGN_AFTER_ME)) {//后加签 WorkItemAssignmentStrategy assignmentStrategy = workItemToBeCompleted.getAssignmentStrategy(); if (assignmentStrategy != null && !assignmentStrategy.equals( WorkItemAssignmentStrategy.ASSIGN_TO_ANY)) { List<WorkItem> workItemsWithSameParent = workItemPersister .findWorkItemsForActivityInstance(workItemToBeCompleted .getActivityInstanceId(), workItemToBeCompleted .getParentWorkItemId()); for(WorkItem wiTmp : workItemsWithSameParent){ if (wiTmp.getState().getValue()<WorkItemState.DELIMITER.getValue()){ throw new InvalidOperationException("Reassigned workitem can NOT jump to another activity."); } } } } else{//前加签 throw new InvalidOperationException("Reassigned workitem can NOT jump to another activity."); } } ProcessInstance thisProcessInstance = thisActivityInstance.getProcessInstance(currentSession); ((WorkflowSessionLocalImpl)currentSession).setCurrentProcessInstance(thisProcessInstance); ((WorkflowSessionLocalImpl)currentSession).setCurrentActivityInstance(thisActivityInstance); ((AbsWorkItem)workItemToBeCompleted).setState(WorkItemState.COMPLETED); ((AbsWorkItem)workItemToBeCompleted).setEndTime(calendarService.getSysDate()); workItemPersister.saveOrUpdate(workItemToBeCompleted); //发布事件 try { WorkflowStatement stmt = currentSession.createWorkflowStatement(); Object thisActivity = stmt .getWorkflowDefinitionElement(thisActivityInstance); this.fireWorkItemEvent(currentSession, workItemToBeCompleted, thisActivity, WorkItemEventTrigger.AFTER_WORKITEM_END); } catch (Exception e) { log.error(e.getMessage(),e); } if (workItemToBeCompleted.getParentWorkItemId() == null || workItemToBeCompleted.getParentWorkItemId().trim().equals("") || workItemToBeCompleted.getParentWorkItemId().trim().equals( WorkItem.NO_PARENT_WORKITEM)) { localSession.setAttribute(WorkItemManager.TARGET_ACTIVITY_ID, targetActivityId); activityInstanceManager.onServiceCompleted(currentSession, thisActivityInstance); } return workItemToBeCompleted; } /* (non-Javadoc) * @see org.fireflow.engine.service.form.WorkItemManager#reassignWorkItemTo(org.fireflow.engine.entity.runtime.WorkItem, java.lang.String, java.lang.String) */ public List<WorkItem> reassignWorkItemTo(WorkflowSession currentSession, WorkItem wi, AssignmentHandler assignmentHandler, Object theActivity,ServiceBinding serviceBinding, ResourceBinding resourceBinding){ LocalWorkItemImpl workItemToBeReassign = (LocalWorkItemImpl)wi; RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)currentSession).getRuntimeContext(); PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, workItemToBeReassign.getProcessType()); WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister(); ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister(); String thisActInstId = workItemToBeReassign.getActivityInstanceId(); ActivityInstance thisActivityInstance = actInstPersister.fetch(ActivityInstanceImpl.class, thisActInstId); ProcessInstance thisProcessInstance = thisActivityInstance.getProcessInstance(currentSession); ((WorkflowSessionLocalImpl)currentSession).setCurrentActivityInstance(thisActivityInstance); ((WorkflowSessionLocalImpl)currentSession).setCurrentProcessInstance(thisProcessInstance); List<WorkItem> result = assignmentHandler.assign(currentSession, thisActivityInstance, this, theActivity, serviceBinding, resourceBinding); // 转移到assignmentHandler里面进行工作项处理 // List<WorkItem> result = new ArrayList<WorkItem>(); // for (User user : users){ // Map<WorkItemProperty,Object> values = new HashMap<WorkItemProperty,Object>(); // values.put(WorkItemProperty.REASSIGN_TYPE, reassignType); // values.put(WorkItemProperty.ASSIGNMENT_STRATEGY, assignmentStrategy); // values.put(WorkItemProperty.PARENT_WORKITEM_ID,workItem.getId()); // // WorkItem wi = this.createWorkItem(currentSession, thisProcessInstance, thisActivityInstance, user,theActivity, values); // // result .add(wi); // } CalendarService calendarService = rtCtx.getEngineModule(CalendarService.class, thisActivityInstance.getProcessType()); ((AbsWorkItem)workItemToBeReassign).setState(WorkItemState.REASSIGNED); ((AbsWorkItem)workItemToBeReassign).setEndTime(calendarService.getSysDate()); workItemPersister.saveOrUpdate(workItemToBeReassign); //发布事件 try { this.fireWorkItemEvent(currentSession, workItemToBeReassign, theActivity, WorkItemEventTrigger.AFTER_WORKITEM_END); } catch (Exception e) { log.error(e.getMessage(),e); } return result; } // /* (non-Javadoc) // * @see org.fireflow.engine.service.form.WorkItemManager#rejectWorkItem(org.fireflow.engine.entity.runtime.WorkItem, java.lang.String) // */ // @Override // public void rejectWorkItem(WorkItem workItem, String comments) // throws InvalidOperationException { // // TODO Auto-generated method stub // // } /* (non-Javadoc) * @see org.fireflow.engine.service.form.WorkItemManager#withdrawWorkItem(org.fireflow.engine.entity.runtime.WorkItem) */ public WorkItem withdrawWorkItem(WorkflowSession currentSession,WorkItem workItem) throws InvalidOperationException { WorkflowQuery<WorkItem> wiQuery = currentSession.createWorkflowQuery(WorkItem.class); wiQuery.add(Restrictions.eq(WorkItemProperty.PROCESS_INSTANCE_ID, ((LocalWorkItem)workItem).getProcessInstanceId())) .add(Restrictions.eq(WorkItemProperty.SUBPROCESS_ID, ((LocalWorkItem)workItem).getSubProcessId())) .add(Restrictions.gt(WorkItemProperty.STEP_NUMBER, ((LocalWorkItem)workItem).getStepNumber())); List<WorkItem> nextWorkItemList = wiQuery.list(); if (nextWorkItemList==null || nextWorkItemList.size()==0){ throw new InvalidOperationException("无后续工作项,无法取回"); } List<String> nextActInstanceIdList = new ArrayList<String>(); boolean canBeWithdrawn = true; int maxStepNumber = 0; for (WorkItem wi : nextWorkItemList){ if (wi.getState().getValue()>WorkItemState.INITIALIZED.getValue()){ //说明有工作项已经被签收,不能做取回操作 canBeWithdrawn = false; } String actInstId = ((LocalWorkItem)wi).getActivityInstanceId(); if (!nextActInstanceIdList.contains(actInstId)){ nextActInstanceIdList.add(actInstId); } if (maxStepNumber<((LocalWorkItem)wi).getStepNumber()){ maxStepNumber = ((LocalWorkItem)wi).getStepNumber(); } } if (!canBeWithdrawn){ throw new InvalidOperationException("有后续工作项已经被签收,不能做取回操作。"); } WorkflowSessionLocalImpl localSession = (WorkflowSessionLocalImpl)currentSession; RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)currentSession).getRuntimeContext(); PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, ((LocalWorkItem)workItem).getProcessType()); CalendarService calendarService = rtCtx.getEngineModule(CalendarService.class, ((LocalWorkItem)workItem).getProcessType()); WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister(); ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister(); TokenPersister tokenPersister = persistenceService.getTokenPersister(); //1、先创建本环节的token,actinst和工作项, int newStepNumber = maxStepNumber+1; ActivityInstance thisActivityInstance = actInstPersister.fetch(ActivityInstance.class, ((LocalWorkItem)workItem).getActivityInstanceId()); Token thisToken = tokenPersister.fetch(Token.class, thisActivityInstance.getTokenId()); Token newToken = new TokenImpl(thisToken); newToken.setElementId(thisToken.getElementId()); newToken.setFromToken(thisToken.getFromToken()); newToken.setStepNumber(newStepNumber); newToken.setState(TokenState.RUNNING); tokenPersister.saveOrUpdate(newToken); ActivityInstanceImpl newActivityInstance = (ActivityInstanceImpl)((ActivityInstanceImpl)thisActivityInstance).clone(); newActivityInstance.setId(null); newActivityInstance.setTokenId(newToken.getId()); newActivityInstance.setStepNumber(newStepNumber); newActivityInstance.setState(ActivityInstanceState.RUNNING); actInstPersister.saveOrUpdate(newActivityInstance); LocalWorkItemImpl newWorkItem = (LocalWorkItemImpl)(( LocalWorkItemImpl)workItem).clone(); newWorkItem.setId(null); newWorkItem.setActivityInstanceId(newActivityInstance.getId()); newWorkItem.setStepNumber(newStepNumber); newWorkItem.setState(WorkItemState.INITIALIZED); workItemPersister.saveOrUpdate(newWorkItem); //2、然后对后续环节实例做abort操作 WorkflowStatement stmt = currentSession.createWorkflowStatement(); for (String actInstId : nextActInstanceIdList){ stmt.abortActivityInstance(actInstId, "被取回"); } return newWorkItem; } /* (non-Javadoc) * @see org.fireflow.engine.service.human.WorkItemManager#completeWorkItem(org.fireflow.engine.WorkflowSession, org.fireflow.engine.entity.runtime.WorkItem, java.lang.String, java.lang.String, java.lang.String) */ public WorkItem completeWorkItem(WorkflowSession currentSession, WorkItem wi) throws InvalidOperationException { LocalWorkItemImpl workItemToBeCompleted = (LocalWorkItemImpl)wi; RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)currentSession).getRuntimeContext(); ActivityInstanceManager actInstMgr = rtCtx.getEngineModule(ActivityInstanceManager.class, workItemToBeCompleted.getProcessType()); PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, workItemToBeCompleted.getProcessType()); CalendarService calendarService = rtCtx.getEngineModule(CalendarService.class, workItemToBeCompleted.getProcessType()); WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister(); ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister(); ActivityInstance thisActivityInstance = actInstPersister.fetch(ActivityInstanceImpl.class, workItemToBeCompleted.getActivityInstanceId()); ProcessInstance thisProcessInstance = thisActivityInstance.getProcessInstance(currentSession); ((WorkflowSessionLocalImpl)currentSession).setCurrentProcessInstance(thisProcessInstance); ((WorkflowSessionLocalImpl)currentSession).setCurrentActivityInstance(thisActivityInstance); ((AbsWorkItem)workItemToBeCompleted).setState(WorkItemState.COMPLETED); ((AbsWorkItem)workItemToBeCompleted).setEndTime(calendarService.getSysDate()); workItemPersister.saveOrUpdate(workItemToBeCompleted); //发布事件 try { WorkflowStatement stmt = currentSession.createWorkflowStatement(); Object thisActivity = stmt .getWorkflowDefinitionElement(thisActivityInstance); this.fireWorkItemEvent(currentSession, workItemToBeCompleted, thisActivity, WorkItemEventTrigger.AFTER_WORKITEM_END); } catch (Exception e) { log.error(e.getMessage(),e); } //后续处理 if (workItemToBeCompleted.getParentWorkItemId() == null || workItemToBeCompleted.getParentWorkItemId().trim().equals("") || workItemToBeCompleted.getParentWorkItemId().trim().equals( WorkItem.NO_PARENT_WORKITEM)) { actInstMgr.onServiceCompleted(currentSession, thisActivityInstance); }else{ //委派的工作项特殊处理 String reassignType = workItemToBeCompleted.getReassignType(); if (reassignType == null || reassignType.trim().equals("") || reassignType.trim().equals(WorkItem.REASSIGN_AFTER_ME)) {//后加签 WorkItemAssignmentStrategy assignmentStrategy = workItemToBeCompleted.getAssignmentStrategy(); if (assignmentStrategy == null || assignmentStrategy.equals( WorkItemAssignmentStrategy.ASSIGN_TO_ANY)) { actInstMgr.onServiceCompleted(currentSession, thisActivityInstance); } else { List<WorkItem> workItemsWithSameParent = workItemPersister .findWorkItemsForActivityInstance(workItemToBeCompleted .getActivityInstanceId(), workItemToBeCompleted .getParentWorkItemId()); boolean canCompleteActivityInstance = true; for(WorkItem wiTmp : workItemsWithSameParent){ if (wiTmp.getState().getValue()<WorkItemState.DELIMITER.getValue()){ canCompleteActivityInstance = false; break; } } if (canCompleteActivityInstance){ actInstMgr.onServiceCompleted(currentSession, thisActivityInstance); } } } else{//前加签 WorkItemAssignmentStrategy assignmentStrategy = workItemToBeCompleted.getAssignmentStrategy(); if (assignmentStrategy == null || assignmentStrategy.equals( WorkItemAssignmentStrategy.ASSIGN_TO_ANY)) { WorkItem parentWorkItem = workItemPersister.fetch(WorkItem.class, workItemToBeCompleted.getParentWorkItemId()); WorkItem newParentWi = this.cloneWorkItem(parentWorkItem, calendarService); workItemPersister.saveOrUpdate(newParentWi); } else { List<WorkItem> workItemsWithSameParent = workItemPersister .findWorkItemsForActivityInstance(workItemToBeCompleted .getActivityInstanceId(), workItemToBeCompleted .getParentWorkItemId()); boolean canReturnToParentWorkItem = true; for(WorkItem wiTmp : workItemsWithSameParent){ if (wiTmp.getState().getValue()<WorkItemState.DELIMITER.getValue()){ canReturnToParentWorkItem = false; break; } } if(canReturnToParentWorkItem){ WorkItem parentWorkItem = workItemPersister.fetch(WorkItem.class, workItemToBeCompleted.getParentWorkItemId()); WorkItem newParentWi = this.cloneWorkItem(parentWorkItem, calendarService); workItemPersister.saveOrUpdate(newParentWi); } } } } return workItemToBeCompleted; } private WorkItem cloneWorkItem(WorkItem wi,CalendarService calendarService){ AbsWorkItem tmp = (AbsWorkItem)((AbsWorkItem)wi).clone(); tmp.setState(WorkItemState.RUNNING); tmp.setClaimedTime(calendarService.getSysDate()); tmp.setEndTime(null); tmp.setNote(null); tmp.setAttachmentId(null); tmp.setCreatedTime(calendarService.getSysDate()); return tmp; } // /* (non-Javadoc) // * @see org.fireflow.engine.service.human.WorkItemManager#completeWorkItem(org.fireflow.engine.WorkflowSession, java.lang.String, java.lang.String, java.lang.String, java.lang.String) // */ // @Override // public void completeWorkItem(WorkflowSession currentSession, // String workItemId, String commentSummary, String note, // String attachmentId,String processType) throws InvalidOperationException { // // RuntimeContext rtCtx = ((WorkflowSessionLocalImpl)currentSession).getRuntimeContext(); // // PersistenceService persistenceService = rtCtx.getEngineModule(PersistenceService.class, processType); // WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister(); // // WorkItem wi = workItemPersister.find(WorkItem.class, workItemId); // // this.completeWorkItem(currentSession, wi, commentSummary, note, attachmentId); // // } /* AbsWorkItemManager实现了ServiceInvoker,不需要该方法 ,2012-02-20 */ /* protected ServiceInvoker getServiceInvoker(RuntimeContext runtimeContext,WorkItem workItem){ ActivityInstance activityInstance = workItem.getActivityInstance(); String processType = activityInstance.getProcessType(); ProcessLanguageManager processUtil = runtimeContext.getEngineModule(ProcessLanguageManager.class,processType); ServiceBinding serviceBinding = null; try{ serviceBinding = processUtil.getServiceBinding(new ProcessKey(activityInstance.getProcessId(),activityInstance.getVersion(),processType), activityInstance.getSubflowId(), activityInstance.getNodeId()); }catch(InvalidModelException e){ log.error(e); } if (serviceBinding==null)return null; ServiceDef service = serviceBinding.getService(); if (service==null) return null; ServiceInvoker serviceInvoker = null; String invokerBeanName = service.getInvokerBeanName(); String invokerClassName = service.getInvokerClassName(); BeanFactory beanFactory = runtimeContext.getEngineModule(BeanFactory.class,processType); if (!StringUtils.isEmpty(invokerBeanName)){ serviceInvoker = (ServiceInvoker)beanFactory.getBean(invokerBeanName); } if (serviceInvoker==null && !StringUtils.isEmpty(invokerClassName)){ serviceInvoker = (ServiceInvoker) beanFactory.createBean(invokerClassName); } return serviceInvoker; } */ public void fireWorkItemEvent(WorkflowSession session,WorkItem workItem,Object activity,WorkItemEventTrigger eventType){ try{ WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl)session; RuntimeContext rtCtx = sessionLocalImpl.getRuntimeContext(); EventBroadcasterManager evetBroadcasterMgr = rtCtx.getDefaultEngineModule(EventBroadcasterManager.class); EventBroadcaster broadcaster = evetBroadcasterMgr.getEventBroadcaster(WorkItemEvent.class.getName()); if (broadcaster!=null){ WorkItemEvent event = new WorkItemEvent(); event.setSource(workItem); event.setEventTrigger(eventType); event.setWorkflowElement(activity); event.setCurrentWorkflowSession(sessionLocalImpl); broadcaster.fireEvent(sessionLocalImpl, event); } }catch(Exception e){ log.error(e.getMessage(), e); } } }