package com.mossle.bpm.cmd;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.mossle.api.humantask.HumanTaskConnector;
import com.mossle.api.humantask.HumanTaskConstants;
import com.mossle.api.humantask.HumanTaskDTO;
import com.mossle.bpm.graph.ActivitiHistoryGraphBuilder;
import com.mossle.bpm.graph.Edge;
import com.mossle.bpm.graph.Graph;
import com.mossle.bpm.graph.Node;
import com.mossle.bpm.support.HumanTaskBuilder;
import com.mossle.core.spring.ApplicationContextHelper;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.HistoricActivityInstanceQueryImpl;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.cmd.GetDeploymentProcessDefinitionCmd;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.HistoricActivityInstanceEntity;
import org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
/**
* 撤销任务.
*/
public class WithdrawTaskCmd implements Command<Integer> {
private static Logger logger = LoggerFactory
.getLogger(WithdrawTaskCmd.class);
private String historyTaskId;
/**
* 这个historyTaskId是已经完成的一个任务的id.
*/
public WithdrawTaskCmd(String historyTaskId) {
this.historyTaskId = historyTaskId;
}
/**
* 撤销流程.
*
* @return 0-撤销成功 1-流程结束 2-下一结点已经通过,不能撤销
*/
public Integer execute(CommandContext commandContext) {
// 获得历史任务
HistoricTaskInstanceEntity historicTaskInstanceEntity = Context
.getCommandContext().getHistoricTaskInstanceEntityManager()
.findHistoricTaskInstanceById(historyTaskId);
// 获得历史节点
HistoricActivityInstanceEntity historicActivityInstanceEntity = getHistoricActivityInstanceEntity(historyTaskId);
Graph graph = new ActivitiHistoryGraphBuilder(
historicTaskInstanceEntity.getProcessInstanceId()).build();
Node node = graph.findById(historicActivityInstanceEntity.getId());
if (!checkCouldWithdraw(node)) {
logger.info("cannot withdraw {}", historyTaskId);
return 2;
}
// 删除所有活动中的task
this.deleteActiveTasks(historicTaskInstanceEntity
.getProcessInstanceId());
// 获得期望撤销的节点后面的所有节点历史
List<String> historyNodeIds = new ArrayList<String>();
this.collectNodes(node, historyNodeIds);
this.deleteHistoryActivities(historyNodeIds);
// 恢复期望撤销的任务和历史
this.processHistoryTask(historicTaskInstanceEntity,
historicActivityInstanceEntity);
logger.info("activiti is withdraw {}",
historicTaskInstanceEntity.getName());
return 0;
}
public HistoricActivityInstanceEntity getHistoricActivityInstanceEntity(
String historyTaskId) {
logger.info("historyTaskId : {}", historyTaskId);
JdbcTemplate jdbcTemplate = ApplicationContextHelper
.getBean(JdbcTemplate.class);
String historicActivityInstanceId = jdbcTemplate.queryForObject(
"select id_ from ACT_HI_ACTINST where task_id_=?",
String.class, historyTaskId);
logger.info("historicActivityInstanceId : {}",
historicActivityInstanceId);
HistoricActivityInstanceQueryImpl historicActivityInstanceQueryImpl = new HistoricActivityInstanceQueryImpl();
historicActivityInstanceQueryImpl
.activityInstanceId(historicActivityInstanceId);
HistoricActivityInstanceEntity historicActivityInstanceEntity = (HistoricActivityInstanceEntity) Context
.getCommandContext()
.getHistoricActivityInstanceEntityManager()
.findHistoricActivityInstancesByQueryCriteria(
historicActivityInstanceQueryImpl, new Page(0, 1))
.get(0);
return historicActivityInstanceEntity;
}
public boolean checkCouldWithdraw(Node node) {
// TODO: 如果是catchEvent,也应该可以撤销,到时候再说
for (Edge edge : node.getOutgoingEdges()) {
Node dest = edge.getDest();
String type = dest.getType();
if ("userTask".equals(type)) {
if (!dest.isActive()) {
boolean isSkip = isSkipActivity(dest.getId());
if (isSkip) {
return checkCouldWithdraw(dest);
} else {
logger.info("cannot withdraw, " + type + "("
+ dest.getName() + ") is complete.");
return false;
}
}
} else if (type.endsWith("Gateway")) {
return checkCouldWithdraw(dest);
} else {
logger.info("cannot withdraw, " + type + "(" + dest.getName()
+ ") is complete.");
return false;
}
}
return true;
}
/**
* 删除未完成任务.
*/
public void deleteActiveTasks(String processInstanceId) {
// humantask
HumanTaskConnector humanTaskConnector = ApplicationContextHelper
.getBean(HumanTaskConnector.class);
humanTaskConnector
.removeHumanTaskByProcessInstanceId(processInstanceId);
Context.getCommandContext().getTaskEntityManager()
.deleteTasksByProcessInstanceId(processInstanceId, null, true);
}
public void collectNodes(Node node, List<String> historyNodeIds) {
logger.info("node : {}, {}, {}", node.getId(), node.getType(),
node.getName());
for (Edge edge : node.getOutgoingEdges()) {
logger.info("edge : {}", edge.getName());
Node dest = edge.getDest();
historyNodeIds.add(dest.getId());
this.collectNodes(dest, historyNodeIds);
}
}
/**
* 删除历史节点.
*/
public void deleteHistoryActivities(List<String> historyNodeIds) {
JdbcTemplate jdbcTemplate = ApplicationContextHelper
.getBean(JdbcTemplate.class);
logger.info("historyNodeIds : {}", historyNodeIds);
for (String id : historyNodeIds) {
String taskId = jdbcTemplate.queryForObject(
"select task_id_ from ACT_HI_ACTINST where id_=?",
String.class, id);
if (taskId != null) {
Context.getCommandContext()
.getHistoricTaskInstanceEntityManager()
.deleteHistoricTaskInstanceById(taskId);
}
jdbcTemplate.update("delete from ACT_HI_ACTINST where id_=?", id);
}
}
public void processHistoryTask(
HistoricTaskInstanceEntity historicTaskInstanceEntity,
HistoricActivityInstanceEntity historicActivityInstanceEntity) {
historicTaskInstanceEntity.setEndTime(null);
historicTaskInstanceEntity.setDurationInMillis(null);
historicActivityInstanceEntity.setEndTime(null);
historicActivityInstanceEntity.setDurationInMillis(null);
TaskEntity task = TaskEntity.create(new Date());
task.setProcessDefinitionId(historicTaskInstanceEntity
.getProcessDefinitionId());
task.setId(historicTaskInstanceEntity.getId());
task.setAssigneeWithoutCascade(historicTaskInstanceEntity.getAssignee());
task.setParentTaskIdWithoutCascade(historicTaskInstanceEntity
.getParentTaskId());
task.setNameWithoutCascade(historicTaskInstanceEntity.getName());
task.setTaskDefinitionKey(historicTaskInstanceEntity
.getTaskDefinitionKey());
task.setExecutionId(historicTaskInstanceEntity.getExecutionId());
task.setPriority(historicTaskInstanceEntity.getPriority());
task.setProcessInstanceId(historicTaskInstanceEntity
.getProcessInstanceId());
task.setDescriptionWithoutCascade(historicTaskInstanceEntity
.getDescription());
task.setTenantId(historicTaskInstanceEntity.getTenantId());
Context.getCommandContext().getTaskEntityManager().insert(task);
try {
HumanTaskConnector humanTaskConnector = ApplicationContextHelper
.getBean(HumanTaskConnector.class);
// humantask
humanTaskConnector
.removeHumanTaskByTaskId(historicTaskInstanceEntity.getId());
this.createHumanTask(task, historicTaskInstanceEntity);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
ExecutionEntity executionEntity = Context.getCommandContext()
.getExecutionEntityManager()
.findExecutionById(historicTaskInstanceEntity.getExecutionId());
executionEntity
.setActivity(getActivity(historicActivityInstanceEntity));
}
public ActivityImpl getActivity(
HistoricActivityInstanceEntity historicActivityInstanceEntity) {
ProcessDefinitionEntity processDefinitionEntity = new GetDeploymentProcessDefinitionCmd(
historicActivityInstanceEntity.getProcessDefinitionId())
.execute(Context.getCommandContext());
return processDefinitionEntity
.findActivity(historicActivityInstanceEntity.getActivityId());
}
public boolean isSkipActivity(String historyActivityId) {
JdbcTemplate jdbcTemplate = ApplicationContextHelper
.getBean(JdbcTemplate.class);
String historyTaskId = jdbcTemplate.queryForObject(
"select task_id_ from ACT_HI_ACTINST where id_=?",
String.class, historyActivityId);
HistoricTaskInstanceEntity historicTaskInstanceEntity = Context
.getCommandContext().getHistoricTaskInstanceEntityManager()
.findHistoricTaskInstanceById(historyTaskId);
String deleteReason = historicTaskInstanceEntity.getDeleteReason();
return "跳过".equals(deleteReason);
}
public HumanTaskDTO createHumanTask(DelegateTask delegateTask,
HistoricTaskInstanceEntity historicTaskInstanceEntity)
throws Exception {
HumanTaskConnector humanTaskConnector = ApplicationContextHelper
.getBean(HumanTaskConnector.class);
HumanTaskDTO humanTaskDto = new HumanTaskBuilder().setDelegateTask(
delegateTask).build();
if ("发起流程".equals(historicTaskInstanceEntity.getDeleteReason())) {
humanTaskDto.setCatalog(HumanTaskConstants.CATALOG_START);
}
HistoricProcessInstance historicProcessInstance = Context
.getCommandContext()
.getHistoricProcessInstanceEntityManager()
.findHistoricProcessInstance(
delegateTask.getProcessInstanceId());
humanTaskDto
.setProcessStarter(historicProcessInstance.getStartUserId());
humanTaskDto = humanTaskConnector.saveHumanTask(humanTaskDto);
return humanTaskDto;
}
}