package com.mossle.bpm.cmd;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.form.StartFormData;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.HistoricActivityInstanceQueryImpl;
import org.activiti.engine.impl.HistoricTaskInstanceQueryImpl;
import org.activiti.engine.impl.Page;
import org.activiti.engine.impl.cmd.GetDeploymentProcessDefinitionCmd;
import org.activiti.engine.impl.cmd.GetStartFormCmd;
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.PvmActivity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 退回任务.
 */
public class RollbackTaskCmd implements Command<Object> {
    /** logger. */
    private static Logger logger = LoggerFactory
            .getLogger(RollbackTaskCmd.class);

    /** task id. */
    private String taskId;

    /** activity id. */
    private String activityId;

    /** user id. */
    private String userId;

    /** use last assignee. */
    private boolean useLastAssignee = false;

    /** 需要处理的多实例节点. */
    private Set<String> multiInstanceExecutionIds = new HashSet<String>();

    /**
     * 指定taskId和跳转到的activityId，自动使用最后的assignee.
     */
    public RollbackTaskCmd(String taskId, String activityId) {
        this.taskId = taskId;
        this.activityId = activityId;
        this.useLastAssignee = true;
    }

    /**
     * 指定taskId和跳转到的activityId, userId.
     */
    public RollbackTaskCmd(String taskId, String activityId, String userId) {
        this.taskId = taskId;
        this.activityId = activityId;
        this.userId = userId;
    }

    /**
     * 退回流程.
     * 
     * @return 0-退回成功 1-流程结束 2-下一结点已经通过,不能退回
     */
    public Integer execute(CommandContext commandContext) {
        // 获得任务
        TaskEntity taskEntity = this.findTask(commandContext);

        // 找到想要回退到的节点
        ActivityImpl targetActivity = this.findTargetActivity(commandContext,
                taskEntity);
        logger.info("rollback to {}", this.activityId);
        logger.info("{}", targetActivity.getProperties());

        String type = (String) targetActivity.getProperty("type");

        if ("userTask".equals(type)) {
            logger.info("rollback to userTask");
            this.rollbackUserTask(commandContext);
        } else if ("startEvent".equals(type)) {
            logger.info("rollback to startEvent");
            this.rollbackStartEvent(commandContext);
        } else {
            throw new IllegalStateException("cannot rollback " + type);
        }

        return 0;
    }

    /**
     * 回退到userTask.
     */
    public Integer rollbackUserTask(CommandContext commandContext) {
        // 获得任务
        TaskEntity taskEntity = this.findTask(commandContext);

        // 找到想要回退到的节点
        ActivityImpl targetActivity = this.findTargetActivity(commandContext,
                taskEntity);

        // 找到想要回退对应的节点历史
        HistoricActivityInstanceEntity historicActivityInstanceEntity = this
                .findTargetHistoricActivity(commandContext, taskEntity,
                        targetActivity);

        // 找到想要回退对应的任务历史
        HistoricTaskInstanceEntity historicTaskInstanceEntity = this
                .findTargetHistoricTask(commandContext, taskEntity,
                        targetActivity);

        logger.info("historic activity instance is : {}",
                historicActivityInstanceEntity.getId());

        Graph graph = new ActivitiHistoryGraphBuilder(
                historicTaskInstanceEntity.getProcessInstanceId()).build();

        Node node = graph.findById(historicActivityInstanceEntity.getId());

        if (!checkCouldRollback(node)) {
            logger.info("cannot rollback {}", taskId);

            return 2;
        }

        if (this.isSameBranch(historicTaskInstanceEntity)) {
            // 如果退回的目标节点的executionId与当前task的executionId一样，说明是同一个分支
            // 只删除当前分支的task
            TaskEntity targetTaskEntity = Context.getCommandContext()
                    .getTaskEntityManager().findTaskById(this.taskId);
            this.deleteActiveTask(targetTaskEntity);
        } else {
            // 否则认为是从分支跳回主干
            // 删除所有活动中的task
            this.deleteActiveTasks(historicTaskInstanceEntity
                    .getProcessInstanceId());

            // 获得期望退回的节点后面的所有节点历史
            List<String> historyNodeIds = new ArrayList<String>();
            collectNodes(node, historyNodeIds);
            this.deleteHistoryActivities(historyNodeIds);
        }

        // 处理多实例
        this.processMultiInstance();

        // 恢复期望退回的任务和历史
        this.processHistoryTask(commandContext, taskEntity,
                historicTaskInstanceEntity, historicActivityInstanceEntity);

        logger.info("activiti is rollback {}",
                historicTaskInstanceEntity.getName());

        return 0;
    }

    /**
     * 回退到startEvent.
     */
    public Integer rollbackStartEvent(CommandContext commandContext) {
        // 获得任务
        TaskEntity taskEntity = this.findTask(commandContext);

        // 找到想要回退到的节点
        ActivityImpl targetActivity = this.findTargetActivity(commandContext,
                taskEntity);

        if (taskEntity.getExecutionId().equals(
                taskEntity.getProcessInstanceId())) {
            // 如果退回的目标节点的executionId与当前task的executionId一样，说明是同一个分支
            // 只删除当前分支的task
            TaskEntity targetTaskEntity = Context.getCommandContext()
                    .getTaskEntityManager().findTaskById(this.taskId);
            this.deleteActiveTask(targetTaskEntity);
        } else {
            // 否则认为是从分支跳回主干
            // 删除所有活动中的task
            this.deleteActiveTasks(taskEntity.getProcessInstanceId());
        }

        // 把流程指向任务对应的节点
        ExecutionEntity executionEntity = Context.getCommandContext()
                .getExecutionEntityManager()
                .findExecutionById(taskEntity.getExecutionId());
        executionEntity.setActivity(targetActivity);

        // 创建HistoricActivityInstance
        Context.getCommandContext().getHistoryManager()
                .recordActivityStart(executionEntity);

        String processDefinitionId = taskEntity.getProcessDefinitionId();
        GetStartFormCmd getStartFormCmd = new GetStartFormCmd(
                processDefinitionId);
        StartFormData startFormData = getStartFormCmd.execute(commandContext);

        try {
            logger.info("{}", targetActivity.getProperties());

            // humanTask
            HumanTaskConnector humanTaskConnector = ApplicationContextHelper
                    .getBean(HumanTaskConnector.class);
            HumanTaskDTO humanTaskDto = humanTaskConnector.createHumanTask();
            humanTaskDto.setName((String) targetActivity.getProperty("name"));
            humanTaskDto.setDescription((String) targetActivity
                    .getProperty("description"));
            humanTaskDto.setCode(targetActivity.getId());
            humanTaskDto.setAssignee(this.userId);
            humanTaskDto.setOwner(null);
            humanTaskDto.setDelegateStatus("none");
            humanTaskDto.setPriority(50);
            humanTaskDto.setCreateTime(new Date());
            humanTaskDto.setDuration(null);
            humanTaskDto.setSuspendStatus("none");
            humanTaskDto.setCategory("startEvent");
            humanTaskDto.setForm(startFormData.getFormKey());
            humanTaskDto.setTaskId(null);
            humanTaskDto.setExecutionId(taskEntity.getExecutionId());
            humanTaskDto
                    .setProcessInstanceId(taskEntity.getProcessInstanceId());
            humanTaskDto.setProcessDefinitionId(taskEntity
                    .getProcessDefinitionId());
            humanTaskDto.setTenantId(taskEntity.getTenantId());
            humanTaskDto.setStatus("active");
            humanTaskDto = humanTaskConnector.saveHumanTask(humanTaskDto);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }

        // 处理多实例
        this.processMultiInstance();

        return 0;
    }

    /**
     * 获得当前任务.
     */
    public TaskEntity findTask(CommandContext commandContext) {
        TaskEntity taskEntity = commandContext.getTaskEntityManager()
                .findTaskById(taskId);

        return taskEntity;
    }

    /**
     * 查找回退的目的节点.
     */
    public ActivityImpl findTargetActivity(CommandContext commandContext,
            TaskEntity taskEntity) {
        if (activityId == null) {
            String historyTaskId = this.findNearestUserTask(commandContext);
            HistoricTaskInstanceEntity historicTaskInstanceEntity = commandContext
                    .getHistoricTaskInstanceEntityManager()
                    .findHistoricTaskInstanceById(historyTaskId);
            this.activityId = historicTaskInstanceEntity.getTaskDefinitionKey();
        }

        String processDefinitionId = taskEntity.getProcessDefinitionId();
        ProcessDefinitionEntity processDefinitionEntity = new GetDeploymentProcessDefinitionCmd(
                processDefinitionId).execute(commandContext);

        return processDefinitionEntity.findActivity(activityId);
    }

    /**
     * 找到想要回退对应的节点历史.
     */
    public HistoricActivityInstanceEntity findTargetHistoricActivity(
            CommandContext commandContext, TaskEntity taskEntity,
            ActivityImpl activityImpl) {
        HistoricActivityInstanceQueryImpl historicActivityInstanceQueryImpl = new HistoricActivityInstanceQueryImpl();
        historicActivityInstanceQueryImpl.activityId(activityImpl.getId());
        historicActivityInstanceQueryImpl.processInstanceId(taskEntity
                .getProcessInstanceId());
        historicActivityInstanceQueryImpl
                .orderByHistoricActivityInstanceEndTime().desc();

        HistoricActivityInstanceEntity historicActivityInstanceEntity = (HistoricActivityInstanceEntity) commandContext
                .getHistoricActivityInstanceEntityManager()
                .findHistoricActivityInstancesByQueryCriteria(
                        historicActivityInstanceQueryImpl, new Page(0, 1))
                .get(0);

        return historicActivityInstanceEntity;
    }

    /**
     * 找到想要回退对应的任务历史.
     */
    public HistoricTaskInstanceEntity findTargetHistoricTask(
            CommandContext commandContext, TaskEntity taskEntity,
            ActivityImpl activityImpl) {
        HistoricTaskInstanceQueryImpl historicTaskInstanceQueryImpl = new HistoricTaskInstanceQueryImpl();
        historicTaskInstanceQueryImpl.taskDefinitionKey(activityImpl.getId());
        historicTaskInstanceQueryImpl.processInstanceId(taskEntity
                .getProcessInstanceId());
        historicTaskInstanceQueryImpl.setFirstResult(0);
        historicTaskInstanceQueryImpl.setMaxResults(1);
        historicTaskInstanceQueryImpl.orderByTaskCreateTime().desc();

        HistoricTaskInstanceEntity historicTaskInstanceEntity = (HistoricTaskInstanceEntity) commandContext
                .getHistoricTaskInstanceEntityManager()
                .findHistoricTaskInstancesByQueryCriteria(
                        historicTaskInstanceQueryImpl).get(0);

        return historicTaskInstanceEntity;
    }

    /**
     * 判断想要回退的目标节点和当前节点是否在一个分支上.
     */
    public boolean isSameBranch(
            HistoricTaskInstanceEntity historicTaskInstanceEntity) {
        TaskEntity taskEntity = Context.getCommandContext()
                .getTaskEntityManager().findTaskById(taskId);

        return taskEntity.getExecutionId().equals(
                historicTaskInstanceEntity.getExecutionId());
    }

    /**
     * 查找离当前节点最近的上一个userTask.
     */
    public String findNearestUserTask(CommandContext commandContext) {
        TaskEntity taskEntity = commandContext.getTaskEntityManager()
                .findTaskById(taskId);

        if (taskEntity == null) {
            logger.debug("cannot find task : {}", taskId);

            return null;
        }

        Graph graph = new ActivitiHistoryGraphBuilder(
                taskEntity.getProcessInstanceId()).build();
        JdbcTemplate jdbcTemplate = ApplicationContextHelper
                .getBean(JdbcTemplate.class);
        String historicActivityInstanceId = jdbcTemplate.queryForObject(
                "SELECT ID_ FROM ACT_HI_ACTINST WHERE TASK_ID_=?",
                String.class, taskId);
        Node node = graph.findById(historicActivityInstanceId);

        String previousHistoricActivityInstanceId = this.findIncomingNode(
                graph, node);

        if (previousHistoricActivityInstanceId == null) {
            logger.debug(
                    "cannot find previous historic activity instance : {}",
                    taskEntity);

            return null;
        }

        return jdbcTemplate.queryForObject(
                "SELECT TASK_ID_ FROM ACT_HI_ACTINST WHERE ID_=?",
                String.class, previousHistoricActivityInstanceId);
    }

    /**
     * 查找进入的连线.
     */
    public String findIncomingNode(Graph graph, Node node) {
        for (Edge edge : graph.getEdges()) {
            Node src = edge.getSrc();
            Node dest = edge.getDest();
            String srcType = src.getType();

            if (!dest.getId().equals(node.getId())) {
                continue;
            }

            if ("userTask".equals(srcType)) {
                boolean isSkip = isSkipActivity(src.getId());

                if (isSkip) {
                    return this.findIncomingNode(graph, src);
                } else {
                    return src.getId();
                }
            } else if (srcType.endsWith("Gateway")) {
                return this.findIncomingNode(graph, src);
            } else {
                logger.info("cannot rollback, previous node is not userTask : "
                        + src.getId() + " " + srcType + "(" + src.getName()
                        + ")");

                return null;
            }
        }

        logger.info("cannot rollback, this : " + node.getId() + " "
                + node.getType() + "(" + node.getName() + ")");

        return null;
    }

    /**
     * 查询历史节点.
     */
    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 checkCouldRollback(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 checkCouldRollback(dest);
                    } else {
                        // logger.info("cannot rollback, " + type + "("
                        // + dest.getName() + ") is complete.");
                        // return false;
                        return true;
                    }
                }
            } else if (type.endsWith("Gateway")) {
                return checkCouldRollback(dest);
            } else {
                logger.info("cannot rollback, " + type + "(" + dest.getName()
                        + ") is complete.");

                return false;
            }
        }

        return true;
    }

    /**
     * 删除活动状态任务.
     */
    public void deleteActiveTasks(String processInstanceId) {
        List<TaskEntity> taskEntities = Context.getCommandContext()
                .getTaskEntityManager()
                .findTasksByProcessInstanceId(processInstanceId);

        for (TaskEntity taskEntity : taskEntities) {
            this.deleteActiveTask(taskEntity);
        }
    }

    /**
     * 遍历节点.
     */
    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());
            collectNodes(dest, historyNodeIds);
        }
    }

    public void deleteHistoryActivities(List<String> historyNodeIds) {
        /*
         * JdbcTemplate jdbcTemplate = ApplicationContextHelper .getBean(JdbcTemplate.class);
         * logger.info("historyNodeIds : {}", historyNodeIds);
         * 
         * for (String id : historyNodeIds) { jdbcTemplate.update("delete from ACT_HI_ACTINST where id_=?", id); }
         */
    }

    /**
     * 根据任务历史，创建待办任务.
     */
    public void processHistoryTask(CommandContext commandContext,
            TaskEntity taskEntity,
            HistoricTaskInstanceEntity historicTaskInstanceEntity,
            HistoricActivityInstanceEntity historicActivityInstanceEntity) {
        if (this.userId == null) {
            if (this.useLastAssignee) {
                this.userId = historicTaskInstanceEntity.getAssignee();
            } else {
                String processDefinitionId = taskEntity
                        .getProcessDefinitionId();
                ProcessDefinitionEntity processDefinitionEntity = new GetDeploymentProcessDefinitionCmd(
                        processDefinitionId).execute(commandContext);
                TaskDefinition taskDefinition = processDefinitionEntity
                        .getTaskDefinitions().get(
                                historicTaskInstanceEntity
                                        .getTaskDefinitionKey());

                if (taskDefinition == null) {
                    String message = "cannot find taskDefinition : "
                            + historicTaskInstanceEntity.getTaskDefinitionKey();
                    logger.info(message);
                    throw new IllegalStateException(message);
                }

                if (taskDefinition.getAssigneeExpression() != null) {
                    logger.info("assignee expression is null : {}",
                            taskDefinition.getKey());
                    this.userId = (String) taskDefinition
                            .getAssigneeExpression().getValue(taskEntity);
                }
            }
        }

        /*
         * 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(userId);
        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.setExecutionId(historicTaskInstanceEntity.getExecutionId());
        task.setDescriptionWithoutCascade(historicTaskInstanceEntity
                .getDescription());
        task.setTenantId(historicTaskInstanceEntity.getTenantId());

        Context.getCommandContext().getTaskEntityManager().insert(task);

        // 把流程指向任务对应的节点
        ExecutionEntity executionEntity = Context.getCommandContext()
                .getExecutionEntityManager()
                .findExecutionById(historicTaskInstanceEntity.getExecutionId());
        executionEntity
                .setActivity(getActivity(historicActivityInstanceEntity));

        // 创建HistoricActivityInstance
        Context.getCommandContext().getHistoryManager()
                .recordActivityStart(executionEntity);

        // 创建HistoricTaskInstance
        Context.getCommandContext().getHistoryManager()
                .recordTaskCreated(task, executionEntity);
        Context.getCommandContext().getHistoryManager().recordTaskId(task);
        // 更新ACT_HI_ACTIVITY里的assignee字段
        Context.getCommandContext().getHistoryManager()
                .recordTaskAssignment(task);

        try {
            // humanTask
            this.createHumanTask(task, historicTaskInstanceEntity);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
    }

    /**
     * 获得历史节点对应的节点信息.
     */
    public ActivityImpl getActivity(
            HistoricActivityInstanceEntity historicActivityInstanceEntity) {
        ProcessDefinitionEntity processDefinitionEntity = new GetDeploymentProcessDefinitionCmd(
                historicActivityInstanceEntity.getProcessDefinitionId())
                .execute(Context.getCommandContext());

        return processDefinitionEntity
                .findActivity(historicActivityInstanceEntity.getActivityId());
    }

    /**
     * 删除未完成任务.
     */
    public void deleteActiveTask(TaskEntity taskEntity) {
        ProcessDefinitionEntity processDefinitionEntity = new GetDeploymentProcessDefinitionCmd(
                taskEntity.getProcessDefinitionId()).execute(Context
                .getCommandContext());

        ActivityImpl activityImpl = processDefinitionEntity
                .findActivity(taskEntity.getTaskDefinitionKey());

        if (this.isMultiInstance(activityImpl)) {
            logger.info("{} is multiInstance", taskEntity.getId());
            this.multiInstanceExecutionIds.add(taskEntity.getExecution()
                    .getParent().getId());
            logger.info("append : {}", taskEntity.getExecution().getParent()
                    .getId());
        }

        // TaskEntity taskEntity = Context.getCommandContext()
        // .getTaskEntityManager().findTaskById(this.taskId);
        Context.getCommandContext().getTaskEntityManager()
                .deleteTask(taskEntity, "驳回", false);

        JdbcTemplate jdbcTemplate = ApplicationContextHelper
                .getBean(JdbcTemplate.class);
        List<Map<String, Object>> list = jdbcTemplate
                .queryForList(
                        "SELECT * FROM ACT_HI_ACTINST WHERE TASK_ID_=? AND END_TIME_ IS NULL",
                        taskId);
        Date now = new Date();

        for (Map<String, Object> map : list) {
            Date startTime = (Date) map.get("START_TIME_");
            long duration = now.getTime() - startTime.getTime();
            jdbcTemplate
                    .update("UPDATE ACT_HI_ACTINST SET END_TIME_=?,DURATION_=? WHERE ID_=?",
                            now, duration, map.get("ID_"));
        }

        // 处理humanTask
        HumanTaskConnector humanTaskConnector = ApplicationContextHelper
                .getBean(HumanTaskConnector.class);
        HumanTaskDTO humanTaskDto = humanTaskConnector
                .findHumanTaskByTaskId(this.taskId);
        humanTaskDto.setCompleteTime(new Date());
        humanTaskDto.setStatus("rollback");
        humanTaskConnector.saveHumanTask(humanTaskDto);
    }

    /**
     * 判断跳过节点.
     */
    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);
    }

    /**
     * 创建humanTask.
     */
    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;
    }

    /**
     * 判断是否会签.
     */
    public boolean isMultiInstance(PvmActivity pvmActivity) {
        return pvmActivity.getProperty("multiInstance") != null;
    }

    /**
     * 处理多实例.
     */
    public void processMultiInstance() {
        logger.info("multiInstanceExecutionIds : {}", multiInstanceExecutionIds);

        for (String executionId : multiInstanceExecutionIds) {
            ExecutionEntity parent = Context.getCommandContext()
                    .getExecutionEntityManager().findExecutionById(executionId);
            List<ExecutionEntity> children = Context.getCommandContext()
                    .getExecutionEntityManager()
                    .findChildExecutionsByParentExecutionId(parent.getId());

            for (ExecutionEntity executionEntity : children) {
                executionEntity.remove();
            }

            parent.remove();
        }
    }
}
