/**
* Copyright 2007-2010 非也
* All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License v3 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 Lesser General Public License along
* with this library; if not, see http://www.gnu.org/licenses/lgpl.html.
*
*/
package org.fireflow.pdl.fpdl.behavior;
import java.util.List;
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.impl.WorkflowSessionLocalImpl;
import org.fireflow.engine.context.RuntimeContext;
import org.fireflow.engine.entity.runtime.ProcessInstance;
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.instancemanager.ProcessInstanceManager;
import org.fireflow.engine.modules.instancemanager.event.ProcessInstanceEventTrigger;
import org.fireflow.engine.modules.persistence.PersistenceService;
import org.fireflow.engine.modules.persistence.ProcessInstancePersister;
import org.fireflow.engine.modules.persistence.TokenPersister;
import org.fireflow.pdl.fpdl.misc.FpdlConstants;
import org.fireflow.pdl.fpdl.process.Node;
import org.fireflow.pdl.fpdl.process.SubProcess;
import org.fireflow.pvm.kernel.KernelManager;
import org.fireflow.pvm.kernel.PObjectKey;
import org.fireflow.pvm.kernel.Token;
import org.fireflow.pvm.kernel.TokenState;
import org.fireflow.pvm.pdllogic.BusinessStatus;
import org.fireflow.pvm.pdllogic.CompensationHandler;
import org.fireflow.pvm.pdllogic.ContinueDirection;
import org.fireflow.pvm.pdllogic.ExecuteResult;
import org.fireflow.pvm.pdllogic.FaultHandler;
import org.fireflow.pvm.pdllogic.WorkflowBehavior;
/**
*
* @author 非也 nychen2000@163.com
* Fire Workflow 官方网站:www.firesoa.com 或者 www.fireflow.org
*
*/
public class SubProcessBehavior implements WorkflowBehavior {
private static final Log log = LogFactory.getLog(SubProcessBehavior.class);
public CompensationHandler getCompensationHandler(String compensationCode){
return null;
}
//(2012-02-05,Cancel动作容易和handleTermination混淆,意义也不是特别大,暂且注销)
// public CancellationHandler getCancellationHandler(){
// return null;
// }
public FaultHandler getFaultHandler(String errorCode){
return null;
}
/**
* prepare方法创建流程实例
*/
public Boolean prepare(WorkflowSession session, Token token,
Object workflowElement) {
WorkflowSessionLocalImpl sessionLocal = (WorkflowSessionLocalImpl)session;
RuntimeContext context = sessionLocal.getRuntimeContext();
PersistenceService persistenceService = context.getEngineModule(PersistenceService.class, token.getProcessType());
ProcessInstancePersister procInstPersistSvc = persistenceService.getProcessInstancePersister();
ProcessInstance newProcessInstance = (ProcessInstance)sessionLocal.getCurrentProcessInstance();
if (newProcessInstance==null || !newProcessInstance.getId().equals(token.getProcessInstanceId())){
WorkflowQuery<ProcessInstance> q4ProcInst = sessionLocal.createWorkflowQuery(ProcessInstance.class);
newProcessInstance = q4ProcInst.get(token.getProcessInstanceId());
sessionLocal.setCurrentProcessInstance(newProcessInstance);
}
//考虑到启动子流程的问题,不允许在此处设置processInstanceId,只能在KernelManager.startPObject(...)有设置
// token.setProcessInstanceId(newProcessInstance.getId());
//考虑到启动子流程的问题,不允许在此处设置elementInstanceId
// token.setElementInstanceId(newProcessInstance.getId());
// TokenPersister tokenPersister = persistenceService.getTokenPersister();
// tokenPersister.saveOrUpdate(token);
((ProcessInstanceImpl)newProcessInstance).setTokenId(token.getId());
procInstPersistSvc.saveOrUpdate(newProcessInstance);
//发布事件
ProcessInstanceManager procInstManager = context.getEngineModule(ProcessInstanceManager.class, token.getProcessType());
procInstManager.fireProcessInstanceEvent(session, newProcessInstance, workflowElement, ProcessInstanceEventTrigger.BEFORE_PROCESS_INSTANCE_RUN);
return true;//true表示告诉虚拟机,“我”已经准备妥当了。
}
/* (non-Javadoc)
* @see org.fireflow.pvm.pdllogic.WorkflowBehavior#execute(org.fireflow.engine.WorkflowSession, org.fireflow.pvm.kernel.Token, java.lang.Object)
*/
public ExecuteResult execute(WorkflowSession session, Token processToken,
Object workflowElement) {
SubProcess subflow = (SubProcess)workflowElement;
Node entry = subflow.getEntry();
if (entry==null){
throw new EngineException("子过程入口节点为空,无法继续执行;子过程Id 是"+subflow.getId());
}
PObjectKey pobjectKey = new PObjectKey(processToken.getProcessId(),processToken.getVersion(),processToken.getProcessType(),entry.getId());
RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
KernelManager kernelManager = ctx.getDefaultEngineModule(KernelManager.class);
kernelManager.startPObject(session, pobjectKey, processToken,null);
ExecuteResult result = new ExecuteResult();
result.setStatus(BusinessStatus.RUNNING);
return result;
}
/* (non-Javadoc)
* @see org.fireflow.pvm.pdllogic.WorkflowBehavior#onTokenStateChanged(org.fireflow.engine.WorkflowSession, org.fireflow.pvm.kernel.Token, java.lang.Object)
*/
public void onTokenStateChanged(WorkflowSession session, Token token,
Object workflowElement) {
RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
PersistenceService persistenceStrategy = ctx.getEngineModule(PersistenceService.class, FpdlConstants.PROCESS_TYPE_FPDL20);
ProcessInstancePersister procInstPersistenceService = persistenceStrategy.getProcessInstancePersister();
WorkflowSessionLocalImpl sessionLocal = (WorkflowSessionLocalImpl)session;
ProcessInstance oldProcInst = sessionLocal.getCurrentProcessInstance();
ProcessInstance procInst = oldProcInst;
if (oldProcInst==null || !oldProcInst.getId().equals(token.getElementInstanceId())){
procInst = procInstPersistenceService.fetch(ProcessInstance.class, token.getElementInstanceId());
}
ProcessInstanceManager processInstanceManager = ctx.getEngineModule(ProcessInstanceManager.class, FpdlConstants.PROCESS_TYPE_FPDL20);
try{
ProcessInstanceState state = ProcessInstanceState.valueOf(token.getState().name());
processInstanceManager.changeProcessInstanceSate(session, procInst, state,workflowElement);
}finally{
((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(oldProcInst);
}
}
/* (non-Javadoc)
* @see org.fireflow.pvm.pdllogic.WorkflowBehavior#continueOn(org.fireflow.engine.WorkflowSession, org.fireflow.pvm.kernel.Token, java.lang.Object)
*/
public ContinueDirection continueOn(WorkflowSession session,
Token token, Object workflowElement) {
RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
KernelManager kernelManager = ctx.getDefaultEngineModule(KernelManager.class);
List<Token> childTokenList = kernelManager.getChildren(token);
if (childTokenList==null || childTokenList.size()==0){
return ContinueDirection.closeMe();
}else{
for (Token tk : childTokenList){
if (tk.getState().getValue()<TokenState.DELIMITER.getValue()){
return ContinueDirection.waitingForClose();
}
}
}
return ContinueDirection.closeMe();
}
}