/**
* 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.pdl.fpdl.behavior;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
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.ActivityInstance;
import org.fireflow.engine.entity.runtime.ActivityInstanceState;
import org.fireflow.engine.entity.runtime.ProcessInstance;
import org.fireflow.engine.entity.runtime.Variable;
import org.fireflow.engine.entity.runtime.impl.AbsVariable;
import org.fireflow.engine.entity.runtime.impl.ActivityInstanceImpl;
import org.fireflow.engine.entity.runtime.impl.VariableImpl;
import org.fireflow.engine.exception.ServiceInvocationException;
import org.fireflow.engine.modules.beanfactory.BeanFactory;
import org.fireflow.engine.modules.instancemanager.ActivityInstanceManager;
import org.fireflow.engine.modules.instancemanager.event.ActivityInstanceEventTrigger;
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.TokenPersister;
import org.fireflow.engine.modules.persistence.VariablePersister;
import org.fireflow.model.data.Property;
import org.fireflow.pdl.fpdl.behavior.router.SplitEvaluator;
import org.fireflow.pdl.fpdl.behavior.router.impl.OrSplitEvaluator;
import org.fireflow.pdl.fpdl.misc.FpdlConstants;
import org.fireflow.pdl.fpdl.process.Activity;
import org.fireflow.pdl.fpdl.process.Node;
import org.fireflow.pdl.fpdl.process.StartNode;
import org.fireflow.pdl.fpdl.process.features.Feature;
import org.fireflow.pdl.fpdl.process.features.startnode.TimerStartFeature;
import org.fireflow.pvm.kernel.BookMark;
import org.fireflow.pvm.kernel.ExecutionEntrance;
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.kernel.impl.TokenImpl;
import org.fireflow.pvm.pdllogic.BusinessStatus;
import org.fireflow.pvm.pdllogic.ContinueDirection;
import org.fireflow.pvm.pdllogic.ExecuteResult;
import org.fireflow.pvm.pdllogic.WorkflowBehavior;
import org.firesoa.common.schema.NameSpaces;
import org.firesoa.common.util.JavaDataTypeConvertor;
/**
* @author 非也
* @version 2.0
*/
public class ActivityBehavior extends AbsNodeBehavior implements WorkflowBehavior {
Log log = LogFactory.getLog(ActivityBehavior.class);
//(2012-02-05,Cancel动作容易和handleTermination混淆,意义也不是特别大,暂且注销)
// private CancellationHandler cancellationHandler = new ActivityCancellationHandler();
/* (non-Javadoc)
* @see org.fireflow.pvm.pdllogic.WorkflowBehavior#prepare(org.fireflow.engine.WorkflowSession, org.fireflow.pvm.kernel.Token, java.lang.Object)
*/
public Boolean prepare(WorkflowSession session, Token token,
Object workflowElement) {
WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl)session;
RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
ActivityInstanceManager activityInstanceMgr = ctx.getEngineModule(ActivityInstanceManager.class, FpdlConstants.PROCESS_TYPE_FPDL20);
PersistenceService persistenceStrategy = ctx.getEngineModule(PersistenceService.class, token.getProcessType());
ActivityInstancePersister actInstPersistSvc = persistenceStrategy.getActivityInstancePersister();
//0、校验processInstance与token的一致性
ProcessInstance processInstance = sessionLocalImpl.getCurrentProcessInstance();
if (processInstance==null || !processInstance.getId().equals(token.getProcessInstanceId())){
WorkflowQuery<ProcessInstance> q4ProcInst = sessionLocalImpl.createWorkflowQuery(ProcessInstance.class);
processInstance = q4ProcInst.get(token.getProcessInstanceId());
sessionLocalImpl.setCurrentProcessInstance(processInstance);
}
//1、创建并保存环节实例
ActivityInstanceImpl activityInstance = (ActivityInstanceImpl)activityInstanceMgr.createActivityInstance(session, processInstance, workflowElement);
activityInstance.setStepNumber(token.getStepNumber());
activityInstance.setTokenId(token.getId());
actInstPersistSvc.saveOrUpdate(activityInstance);
//2、设置session和token
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(activityInstance);
token.setElementInstanceId(activityInstance.getId());
//3、初始化活动的流程变量
initActivityInstanceVariables(persistenceStrategy.getVariablePersister(),
activityInstance,((Activity)workflowElement).getProperties(),null);
//4、发布事件
activityInstanceMgr.fireActivityInstanceEvent(session, activityInstance, workflowElement, ActivityInstanceEventTrigger.ON_ACTIVITY_INSTANCE_CREATED);
return 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 token,
Object workflowElement) {
WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl)session;
Activity activity = (Activity)workflowElement;
log.debug("Activity[id="+activity.getId()+"] Behavior executed!");
RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
//1、检验currentActivityInstance和currentProcessInstance的一致性
ProcessInstance oldProcInst = sessionLocalImpl.getCurrentProcessInstance();
ActivityInstance oldActInst = sessionLocalImpl.getCurrentActivityInstance();
PersistenceService persistenceStrategy = ctx.getEngineModule(PersistenceService.class, FpdlConstants.PROCESS_TYPE_FPDL20);
ActivityInstancePersister actInstPersistenceService = persistenceStrategy.getActivityInstancePersister();
ProcessInstancePersister processInstancePersister = persistenceStrategy.getProcessInstancePersister();
if (oldProcInst==null || !oldProcInst.getId().equals(token.getProcessInstanceId())){
ProcessInstance procInst = processInstancePersister.fetch(ProcessInstance.class, token.getProcessInstanceId());
((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(procInst);
}
if (oldActInst==null || !oldActInst.getId().equals(token.getElementInstanceId())){
ActivityInstance actInst = actInstPersistenceService.fetch(ActivityInstance.class, token.getElementInstanceId());
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(actInst);
}
//2、执行业务操作
ActivityInstanceManager activityInstanceMgr = ctx.getEngineModule(ActivityInstanceManager.class, FpdlConstants.PROCESS_TYPE_FPDL20);
ActivityInstance currentActivityInstance = sessionLocalImpl.getCurrentActivityInstance();
try {
boolean b = activityInstanceMgr.runActivityInstance(session, workflowElement, currentActivityInstance);
if (b){
ExecuteResult result = new ExecuteResult();
result.setStatus(BusinessStatus.COMPLETED);
return result;
}else{
//只有在这种情况下,启动边上的Timer节点才有意义
List<StartNode> attachedStartNodes = activity.getAttachedStartNodes();
if (attachedStartNodes!=null){
for (StartNode startNode : attachedStartNodes){
Feature decorator = startNode.getFeature();
//启动timer类型的边节点
if (decorator instanceof TimerStartFeature){
Token childToken = new TokenImpl(token);
childToken.setElementId(startNode.getId());
childToken.setParentTokenId(token.getParentTokenId());
childToken.setAttachedToToken(token.getId());
BookMark bookMark = new BookMark();
bookMark.setToken(childToken);
bookMark.setExtraArg(BookMark.SOURCE_TOKEN, token);
bookMark.setExecutionEntrance(ExecutionEntrance.TAKE_TOKEN);
KernelManager kernelManager = ctx.getDefaultEngineModule(KernelManager.class);
kernelManager.addBookMark(bookMark);
}
}
}
ExecuteResult result = new ExecuteResult();
result.setStatus(BusinessStatus.RUNNING);
return result;
}
} catch (ServiceInvocationException e) {
// TODO Auto-generated catch block
//TODO 进行异常处理,记录日志
e.printStackTrace();
ExecuteResult result = new ExecuteResult();
result.setErrorCode(e.getErrorCode());
result.setStatus(BusinessStatus.FAULTING);
return result;
}finally{
sessionLocalImpl.setCurrentProcessInstance(oldProcInst);
sessionLocalImpl.setCurrentActivityInstance(oldActInst);
}
}
public ContinueDirection continueOn(WorkflowSession session, Token token,
Object workflowElement) {
if (token.getState().getValue()<TokenState.DELIMITER.getValue() &&
token.getState().getValue()!=TokenState.RUNNING.getValue()){
return ContinueDirection.closeMe();
}
WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl)session;
//1、检验currentActivityInstance和currentProcessInstance的一致性
ProcessInstance oldProcInst = sessionLocalImpl.getCurrentProcessInstance();
ActivityInstance oldActInst = sessionLocalImpl.getCurrentActivityInstance();
RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
PersistenceService persistenceStrategy = ctx.getEngineModule(PersistenceService.class, FpdlConstants.PROCESS_TYPE_FPDL20);
ActivityInstancePersister actInstPersistenceService = persistenceStrategy.getActivityInstancePersister();
ProcessInstancePersister processInstancePersister = persistenceStrategy.getProcessInstancePersister();
if (oldProcInst==null || !oldProcInst.getId().equals(token.getProcessInstanceId())){
ProcessInstance procInst = processInstancePersister.fetch(ProcessInstance.class, token.getProcessInstanceId());
((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(procInst);
}
if (oldActInst==null || !oldActInst.getId().equals(token.getElementInstanceId())){
ActivityInstance actInst = actInstPersistenceService.fetch(ActivityInstance.class, token.getElementInstanceId());
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(actInst);
}
//2、执行业务操作
try{
ActivityInstanceManager activityInstanceMgr = ctx.getEngineModule(ActivityInstanceManager.class, FpdlConstants.PROCESS_TYPE_FPDL20);
ActivityInstance currentActivityInstance = sessionLocalImpl.getCurrentActivityInstance();
int direction = activityInstanceMgr.tryCloseActivityInstance(session, currentActivityInstance,workflowElement);
if (direction == ContinueDirection.WAITING_FOR_CLOSE) {
return ContinueDirection.waitingForClose();// 继续等待;
}
else if (direction==ContinueDirection.START_NEXT_AND_WAITING_FOR_CLOSE){
//计算后续路由
List<PObjectKey> nextPObjectKeys = determineNextPObjectKeys(session,token,workflowElement);
ContinueDirection directionObj = ContinueDirection.startNextAndWaitingForClose();
if (nextPObjectKeys.size()>0){
directionObj.setNextProcessObjectKeys(nextPObjectKeys);
}
return directionObj;
}
else if (direction == ContinueDirection.CLOSE_ME) {
//计算后续路由
List<PObjectKey> nextPObjectKeys = determineNextPObjectKeys(session,token,workflowElement);
ContinueDirection directionObj = ContinueDirection.closeMe();
if (nextPObjectKeys.size()>0){
directionObj.setNextProcessObjectKeys(nextPObjectKeys);
}
return directionObj;
}
else{
//TODO 抛出异常
throw new RuntimeException();
}
}finally{
//2012-03-17 对于continueOn方法,不需要、也不应该在此重新设置olcProcInst和oldActInst
// ((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(oldProcInst);
// ((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(oldActInst);
}
}
//(2012-02-05,Cancel动作容易和handleTermination混淆,意义也不是特别大,暂且注销)
// public CancellationHandler getCancellationHandler(){
// return cancellationHandler;
// }
/* (non-Javadoc)
* TODO 该方法逻辑太复杂,有改善空间,2012-02-05
* @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) {
WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl)session;
RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
PersistenceService persistenceStrategy = ctx.getEngineModule(PersistenceService.class, FpdlConstants.PROCESS_TYPE_FPDL20);
ActivityInstancePersister actInstPersistenceService = persistenceStrategy.getActivityInstancePersister();
TokenPersister tokenPersister = persistenceStrategy.getTokenPersister();
ActivityInstance oldActInst = sessionLocalImpl.getCurrentActivityInstance();
ActivityInstance activityInstance = oldActInst;
if (oldActInst==null || !oldActInst.getId().equals(token.getElementInstanceId())){
activityInstance = actInstPersistenceService.fetch(ActivityInstance.class, token.getElementInstanceId());
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(activityInstance);
}
ActivityInstanceManager activityInstanceMgr = ctx.getEngineModule(ActivityInstanceManager.class, token.getProcessType());
try{
ActivityInstanceState state = ActivityInstanceState.valueOf(token.getState().name());
if (state.getValue()>ActivityInstanceState.DELIMITER.getValue()){
// 停止边上的定时器对应的activityInstance
List<Token> attachedTokens = tokenPersister.findAttachedTokens(token);
if (attachedTokens!=null && attachedTokens.size()>0){
KernelManager kernelManager = ctx.getEngineModule(KernelManager.class, token.getProcessType());
for (Token attachedToken : attachedTokens){
if (attachedToken.getState().getValue()<TokenState.DELIMITER.getValue()){
BookMark bookMark = new BookMark();
bookMark.setToken(attachedToken);
bookMark.setExecutionEntrance(ExecutionEntrance.HANDLE_TERMINATION);//此处只能用HANDLE_TERMINATION,因为HANDLE_FORWORD可能导致TimerStart继续执行。
bookMark.setExtraArg(BookMark.SOURCE_TOKEN, token);
kernelManager.addBookMark(bookMark);
}
}
}
//将调度器中的timmer删除
//对于Activity而言,此段代码意义不大,因为Activity中没有Timer服务,所以暂时注释掉。2012-02-19
/*
ScheduleJobPersister scheduleJobPersister = persistenceStrategy.getScheduleJobPersister();
List<ScheduleJob> scheduleJobs = scheduleJobPersister.findScheduleJob4ActivityInstance(activityInstance.getId());
if (scheduleJobs!=null && scheduleJobs.size()>0){
for (ScheduleJob job : scheduleJobs){
if (job.getState().getValue()<ScheduleJobState.DELIMITER.getValue()){
Scheduler scheduler = ctx.getEngineModule(Scheduler.class, activityInstance.getProcessType());
scheduler.unSchedule(job, ctx);
ScheduleJobState scheduleJobState = ScheduleJobState.COMPLETED;
try{
scheduleJobState = ScheduleJobState.valueOf(state.getValue());
}catch(Exception e){
scheduleJobState = ScheduleJobState.ABORTED;
}
((ScheduleJobImpl)job).setState(scheduleJobState);
scheduleJobPersister.saveOrUpdate(job);
}
}
}
*/
}
activityInstanceMgr.changeActivityInstanceState(session, activityInstance, state, workflowElement);
}finally{
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(oldActInst);
}
}
/*
public void abort(WorkflowSession session,Token token,Object workflowElement){
//1、检验currentActivityInstance和currentProcessInstance的一致性
ProcessInstance oldProcInst = session.getCurrentProcessInstance();
ActivityInstance oldActInst = session.getCurrentActivityInstance();
RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
PersistenceService persistenceService = ctx.getEngineModule(PersistenceService.class, FpdlConstants.PROCESS_TYPE_FPDL20);
ActivityInstancePersister actInstPersistenceService = persistenceService.getActivityInstancePersister();
ProcessInstancePersister processInstancePersister = persistenceService.getProcessInstancePersister();
if (oldProcInst==null || !oldProcInst.getId().equals(token.getProcessInstanceId())){
ProcessInstance procInst = processInstancePersister.find(ProcessInstance.class, token.getProcessInstanceId());
((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(procInst);
}
if (oldActInst==null || !oldActInst.getId().equals(token.getElementInstanceId())){
ActivityInstance actInst = actInstPersistenceService.find(ActivityInstance.class, token.getElementInstanceId());
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(actInst);
}
try{
ActivityInstance thisActInst = session.getCurrentActivityInstance();
// 将Workitem设置为Cancelled状态,
WorkItemPersister workItemPersister = persistenceService.getWorkItemPersister();
List<WorkItem> workItems = workItemPersister.findWorkItemsForActivityInstance(thisActInst.getId());
if (workItems!=null && workItems.size()>0){
for (WorkItem wi : workItems){
if (wi.getState().getValue()<WorkItemState.DELIMITER.getValue()){
((WorkItemImpl)wi).setState(WorkItemState.CANCELLED);
workItemPersister.saveOrUpdate(wi);
}
}
}
//将调度器中的timmer删除
ScheduleJobPersister scheduleJobPersister = persistenceService.getScheduleJobPersister();
List<ScheduleJob> scheduleJobs = scheduleJobPersister.findScheduleJob4ActivityInstance(thisActInst.getId());
if (scheduleJobs!=null && scheduleJobs.size()>0){
for (ScheduleJob job : scheduleJobs){
if (job.getState().getValue()<ScheduleJobState.DELIMITER.getValue()){
Scheduler scheduler = ctx.getEngineModule(Scheduler.class, thisActInst.getProcessType());
scheduler.unSchedule(job, ctx);
((ScheduleJobImpl)job).setState(ScheduleJobState.ABORTED);
scheduleJobPersister.saveOrUpdate(job);
}
}
}
}finally{
((WorkflowSessionLocalImpl)session).setCurrentProcessInstance(oldProcInst);
((WorkflowSessionLocalImpl)session).setCurrentActivityInstance(oldActInst);
}
}
*/
private void initActivityInstanceVariables(VariablePersister variablePersister,
ActivityInstance activityInstance,List<Property> processProperties,Map<String,Object> initVariables){
if (processProperties!=null){
for (Property property:processProperties){
String valueAsStr = property.getInitialValueAsString();
Object value = null;
if (valueAsStr!=null && valueAsStr.trim()!=null){
try {
value = JavaDataTypeConvertor.convertToJavaObject(property.getDataType(), property.getInitialValueAsString(), property.getDataPattern());
} catch (ClassCastException e) {
//TODO 记录流程日志
log.warn("Initialize process instance variable error, subflowId="+activityInstance.getSubProcessId()+", variableName="+property.getName(), e);
} catch (ClassNotFoundException e) {
//TODO 记录流程日志
log.warn("Initialize process instance variable error, subflowId="+activityInstance.getSubProcessId()+", variableName="+property.getName(), e);
}
}
//从initVariables中获取value
if (initVariables!=null){
Object tmpValue = initVariables.remove(property.getName());
if (tmpValue!=null){
try {
value = JavaDataTypeConvertor.dataTypeConvert(property.getDataType(), tmpValue, property.getDataPattern());
} catch (ClassCastException e) {
//TODO 记录流程日志
log.warn("Initialize process instance variable error, subflowId="+activityInstance.getSubProcessId()+", variableName="+property.getName(), e);
} catch (ClassNotFoundException e) {
//TODO 记录流程日志
log.warn("Initialize process instance variable error, subflowId="+activityInstance.getSubProcessId()+", variableName="+property.getName(), e);
}
}
}
createVariable(variablePersister,activityInstance,property.getName(),value,property.getDataType());
}
}
if (initVariables!=null && !initVariables.isEmpty()){
Iterator<String> keySet = initVariables.keySet().iterator();
while (keySet.hasNext()){
String key = keySet.next();
Object value = initVariables.get(key);
createVariable(variablePersister,activityInstance,key,value,null);
}
}
}
private void createVariable(VariablePersister variablePersister,
ActivityInstance activityInstance,String name ,Object value,QName dataType){
VariableImpl v = new VariableImpl();
((AbsVariable)v).setScopeId(activityInstance.getScopeId());
((AbsVariable)v).setName(name);
((AbsVariable)v).setProcessElementId(activityInstance.getProcessElementId());
((AbsVariable)v).setPayload(value);
if (value!=null){
if (value instanceof org.w3c.dom.Document){
if (dataType != null ){
((AbsVariable)v).setDataType(dataType);
}
v.getHeaders().put(Variable.HEADER_KEY_CLASS_NAME, "org.w3c.dom.Document");
}else if (value instanceof org.dom4j.Document){
if (dataType != null ){
((AbsVariable)v).setDataType(dataType);
}
v.getHeaders().put(Variable.HEADER_KEY_CLASS_NAME, "org.dom4j.Document");
}else{
((AbsVariable)v).setDataType(new QName(NameSpaces.JAVA.getUri(),value.getClass().getName()));
}
}
((AbsVariable)v).setProcessId(activityInstance.getProcessId());
((AbsVariable)v).setVersion(activityInstance.getVersion());
((AbsVariable)v).setProcessType(activityInstance.getProcessType());
variablePersister.saveOrUpdate(v);
}
protected List<String> determineNextTransitions(
WorkflowSession session, Token token4Node, Node node){
RuntimeContext runtimeContext = ((WorkflowSessionLocalImpl)session).getRuntimeContext();
BeanFactory beanFactory = runtimeContext.getEngineModule(BeanFactory.class, FpdlConstants.PROCESS_TYPE_FPDL20);
String className = OrSplitEvaluator.class.getName();
SplitEvaluator splitEvaluator = this.splitEvaluatorRegistry.get(className);
if (splitEvaluator==null){
splitEvaluator = (SplitEvaluator)beanFactory.createBean(className);
splitEvaluatorRegistry.put(className, splitEvaluator);
}
return splitEvaluator.determineNextTransitions(session, token4Node, node);
}
}