/*
* Copyright 2010-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.starflow.engine.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.TransactionStatus;
import org.springframework.util.Assert;
import com.googlecode.starflow.engine.ProcessEngine;
import com.googlecode.starflow.engine.ProcessEngineException;
import com.googlecode.starflow.engine.StarFlowState;
import com.googlecode.starflow.engine.core.ActivityTypeFactory;
import com.googlecode.starflow.engine.core.Constants;
import com.googlecode.starflow.engine.core.activity.ActivityType;
import com.googlecode.starflow.engine.event.ActivityCreateEvent;
import com.googlecode.starflow.engine.event.ActivityStartEvent;
import com.googlecode.starflow.engine.event.support.EventUtil;
import com.googlecode.starflow.engine.model.ActivityInst;
import com.googlecode.starflow.engine.model.ProcessDefine;
import com.googlecode.starflow.engine.model.ProcessInstance;
import com.googlecode.starflow.engine.model.TransCtrl;
import com.googlecode.starflow.engine.model.elements.ActivityElement;
import com.googlecode.starflow.engine.repository.IActivityInstRepository;
import com.googlecode.starflow.engine.repository.IProcessDefineRepository;
import com.googlecode.starflow.engine.repository.IProcessInstanceRepository;
import com.googlecode.starflow.engine.service.IActivityInstService;
import com.googlecode.starflow.engine.transaction.TransactionCallbackWithoutResult;
import com.googlecode.starflow.engine.transaction.TransactionTemplate;
/**
*
* @author libinsong1204@gmail.com
* @version 1.0
*/
public class ActivityInstService implements IActivityInstService {
final private Logger logger = LoggerFactory.getLogger(ActivityInstService.class);
final private ProcessEngine processEngine;
private final IProcessDefineRepository procDefRep;
private final IProcessInstanceRepository procInstRep;
private final IActivityInstRepository actInstRep;
private TransactionTemplate transactionTemplate;
public ActivityInstService(ProcessEngine processEngine) {
Assert.notNull(processEngine);
this.processEngine = processEngine;
this.procDefRep = this.processEngine.getApplicationContext().getBean(IProcessDefineRepository.class);
this.procInstRep = this.processEngine.getApplicationContext().getBean(IProcessInstanceRepository.class);
this.actInstRep = this.processEngine.getApplicationContext().getBean(IActivityInstRepository.class);
this.transactionTemplate = processEngine.getTransactionTemplate();
}
/* (non-Javadoc)
* @see com.starit.wf.engine.domain.service.IActivityInstService#finishActivity(long)
*/
public void finishActivity(long activityInstId) {
final ActivityInst activityInst = this.actInstRep.findActivityInst(activityInstId);
//判断环节是否处于运行状态,才可完成该工作项
if(StarFlowState.ACT_INST_RUNING != activityInst.getCurrentState())
throw new ProcessEngineException("当前环节(activityInstId="+activityInst.getActivityInstId()+")不处于状态,"+
"无法完成环节的运行!");
final ProcessInstance processInstance = this.procInstRep.findProcessInstance(activityInst.getProcessInstId());
final ProcessDefine processDefine = this.procDefRep.findProcessDefine(processInstance.getProcessDefId());
final ActivityElement activityElement = processDefine.getProcessElement().getActivitys().get(activityInst.getActivityDefId());
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
//发布环节结束事件
ActivityStartEvent event = new ActivityStartEvent(processEngine);
event.setProcessInstance(processInstance);
event.setPreActivityXml(activityElement);
EventUtil.publishActivityFinishEvent(event, processInstance, activityInst);
}
});
}
public void startActivityInst(long processInstId, String activityDefId) {
final ProcessInstance processInstance = procInstRep.findProcessInstance(processInstId);
if(StarFlowState.PROCESS_INST_RUNNING != processInstance.getCurrentState())
throw new ProcessEngineException("流程不处于运行状态,不能重启环节!");
final ProcessDefine processDefine = this.procDefRep.findProcessDefine(processInstance.getProcessDefId());
final ActivityElement activityXml = processDefine.getProcessElement().getActivitys().get(activityDefId);
if(activityXml == null)
throw new ProcessEngineException("指定启动环节【{}】不存在" + activityDefId);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
String actType = activityXml.getType();
ActivityType type = ActivityTypeFactory.buildActivityType(actType);
//创建环节
ActivityCreateEvent event = new ActivityCreateEvent(processEngine);
event.setProcessInstance(processInstance);
ActivityInst activityInst = type.createActivity(event, activityXml);
//启动环节
EventUtil.publishActivityStartEvent(event, activityInst, activityXml);
}
});
}
/* (non-Javadoc)
* @see com.starit.wf.engine.domain.service.IActivityInstService#terminateActivity(long)
*/
public void terminateActivity(final long activityInstId) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
ActivityInst activityInst = actInstRep.findActivityInst(activityInstId);
ProcessInstance processInstance = procInstRep.findProcessInstance(activityInst.getProcessInstId());
EventUtil.publishActivityTerminalEvent(processEngine, processInstance, activityInst);
}
});
}
/* (non-Javadoc)
* @see com.starit.wf.engine.domain.service.IActivityInstService#restartActivity(long)
*/
public void restartActivity(long processInstId, long activityInstId) {
ProcessInstance processInstance = procInstRep.findProcessInstance(processInstId);
if(StarFlowState.PROCESS_INST_RUNNING != processInstance.getCurrentState())
throw new ProcessEngineException("流程不处于运行状态,不能重启环节!");
ActivityInst activityInst = actInstRep.findActivityInst(activityInstId);
if(activityInst == null || activityInst.getCurrentState() == StarFlowState.ACT_INST_RUNING
|| activityInst.getCurrentState() == StarFlowState.ACT_INST_WAITING
|| activityInst.getCurrentState() == StarFlowState.ACT_APP_EXCEPTION) {
throw new ProcessEngineException("环节只有处在完成、终止、应用异常状态,才可以重启环节");
}
// if(!Constants.ACT_TYPE_MANUL.equals(activityInst.getActivityType())) {
// throw new ProcessEngineException("只有人工环节才可以重启环节,当前环节类型为:"+activityInst.getActivityType());
// }
ProcessDefine processDefine = this.procDefRep.findProcessDefine(processInstance.getProcessDefId());
ActivityElement activityElement = processDefine.getProcessElement().getActivitys().get(activityInst.getActivityDefId());
EventUtil.publishActivityRestartEvent(processEngine, processInstance, activityInst, activityElement);
}
public void activateActivity(final long activityInstId) {
final ActivityInst activityInst = actInstRep.findActivityInst(activityInstId);
final ProcessInstance processInstance = procInstRep.findProcessInstance(activityInst.getProcessInstId());
final ProcessDefine processDefine = this.procDefRep.findProcessDefine(processInstance.getProcessDefId());
final ActivityElement activityElement = processDefine.getProcessElement().getActivitys().get(activityInst.getActivityDefId());
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
//判断环节是否处于运行状态,才可完成该工作项
if(StarFlowState.ACT_INST_WAITING != activityInst.getCurrentState())
throw new ProcessEngineException("当前环节(activityInstId="+activityInst.getActivityInstId()+")不处于待激活状态,"+
"无法激活该环节!");
//创建环节
ActivityCreateEvent event = new ActivityCreateEvent(processEngine);
event.setProcessInstance(processInstance);
//启动环节
EventUtil.publishActivityStartEvent(event, activityInst, activityElement);
if(logger.isDebugEnabled())
logger.debug("环节【{}】人工激活", activityInst.getActivityInstName());
}
});
}
/* (non-Javadoc)
* @see com.starit.wf.engine.domain.service.IActivityInstService#rollbackToActivityFroRecentManual(long)
*/
public void rollbackToActivityFroRecentManual(final long currentActInstID) {
final ActivityInst activityInst = this.actInstRep.findActivityInst(currentActInstID);
//判断环节是否处于运行状态,才可执行回退
if(StarFlowState.ACT_INST_RUNING != activityInst.getCurrentState())
throw new ProcessEngineException("当前环节(activityInstId="+activityInst.getActivityInstId()+")不处于运行状态,"+
"不能执行回退。");
final ProcessInstance processInstance = this.procInstRep.findProcessInstance(activityInst.getProcessInstId());
List<TransCtrl> trans = this.actInstRep.findTransCtrls(activityInst.getProcessInstId());
String recentActDefId = null;
String destActId = activityInst.getActivityDefId();
for(TransCtrl transCtrl : trans) {
if(transCtrl.getDestActDefId().equalsIgnoreCase(destActId) //如果不是人工环节,继续向前循环
&& !Constants.ACT_TYPE_MANUL.equalsIgnoreCase(transCtrl.getSrcActType())) {
destActId = transCtrl.getSrcActDefId();
} else if(transCtrl.getDestActDefId().equalsIgnoreCase(destActId)
&& Constants.ACT_TYPE_MANUL.equalsIgnoreCase(transCtrl.getSrcActType())) {
recentActDefId = transCtrl.getSrcActDefId();
break;
}
}
if(recentActDefId == null)
throw new ProcessEngineException("最近一个人工环节没有找到,无法回退");
rollBackExecute(currentActInstID, activityInst, processInstance,
recentActDefId);
}
/* (non-Javadoc)
* @see com.starit.wf.engine.domain.service.IActivityInstService#rollbackToActivityFroOneStep(long)
*/
public void rollbackToActivityFroOneStep(long currentActInstID) {
throw new UnsupportedOperationException("单步回退功能没有实现");
}
private void rollBackExecute(final long currentActInstID,
final ActivityInst activityInst,
final ProcessInstance processInstance, final String recentActDefId) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
//先终止当前环节
terminateActivity(currentActInstID);
List<String> actDefIds = new ArrayList<String>();
actDefIds.add(recentActDefId);
//启动目标环节
EventUtil.publishActivityRollBackEvent(processEngine, processInstance, activityInst, actDefIds);
}
});
}
public List<TransCtrl> findTransCtrls(long processInstId) {
return actInstRep.findTransCtrls(processInstId);
}
public List<ActivityInst> findWaitingAndTerminateAndRunningActivityInst(long processInstId) {
return actInstRep.findWaitingAndTerminateAndRunningActivityInst(processInstId);
}
}