/**
* 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.instancemanager.impl;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fireflow.client.WorkflowSession;
import org.fireflow.client.WorkflowStatement;
import org.fireflow.client.impl.InternalSessionAttributeKeys;
import org.fireflow.client.impl.WorkflowSessionLocalImpl;
import org.fireflow.engine.context.AbsEngineModule;
import org.fireflow.engine.context.RuntimeContext;
import org.fireflow.engine.context.RuntimeContextAware;
import org.fireflow.engine.entity.EntityProperty;
import org.fireflow.engine.entity.repository.ProcessKey;
import org.fireflow.engine.entity.repository.ProcessRepository;
import org.fireflow.engine.entity.runtime.ActivityInstance;
import org.fireflow.engine.entity.runtime.ActivityInstanceState;
import org.fireflow.engine.entity.runtime.ProcessInstance;
import org.fireflow.engine.entity.runtime.ProcessInstanceProperty;
import org.fireflow.engine.entity.runtime.ProcessInstanceState;
import org.fireflow.engine.entity.runtime.impl.ProcessInstanceImpl;
import org.fireflow.engine.exception.EngineException;
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.instancemanager.ProcessInstanceManager;
import org.fireflow.engine.modules.instancemanager.event.ProcessInstanceEvent;
import org.fireflow.engine.modules.instancemanager.event.ProcessInstanceEventTrigger;
import org.fireflow.engine.modules.persistence.ActivityInstancePersister;
import org.fireflow.engine.modules.persistence.PersistenceService;
import org.fireflow.engine.modules.persistence.ProcessInstancePersister;
import org.fireflow.engine.modules.persistence.ProcessPersister;
import org.fireflow.model.InvalidModelException;
import org.fireflow.pvm.kernel.KernelManager;
import org.fireflow.pvm.kernel.PObjectKey;
import org.fireflow.pvm.kernel.Token;
/**
* @author 非也
* @version 2.0
*/
public abstract class AbsProcessInstanceManager extends AbsEngineModule implements ProcessInstanceManager,RuntimeContextAware{
Log log = LogFactory.getLog(AbsProcessInstanceManager.class);
protected RuntimeContext runtimeContext = null;
public ProcessInstance runProcessInstance(WorkflowSession session,String processInstanceId,String processType,
String bizId, Map<String, Object> variables) {
if (processInstanceId==null || processInstanceId.trim().equals("")){
throw new EngineException("流程实例Id不能为空");
}
WorkflowSessionLocalImpl localSession = (WorkflowSessionLocalImpl)session;
KernelManager kernelManager = runtimeContext.getDefaultEngineModule(KernelManager.class);
PersistenceService persistenceStrategy = runtimeContext.getEngineModule(PersistenceService.class,processType);
ProcessInstancePersister procInstPersistenceService = persistenceStrategy.getProcessInstancePersister();
ProcessPersister processPersister = persistenceStrategy.getProcessPersister();
ProcessInstance processInstance = (ProcessInstance)localSession.getCurrentProcessInstance();
if (processInstance==null || !processInstanceId.equals(processInstance.getId())){
processInstance = procInstPersistenceService.fetch(ProcessInstance.class, processInstanceId);
((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(processInstance);
}
if (processInstance==null || !ProcessInstanceState.INITIALIZED.equals(processInstance.getState())){
return processInstance;//说明已经是运行状态,无需再次运行。
}
if (bizId!=null&& !bizId.trim().equals("")){
((ProcessInstanceImpl)processInstance).setBizId(bizId);
procInstPersistenceService.saveOrUpdate(processInstance);
}
ProcessRepository repository = null;
try {
repository = processPersister.findProcessRepositoryByProcessKey( ProcessKey.valueOf(processInstance));
} catch (InvalidModelException e) {
throw new EngineException(processInstance,e.getMessage());
}
initProcessInstanceVariables(processInstance,repository==null?null:repository.getProcessObject(),variables);
//提取到parentToken
Token parentToken = null;
if (processInstance.getParentActivityInstanceId()!=null &&
!processInstance.getParentActivityInstanceId().equals("")){
parentToken = kernelManager.getTokenByElementInstanceId(processInstance.getParentActivityInstanceId(), processType);
}
//启动流程实例
kernelManager.startPObject(session, new PObjectKey(processInstance.getProcessId(),
processInstance.getVersion(),processInstance.getProcessType(),processInstance.getSubProcessId()),
parentToken,processInstance);
if (parentToken==null){//当parentToken不为空时,kernelManager已经处于执行状态;否则需要调用kernelManager.execute(session)启动一下
kernelManager.execute(session);
}
return processInstance;
}
protected abstract void initProcessInstanceVariables(ProcessInstance processInstance,Object subflow,Map<String,Object> initVariables);
public void changeProcessInstanceSate(WorkflowSession session,ProcessInstance procInst,ProcessInstanceState state,Object workflowElement){
CalendarService calendarService = runtimeContext.getEngineModule(CalendarService.class,procInst.getProcessType());
PersistenceService persistenceStrategy = runtimeContext.getEngineModule(PersistenceService.class, procInst.getProcessType());
ProcessInstancePersister procInstPersistenceService = persistenceStrategy.getProcessInstancePersister();
WorkflowSessionLocalImpl localSession = (WorkflowSessionLocalImpl)session;
//从session取相关字段的值
//TODO 是否需要state.getValue()==ProcessInstanceState.ABORTED.getValue() 这个判断
if (state.getValue()==ProcessInstanceState.ABORTED.getValue()){
Map<EntityProperty,Object> fieldsValues = (Map<EntityProperty,Object>)localSession.getAttribute(InternalSessionAttributeKeys.FIELDS_VALUES);
if (fieldsValues!=null){
String note = (String)fieldsValues.get(ProcessInstanceProperty.NOTE);
if (!StringUtils.isEmpty(note)){
((ProcessInstanceImpl)procInst).setNote(note);
}
}
}
((ProcessInstanceImpl)procInst).setState(state);
if (state.getValue()>ProcessInstanceState.DELIMITER.getValue()){
((ProcessInstanceImpl)procInst).setEndTime(calendarService.getSysDate());
}
procInstPersistenceService.saveOrUpdate(procInst);
if (state.getValue() > ProcessInstanceState.DELIMITER.getValue()) {
// 发布AFTER_PROCESS_INSTANCE_END事件
this.fireProcessInstanceEvent(session, procInst,
workflowElement, ProcessInstanceEventTrigger.AFTER_PROCESS_INSTANCE_END);
}
}
/* (non-Javadoc)
* @see org.fireflow.engine.instancemanager.ProcessInstanceManager#abortProcessInstance(org.fireflow.engine.WorkflowSession, org.fireflow.engine.entity.runtime.ProcessInstance)
*/
// public ProcessInstance abortProcessInstance(WorkflowSession session,
// ProcessInstance processInstance) {
// RuntimeContext context = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
// PersistenceService persistenceService = context.getEngineModule(PersistenceService.class, processInstance.getProcessType());
// //1、首先abort相应的activityInstance
// ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister();
// List<ActivityInstance> activityInstanceList = actInstPersister.findActivityInstances(processInstance.getId());
// ActivityInstanceManager actInstMgr = context.getEngineModule(ActivityInstanceManager.class, processInstance.getProcessType());
// if(activityInstanceList!=null){
// for (ActivityInstance activityInstance : activityInstanceList){
// if (activityInstance.getState().getValue()<ActivityInstanceState.DELIMITER.getValue()){
// actInstMgr.abortActivityInstance(session, activityInstance);
// }
// }
// }
//
// //2、然后abort processInstance
// CalendarService calendarService = context.getEngineModule(CalendarService.class, processInstance.getProcessType());
// ProcessInstancePersister persister = persistenceService.getProcessInstancePersister();
// ((ProcessInstanceImpl)processInstance).setState(ProcessInstanceState.ABORTED);
// ((ProcessInstanceImpl)processInstance).setEndTime(calendarService.getSysDate());
// persister.saveOrUpdate(processInstance);
// KernelManager kernelManager = context.getDefaultEngineModule(KernelManager.class);
// Token token = kernelManager.getToken(processInstance.getTokenId(), processInstance.getProcessType());
//
// kernelManager.fireTerminationEvent(session, token, null);
//
// return processInstance;
// }
/* (non-Javadoc)
* @see org.fireflow.engine.instancemanager.ProcessInstanceManager#restoreProcessInstance(org.fireflow.engine.WorkflowSession, org.fireflow.engine.entity.runtime.ProcessInstance)
*/
public ProcessInstance restoreProcessInstance(WorkflowSession session,
ProcessInstance processInstance) {
RuntimeContext context = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
PersistenceService persistenceService = context.getEngineModule(PersistenceService.class, processInstance.getProcessType());
//1、首先restore相应的activityInstance
ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister();
List<ActivityInstance> activityInstanceList = actInstPersister.findActivityInstances(processInstance.getId());
ActivityInstanceManager actInstMgr = context.getEngineModule(ActivityInstanceManager.class, processInstance.getProcessType());
if(activityInstanceList!=null){
for (ActivityInstance activityInstance : activityInstanceList){
if (activityInstance.getState().getValue()<ActivityInstanceState.DELIMITER.getValue()){
actInstMgr.restoreActivityInstance(session, activityInstance);
}
}
}
WorkflowSessionLocalImpl localSession = (WorkflowSessionLocalImpl)session;
//2、然后restore processInstance
//从session取相关字段的值
Map<EntityProperty,Object> fieldsValues = (Map<EntityProperty,Object>)localSession.getAttribute(InternalSessionAttributeKeys.FIELDS_VALUES);
if (fieldsValues!=null){
String note = (String)fieldsValues.get(ProcessInstanceProperty.NOTE);
if (!StringUtils.isEmpty(note)){
((ProcessInstanceImpl)processInstance).setNote(note);
}
}
ProcessInstancePersister persister = persistenceService.getProcessInstancePersister();
((ProcessInstanceImpl)processInstance).setSuspended(false);
persister.saveOrUpdate(processInstance);
//触发事件
try{
WorkflowStatement stmt = localSession.createWorkflowStatement();
Object thisSubProcess = stmt.getWorkflowDefinitionElement(processInstance);
this.fireProcessInstanceEvent(localSession, processInstance, thisSubProcess, ProcessInstanceEventTrigger.ON_PROCESS_INSTANCE_RESTORED);
}catch(Exception e){
log.error(e.getMessage(),e);
}
return processInstance;
}
/* (non-Javadoc)
* @see org.fireflow.engine.instancemanager.ProcessInstanceManager#suspendProcessInstance(org.fireflow.engine.WorkflowSession, org.fireflow.engine.entity.runtime.ProcessInstance)
*/
public ProcessInstance suspendProcessInstance(WorkflowSession session,
ProcessInstance processInstance) {
RuntimeContext context = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
PersistenceService persistenceService = context.getEngineModule(PersistenceService.class, processInstance.getProcessType());
WorkflowSessionLocalImpl localSession = (WorkflowSessionLocalImpl)session;
//1、首先suspend相应的activityInstance
ActivityInstancePersister actInstPersister = persistenceService.getActivityInstancePersister();
List<ActivityInstance> activityInstanceList = actInstPersister.findActivityInstances(processInstance.getId());
ActivityInstanceManager actInstMgr = context.getEngineModule(ActivityInstanceManager.class, processInstance.getProcessType());
if(activityInstanceList!=null){
for (ActivityInstance activityInstance : activityInstanceList){
if (activityInstance.getState().getValue()<ActivityInstanceState.DELIMITER.getValue()){
actInstMgr.suspendActivityInstance(session, activityInstance);
}
}
}
//2、然后suspend processInstance
//从session取相关字段的值
Map<EntityProperty,Object> fieldsValues = (Map<EntityProperty,Object>)localSession.getAttribute(InternalSessionAttributeKeys.FIELDS_VALUES);
if (fieldsValues!=null){
String note = (String)fieldsValues.get(ProcessInstanceProperty.NOTE);
if (!StringUtils.isEmpty(note)){
((ProcessInstanceImpl)processInstance).setNote(note);
}
}
ProcessInstancePersister persister = persistenceService.getProcessInstancePersister();
((ProcessInstanceImpl)processInstance).setSuspended(true);
persister.saveOrUpdate(processInstance);
//触发事件
try{
WorkflowStatement stmt = localSession.createWorkflowStatement();
Object thisSubProcess = stmt.getWorkflowDefinitionElement(processInstance);
this.fireProcessInstanceEvent(localSession, processInstance, thisSubProcess, ProcessInstanceEventTrigger.ON_PROCESS_INSTANCE_SUSPENDED);
}catch(Exception e){
log.error(e.getMessage(),e);
}
return processInstance;
}
/* (non-Javadoc)
* @see org.fireflow.engine.context.RuntimeContextAware#getRuntimeContext()
*/
public RuntimeContext getRuntimeContext() {
return runtimeContext;
}
/* (non-Javadoc)
* @see org.fireflow.engine.context.RuntimeContextAware#setRuntimeContext(org.fireflow.engine.context.RuntimeContext)
*/
public void setRuntimeContext(RuntimeContext ctx) {
runtimeContext = ctx;
}
public void fireProcessInstanceEvent(WorkflowSession session,ProcessInstance procInst,Object subflow,ProcessInstanceEventTrigger eventType){
try{
WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl)session;
RuntimeContext rtCtx = sessionLocalImpl.getRuntimeContext();
EventBroadcasterManager evetBroadcasterMgr = rtCtx.getDefaultEngineModule(EventBroadcasterManager.class);
EventBroadcaster broadcaster = evetBroadcasterMgr.getEventBroadcaster(ProcessInstanceEvent.class.getName());
if (broadcaster!=null){
ProcessInstanceEvent event = new ProcessInstanceEvent();
event.setSource(procInst);
event.setEventTrigger(eventType);
event.setWorkflowElement(subflow);
event.setCurrentWorkflowSession(sessionLocalImpl);
broadcaster.fireEvent(sessionLocalImpl, event);
}
}catch(Exception e){
log.error(e.getMessage(),e);
}
}
}