WipWorkflowQueryManagerImpl.java

package com.mycim.server.wip.manager.impl;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalStateException;
import com.mycim.framework.utils.MiscUtils;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.framework.workflow.editor.WorkflowEditorService;
import com.mycim.framework.workflow.engine.WorkflowManagerService;
import com.mycim.server.base.manager.NamedObjectManager;
import com.mycim.server.base.manager.ObjectVersionManager;
import com.mycim.server.ctx.exec.manager.ResequenceContextValueManager;
import com.mycim.server.ctx.exec.manager.WflLinkContextValueManager;
import com.mycim.server.prp.dao.WorkFlowStepDAO;
import com.mycim.server.prp.dao.WorkflowViewDAO;
import com.mycim.server.prp.manager.ProcessManager;
import com.mycim.server.prp.manager.WorkFlowExcuteManager;
import com.mycim.server.prp.manager.WorkflowManager;
import com.mycim.server.wip.manager.WipWorkflowQueryManager;
import com.mycim.utils.PostgreSqlUtil;
import com.mycim.utils.WipUtils;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.procedureDO.NextMultiStepInfoDO;
import com.mycim.workflow.valueobject.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author shijie.deng
 * @version 6.0.0
 * @date 2019/9/17
 **/
@Service
@Transactional
public class WipWorkflowQueryManagerImpl implements WipWorkflowQueryManager {

    private static final Long TASK_START = 110L;

    private static final Long TASK_END = 120L;

    private static final String STEP_TYPE_WFL = "WFL";

    private static final String STEP_TYPE_TASK = "TASK";

    private static final String LINK_ID_DEFAULT = "DEFAULT";

    private static final String WORKFLOW_MODEL_PREFIX = "Value.";

    @Autowired
    private ProcessManager processManager;

    @Autowired
    private WorkflowViewDAO workflowViewDAO;

    @Autowired
    private WorkFlowStepDAO workFlowStepDAO;

    @Autowired
    private WorkFlowExcuteManager workFlowExcuteManager;

    @Autowired
    private NamedObjectManager namedObjectManager;

    @Autowired
    private ObjectVersionManager objectVersionManager;

    @Autowired
    private WorkflowManagerService workflowManagerService;

    @Autowired
    private WorkflowEditorService workflowEditorService;

    @Autowired
    private WorkflowManager workflowManager;

    @Autowired
    private WflLinkContextValueManager wflLinkContextValueManager;

    @Autowired
    private ResequenceContextValueManager resequenceContextValueManager;

    @Override
    public Map getStepsInfoByVersion(long processRrn, int processVer, String stepPath, Map matchingRules) {
        Map stepsInfo = new HashMap();
        Long routeRrn = processRrn;
        if ((stepPath != null) && (stepPath.trim().length() == 0)) {
            stepPath = null;
        }

        long executionRrn = createExecutionRrnFastByVersion(processRrn, stepPath, matchingRules,
                                                            processVer);   //TODO 改回原SP,待验证
        //        long operationRrn = getOperationByExec(executionRrn);
        long operationRrn = workflowViewDAO.getOperationByExec(executionRrn);   //TODO 改回原SP,待验证
        int operationVer = 0;

        if (operationRrn != 0) {
            operationVer = objectVersionManager.getActiveVersion(operationRrn, true);
        }


        Map workflowParameters = getWorkflowParamValueMap(executionRrn);


        String stageId = (String) workflowParameters.get("stageId");
        String layerId = (String) workflowParameters.get("layerId");

        if (workflowParameters != null) {
            stepsInfo.put("stageId", stageId);
            stepsInfo.put("layerId", layerId);
        }


        stepsInfo.put("executionRrn", new Long(executionRrn));
        stepsInfo.put("operationRrn", new Long(operationRrn));
        stepsInfo.put("operationVer", new Integer(operationVer));

        // get processstepverison and processsstepidversion
        Map _stepInfo = getProcessStepVersion(executionRrn);         //TODO 改回原SP,待验证

        stepsInfo.put("routeRrn", _stepInfo.get("routeRrn"));
        stepsInfo.put("processStepVersion4wfl", _stepInfo.get("processStepVersion4wfl"));
        stepsInfo.put("processStepVersion", _stepInfo.get("processStepVersion"));
        stepsInfo.put("processVersion", parseProcessVer((String) _stepInfo.get("processStepVersion")));
        stepsInfo.put("processStepIdVersion", _stepInfo.get("processStepIdVersion"));
        stepsInfo.put("nextoperationRrn1", _stepInfo.get("nextoperationRrn1"));
        stepsInfo.put("nextoperationId1",
                      namedObjectManager.getInstanceId(MiscUtils.parseSQL((Long) stepsInfo.get("nextoperationRrn1"))));
        stepsInfo.put("nextprocessStepVersion1", _stepInfo.get("nextprocessStepVersion1"));
        stepsInfo.put("nextprocessStepIdVersion1", _stepInfo.get("nextprocessStepIdVersion1"));
        stepsInfo.put("nextoperationRrn2", _stepInfo.get("nextoperationRrn2"));
        stepsInfo.put("nextoperationId2",
                      namedObjectManager.getInstanceId(MiscUtils.parseSQL((Long) stepsInfo.get("nextoperationRrn2"))));
        stepsInfo.put("nextprocessStepVersion2", _stepInfo.get("nextprocessStepVersion2"));
        stepsInfo.put("nextprocessStepIdVersion2", _stepInfo.get("nextprocessStepIdVersion2"));

        stepsInfo.put("totalProcessTime", "100");
        stepsInfo.put("totalSteps", 10L);

        return stepsInfo;
    }

    @Override
    public Map getProcessStepVersion(long executionRrn) {//TODO 改回原SP,待验证
        Map stepInfo = new HashMap();

        Map processStep = getCurrentStepDetailInfo(executionRrn);


        stepInfo.put("processStepVersion4wfl", processStep.get("StepPath"));

        processStep = reconstructRouteMap(processStep);

        stepInfo.put("processStepVersion", processStep.get("processStepVersion"));
        stepInfo.put("processStepIdVersion", processStep.get("processStepIdVersion"));
        stepInfo.put("operation", processStep.get("Operation"));
        stepInfo.put("routeRrn", processStep.get("Route"));

        Collection nextStepsInfo = getNextMultiStepInfoByDao(executionRrn, 2);       //TODO 改回原SP,待验证


        int i = 1;

        for (Iterator it = nextStepsInfo.iterator(); it.hasNext(); ) {
            Map item = (Map) it.next();

            item = reconstructRouteMap(item);

            Long new_operationRrn = new Long((String) item.get("Operation"));

            stepInfo.put("nextoperationRrn" + i, new_operationRrn);

            stepInfo.put("nextoperationId" + i, namedObjectManager.getInstanceId(new_operationRrn.longValue()));

            stepInfo.put("nextprocessStepVersion" + i, item.get("processStepVersion"));
            stepInfo.put("nextprocessStepIdVersion" + i, item.get("processStepIdVersion"));
            i++;
        }

        return stepInfo;
    }

    @Override
    public String getNextMultiStepInfo(NextMultiStepInfoDO multiStepDO) {
        multiStepDO.v_str_executionrrn = multiStepDO.inExecutionRrn.toString();
        multiStepDO.v_time = multiStepDO.inStep;
        multiStepDO.outList = "";

        if (multiStepDO.v_time < 1) {
            return getNextMultiStepInfoEnd(multiStepDO);
        }

        multiStepDO.v_temp_count = workFlowExcuteManager.getWorkflowExecutionCount(multiStepDO.inExecutionRrn);
        Assert.state(multiStepDO.v_temp_count != 0, Errors.create().content("Not found this  ExecutionRrn").build());

        multiStepDO.v_matching_rules = workFlowExcuteManager.getCurrentMatchRulesForLot(multiStepDO.inExecutionRrn);
        multiStepDO.v_current_step = workFlowExcuteManager
                .getCurrentStepFromWorkflowExecution(multiStepDO.inExecutionRrn);
        if (PostgreSqlUtil.instr(multiStepDO.v_current_step, "|", 1, 1) < 1) {
            multiStepDO.v_rework_flag = true;
        }

        return getNextMultiStepInfoNextStepFinder(multiStepDO);
    }

    @Override
    public List getNextMultiStepInfoByDao(long executionRrn, int n) {
        List items = new ArrayList();


        //        NextMultiStepInfoDO nextMultiStepInfoDO = new NextMultiStepInfoDO();
        //        nextMultiStepInfoDO.inExecutionRrn = executionRrn;
        //        nextMultiStepInfoDO.inStep = (long) n;

        //        String list = getNextMultiStepInfo(nextMultiStepInfoDO);
        String list = workflowViewDAO.getNextMultiStepInfoByDao(executionRrn, n);       //TODO 改回原SP,待验证

        try {

            java.util.StringTokenizer a = new java.util.StringTokenizer(list, "~");

            while (a.hasMoreElements()) {
                String b = a.nextToken();

                java.util.StringTokenizer d = new java.util.StringTokenizer(b, ",");

                HashMap map = new HashMap();

                while (d.hasMoreElements()) {
                    String s1 = d.nextToken();
                    String s2 = d.nextToken();
                    String s3 = d.nextToken();
                    String s4 = d.nextToken();
                    map.put("Operation", s3);
                    map.put("OperationRrn", new Long(s3));
                    map.put("StepPath", s4);
                    map.put("Process", s1);
                    map.put("Route", s2);
                }
                items.add(map);

            }
        } catch (Exception ex) {

        }

        return items;
    }

    @Override
    public HashMap getCurrentStepDetailInfo(long executionRrn) {
        HashMap returnMap = new HashMap();
        WorkflowInstance workflowInstance = workflowManagerService.getWorkflowInstance(executionRrn);
        WorkflowPath path = workflowInstance.getPath();
        Collection pathlist = path.getPathList();

        Iterator it = pathlist.iterator();

        if (it.hasNext()) {
            HashMap map = (HashMap) it.next();
            returnMap.put("Process", map.get("WFLRRN"));

            returnMap.put("Route", map.get("WFLRRN"));

            long stepRrn = path.getCurrentStepRrn();
            WorkflowStepModel workflowStepModel = workflowManagerService.getWorkflowStepModel(stepRrn);
            String tempstr = workflowStepModel.getParameterValue1();

            // value.xxxx
            if (tempstr != null) {
                tempstr = tempstr.substring(6);
                returnMap.put("Operation", tempstr);
            }

            if (!it.hasNext()) {
                returnMap.put("Process", null);
            }

            returnMap.put("StepPath", path.getStringOfWflPath());
        }

        if (it.hasNext()) {
            HashMap map = (HashMap) it.next();
            returnMap.put("Route", map.get("WFLRRN"));

            long stepRrn = path.getCurrentStepRrn();
            WorkflowStepModel workflowStepModel = workflowManagerService.getWorkflowStepModel(stepRrn);
            String tempstr = workflowStepModel.getParameterValue1();

            // value.xxxx
            tempstr = tempstr.substring(6);
            returnMap.put("Operation", tempstr);
        }
        return returnMap;
    }

    @Override
    public Map getWorkflowParamValueMap(long executionRrn) {
        WorkflowInstance workflowInstance = workflowManagerService.getWorkflowInstance(executionRrn);
        WorkflowInstanceModel model = workflowInstance.getModel();
        WorkflowParameterPair workflowParameterPair = new WorkflowParameterPair(model.getParameterNameString(),
                                                                                model.getParameterValueString());
        Map parameters = workflowParameterPair.getParameterValueMap();
        return parameters;
    }

    @Override
    public Map getStepsInfo(long processRrn, String stepPath, Map matchingRules) {//TODO 改回原SP,待验证
        Map stepsInfo = new HashMap(20);

        // see workflow api doc

        // **only process Rrn is needed in createExcutionRrn..
        Long routeRrn = processRrn;

        // avoid step Path space.
        if ((stepPath != null) && (stepPath.trim().length() == 0)) {
            stepPath = null;
        }
        long executionRrn = 0L;
        executionRrn = workFlowExcuteManager.createExecutionRrnFast(routeRrn, stepPath, matchingRules);
        long operationRrn = getOperationByExec(executionRrn);

        int operationVer = 0;

        if (operationRrn != 0) {
            operationVer = objectVersionManager.getActiveVersion(operationRrn, true);
        }
        Map workflowParameters = getWorkflowParamValueMap(executionRrn);
        String stageId = (String) workflowParameters.get("stageId");
        String layerId = (String) workflowParameters.get("layerId");

        if (workflowParameters != null) {
            stepsInfo.put("stageId", stageId);
            stepsInfo.put("layerId", layerId);
        }
        stepsInfo.put("executionRrn", new Long(executionRrn));
        stepsInfo.put("operationRrn", new Long(operationRrn));
        stepsInfo.put("operationVer", new Integer(operationVer));
        Map _stepInfo = getProcessStepVersion(executionRrn);
        stepsInfo.put("processStepVersion4wfl", _stepInfo.get("processStepVersion4wfl"));
        stepsInfo.put("processStepVersion", _stepInfo.get("processStepVersion"));
        stepsInfo.put("processVersion", new Integer(parseProcessVer((String) _stepInfo.get("processStepVersion"))));
        stepsInfo.put("processStepIdVersion", _stepInfo.get("processStepIdVersion"));
        stepsInfo.put("nextoperationRrn1", _stepInfo.get("nextoperationRrn1"));
        stepsInfo.put("nextoperationId1",
                      namedObjectManager.getInstanceId(MiscUtils.parseSQL((Long) stepsInfo.get("nextoperationRrn1"))));
        stepsInfo.put("nextprocessStepVersion1", _stepInfo.get("nextprocessStepVersion1"));
        stepsInfo.put("nextprocessStepIdVersion1", _stepInfo.get("nextprocessStepIdVersion1"));
        stepsInfo.put("nextoperationRrn2", _stepInfo.get("nextoperationRrn2"));
        stepsInfo.put("nextoperationId2",
                      namedObjectManager.getInstanceId(MiscUtils.parseSQL((Long) stepsInfo.get("nextoperationRrn2"))));
        stepsInfo.put("nextprocessStepVersion2", _stepInfo.get("nextprocessStepVersion2"));
        stepsInfo.put("nextprocessStepIdVersion2", _stepInfo.get("nextprocessStepIdVersion2"));

        stepsInfo.put("totalProcessTime", "100");
        stepsInfo.put("totalSteps", new Long(10));

        return stepsInfo;
    }

    @Override
    public List<Map> getWflInfoForCombo(String selectColumn, String resultColumnName,
                                        Map<String, Object> conditionMap) {
        return workflowViewDAO.getWflInfoForCombo(selectColumn, resultColumnName, conditionMap);
    }

    @Override
    public long getOperationByExec(long executionRrn) {
        //TODO 改回原SP,待验证
        //        Long operationRrn = 0L;
        //
        //        String v_current_step     = "";
        //        Long   v_current_step_rrn = 0L;
        //
        //        if (!isExistExecutionRrn(executionRrn)) {
        //            throw new ManagerException("Failed To Find WorkflowExecution");
        //        }
        //        v_current_step = workFlowExcuteManager.getCurrentStepFromWorkflowExecution(executionRrn);
        //        v_current_step_rrn = workFlowExcuteManager.getStep(v_current_step);
        //        Map parameterValues = workFlowExcuteManager
        //        .getFilterParameterValue123FromWorkflowTemplateDetail(
        //                v_current_step_rrn);
        //        String parameterValue1 = MapUtils.getString(parameterValues, "parameterValue1");
        //        operationRrn = Long.parseLong(parameterValue1.substring(0, 7));
        //
        //        return operationRrn;
        return workflowViewDAO.getOperationByExec(executionRrn);
    }

    @Override
    public String[] parseWflStepPath(String wflStepPath) {
        String[] result = new String[6];
        String[] wflInfo = StringUtils.split(wflStepPath, '|');

        if (wflInfo.length == 2) {
            String[] processInfo = StringUtils.split(wflInfo[0], '.');
            String[] routeInfo = StringUtils.split(wflInfo[1], '.');
            result = StringUtils.mergeStringArraysForNotCheckContains(processInfo, routeInfo);
        } else {
            String[] reworkWflInfo = StringUtils.split(wflInfo[0], '.');
            if (reworkWflInfo.length == 3) {
                result[3] = reworkWflInfo[0];
                result[4] = reworkWflInfo[1];
                result[5] = reworkWflInfo[2];
            }
        }

        return result;
    }

    @Override
    public boolean isExistExecutionRrn(long executionRrn) {
        return workflowViewDAO.isExistExecutionRrn(executionRrn);
    }

    @Override
    public String getStepNumberByWflTree(Lot lot, String routeId, String operationId, boolean beforeFirst) {
        List<String[]> wflTree = null;
        String stepNumber = null;
        if (beforeFirst) {
            wflTree = workflowManager.getWorkFlowTreeBefore(lot.getExecutionRrn());
            stepNumber = traverseTressForStepNumber(wflTree, routeId, operationId);
            if (StringUtils.isEmpty(stepNumber)) {
                wflTree = workflowManager.getWorkFlowTreeAfter(lot.getExecutionRrn());
                stepNumber = traverseTressForStepNumber(wflTree, routeId, operationId);
            }
        } else {
            wflTree = workflowManager.getWorkFlowTreeAfter(lot.getExecutionRrn());
            stepNumber = traverseTressForStepNumber(wflTree, routeId, operationId);
            if (StringUtils.isEmpty(stepNumber)) {
                wflTree = workflowManager.getWorkFlowTreeBefore(lot.getExecutionRrn());
                stepNumber = traverseTressForStepNumber(wflTree, routeId, operationId);
            }
        }
        if (StringUtils.isEmpty(stepNumber) && StringUtils.equalsIgnoreCase(operationId, lot.getOperationId()) &&
                StringUtils.equalsIgnoreCase(routeId, lot.getRouteId())) {
            stepNumber = lot.getWflStepPath();
        }
        return stepNumber;
    }
    private String getStepNumberByWflTree(Lot lot, long routeRrn, long operationRrn) {
        String stepNumber = null;
        List<Map<String, Object>> processAllStepInfo = processManager.getProcessAllStepInfo(
         lot.getProcessRrn(),lot.getProcessVersion(),
        null,null,
        99999L, lot.getProductRrn(),
         lot.getProductVersion(),0);
        Map<String, Object> orElse = processAllStepInfo.stream()
        .filter(info -> MapUtils.getLong(info,"operationRrn") == operationRrn && MapUtils.getLong(info,"routeRrn") == routeRrn)
        .findFirst().orElse(null);
        if (orElse == null) {
            stepNumber = lot.getWflStepPath();
        }else {
            stepNumber = MapUtils.getString(orElse, "processRrn") + "." + MapUtils.getString(orElse,
           "processVersion") + "." + MapUtils.getString(orElse, "routeStepRrn") + "|" + MapUtils.getString(orElse,
           "routeRrn") + "." + MapUtils.getString(orElse, "routeVersion") + "." + MapUtils.getString(orElse, "operationStepRrn");
        }
        return stepNumber;
    }
    @Override
    public String getStepNumberByWflTreeBeforeFirst(Lot lot, long routeRrn, long operationRrn) {

        // String routeId = namedObjectManager.getNamedObjectId(routeRrn);
        // String operationId = namedObjectManager.getNamedObjectId(operationRrn);
        // return getStepNumberByWflTree(lot, routeId, operationId, true);
        return getStepNumberByWflTree(lot,routeRrn,operationRrn);
    }

    @Override
    public String getOprationByWflTreeBeforeFirst(Lot lot, long routeRrn, long operationRrn) {
        Map operationNodeInfo = getOperationNodeInfoByWflTree(lot, routeRrn, operationRrn, true);
        return MapUtils.getString(operationNodeInfo, "operationRrn");
    }

    @Override
    public String reconstructRouteMap(String returnProcessStepVersion, Map processStep) {
        StringBuffer rrnStr = new StringBuffer("");

        if (processStep != null) {
            if (processStep.get("Process") != null) {
                String processInfo = StringUtils.substringBefore(returnProcessStepVersion, "|");
                String processVersion = StringUtils.substringBetween(processInfo, ".", ".");
                makeStr((Long) processStep.get("Process"), processVersion, rrnStr);
                rrnStr.append("|");
            }

            if (processStep.get("Route") != null) {
                String routeInfo = StringUtils.substringAfter(returnProcessStepVersion, "|");
                String routeVersion = StringUtils.substringBetween(routeInfo, ".", ".");
                makeStr((Long) processStep.get("Route"), routeVersion, rrnStr);
                rrnStr.append("|");
            }

            if (processStep.get("Operation") != null) {
                makeStr((Long) processStep.get("Operation"), "0", rrnStr);
            }

        }

        return rrnStr.toString();
    }

    @Override
    public Map reconstructRouteMap(Map processStep) {
        StringBuffer rrnStr = new StringBuffer();
        StringBuffer idStr = new StringBuffer();

        if (processStep != null) {

            String path = (String) processStep.get("StepPath");

            if (processStep.get("Process") != null) {
                makeStr(new Long((String) processStep.get("Process")), parseNextStepPath(path, "process"), rrnStr,
                        idStr);
                rrnStr.append("|");
                idStr.append("|");
            }

            if (processStep.get("Route") != null) {
                makeStr(new Long((String) processStep.get("Route")), parseNextStepPath(path, null), rrnStr, idStr);
                rrnStr.append("|");
                idStr.append("|");
            }

            if (processStep.get("Operation") != null) {
                makeStr(new Long((String) processStep.get("Operation")), null, rrnStr, idStr);
            }

        }

        processStep.put("processStepVersion", rrnStr.toString());
        processStep.put("processStepIdVersion", idStr.toString());

        return processStep;
    }

    @Override
    public Map<String, Object> getNextStepWflInfo(Long facilityRrn, Long processRrn, Integer processVersion,
                                                  String wflStepPath, Map<String, Object> contextKey) {

        String[] wflInfo = parseWflStepPath(wflStepPath);

        long routeStepRrn = NumberUtils.toLong(wflInfo[2]);
        long operationStepRrn = NumberUtils.toLong(wflInfo[5]);

        boolean isRouteLastStep = isRouteLastStep(operationStepRrn);
        long stepRrn = isRouteLastStep ? routeStepRrn : operationStepRrn;
        String linkId = wflLinkContextValueManager
                .getEffectiveMultipathWflLinkId(facilityRrn, contextKey, isRouteLastStep);

        return getNextStepWflInfo(processRrn, processVersion, stepRrn, linkId);
    }

    @Override
    public Map<String, Object> getNextStepWflInfo(Long processRrn, Integer processVersion, long stepRrn,
                                                  String linkId) {
        String tempLinkId =
                StringUtils.isEmpty(linkId) || StringUtils.equals(LINK_ID_DEFAULT, linkId) ? StringUtils.EMPTY : linkId;
        Map<String, Object> result = new HashMap<>();
        //参数不合法则直接return 空Map 防止下面操作空指针
        if(processRrn==null||processRrn==0||processVersion==null||processVersion==0){
            return result;
        }
        List<WorkflowLinkModel> workflowLinkModels = workFlowStepDAO.getNextWorkFlowStepsByStepRrn(stepRrn);
        if (CollectionUtils.isNotEmpty(workflowLinkModels)) {
            for (WorkflowLinkModel workflowLinkModel : workflowLinkModels) {
                WorkflowStepModel workflowStepModel = workflowEditorService
                        .getWorkFlowTemplateDetailByStepRrn(workflowLinkModel.getNextStepRrn());

                if (StringUtils.equals(STEP_TYPE_WFL, workflowStepModel.getStepType()) && StringUtils
                        .equals(workflowLinkModel.getId() == null ? StringUtils.EMPTY : workflowLinkModel.getId(),
                                tempLinkId)) {
                    WorkflowStepModel startTask = getWorkFlowStepForStartOrEnd(workflowStepModel.getActivityRrn(),
                                                                               workflowStepModel.getStepVersion(),
                                                                               TASK_START);
                    return getNextStepWflInfo(processRrn, processVersion, startTask.getStepRrn(), StringUtils.EMPTY);
                }

                if (StringUtils.equals(STEP_TYPE_TASK, workflowStepModel.getStepType()) && StringUtils
                        .equals(workflowLinkModel.getId() == null ? StringUtils.EMPTY : workflowLinkModel.getId(),
                                tempLinkId)) {
                    WorkflowStepModel operationStepModel = workflowManagerService
                            .getWorkflowStepModel(workflowLinkModel.getNextStepRrn());
                    WorkflowStepModel routeStepModel = workflowManager
                            .getWorkflowStepForWFL(processRrn, processVersion, operationStepModel.getWflRrn());

                    result.put("processRrn", processRrn);
                    result.put("processVersion", processVersion);

                    result.put("routeRrn", operationStepModel.getWflRrn());
                    result.put("routeVersion", operationStepModel.getWflVersion());
                    result.put("routeSeq", StringUtils
                            .substringAfter(routeStepModel.getParameterValue1(), WorkflowStepModel.PARAMETER_PREFIX));

                    result.put("operationRrn",
                               NumberUtils.toLong(StringUtils.substring(operationStepModel.getParameterValue1(), 6)));
                    result.put("operationSeq", StringUtils.substringAfter(operationStepModel.getParameterValue4(),
                                                                          WorkflowStepModel.PARAMETER_PREFIX));
                    break;
                }
            }
        }

        return result;
    }

    @Override
    public Map getNodeInfoByWflTree(Lot lot, long operationRrn, boolean beforeFirst) {
        List wflTree = null;
        Map node = null;
        if (beforeFirst) {
            wflTree = workflowManager.getWorkFlowTreeBefore(lot.getExecutionRrn().longValue());
            node = traverseDescTressForStepNumber(wflTree, operationRrn);
            if (node.size() <= 0) {
                wflTree = workflowManager.getWorkFlowTreeAfterCurrent(lot.getExecutionRrn().longValue());
                node = traverseAscTressForStepNumber(wflTree, operationRrn);
            }
        } else {
            wflTree = workflowManager.getWorkFlowTreeAfterCurrent(lot.getExecutionRrn().longValue());
            node = traverseAscTressForStepNumber(wflTree, operationRrn);
            if (node.size() <= 0) {
                wflTree = workflowManager.getWorkFlowTreeBefore(lot.getExecutionRrn().longValue());
                node = traverseDescTressForStepNumber(wflTree, operationRrn);
            }
        }

        if (node.size() <= 0) {
            node.put("stepInfo", lot.getWflStepPath());
            node.put("operationRrn", lot.getOperationRrn());
        }
        return node;
    }

    @Override
    public Map<String, Object> getReworkStepsInfo(long processRrn, int processVer, String stepPath, Map matchingRules) {
        if (processVer > 0) {
            getStepsInfo(processRrn, processVer, stepPath, matchingRules);
        }
        return getStepsInfo(processRrn, stepPath, matchingRules);
    }

    @Override
    public List<String> getMethodIdListByExecutionRrn(long executionRrn) {
        return workflowViewDAO.getMethodIdListByExecutionRrn(executionRrn);
    }

    @Override
    public Long getOperationRrnByWflStepPath(String wflStepPath) {
        String[] wflStep = parseWflStepPath(wflStepPath);
        Long operationStepRrn = NumberUtils.toLong(wflStep[5]);

        WorkflowStepModel workflowModel = workflowManager.getWorkflowStepForStepRrn(operationStepRrn);

        if (Objects.nonNull(workflowModel)) {
            Long operationRrn = NumberUtils
                    .toLong(StringUtils.substringAfter(workflowModel.getParameterValue1(), WORKFLOW_MODEL_PREFIX));
            return operationRrn;
        }
        return NumberUtils.LONG_ZERO;
    }

    @Override
    public String getFlowSeqByWflStep(String wflStepPath) {
        if(StringUtils.isBlank(wflStepPath)) {
            return StringUtils.EMPTY;
        }

        String[] wflStep = parseWflStepPath(wflStepPath);
        if (Objects.nonNull(wflStep) && wflStep.length > 3) {
            Long processRrn = NumberUtils.toLong(wflStep[0]);
            Integer processVersion = NumberUtils.toInt(wflStep[1]);
            Long routeRrn = NumberUtils.toLong(wflStep[3]);

            Long operationRrn = getOperationRrnByWflStepPath(wflStepPath);

            return resequenceContextValueManager.getFlowSeq(processRrn, processVersion, operationRrn, routeRrn);
        }
        return StringUtils.EMPTY;
    }

    @Override
    public Map<String, Object> getStepsInfo(Long processRrn, Integer processVer, String stepPath,
                                            Map<String, Object> matchingRules) {
        Map<String, Object> stepsInfo = new HashMap<>();

        if ((stepPath != null) && (stepPath.trim().length() == 0)) {
            stepPath = null;
        }

        long executionRrn = workFlowExcuteManager.createExecutionRrnFast(processRrn, stepPath, matchingRules);
        long operationRrn = getOperationByExec(executionRrn);


        int operationVer = 0;

        if (operationRrn != 0) {
            operationVer = objectVersionManager.getActiveVersion(operationRrn);
        }

        Map workflowParameters = getWorkflowParamValueMap(executionRrn);
        String stageId = MapUtils.getString(workflowParameters, "stageId");
        String layerId = MapUtils.getString(workflowParameters, "layerId");
        if (workflowParameters != null) {
            stepsInfo.put("stageId", stageId);
            stepsInfo.put("layerId", layerId);
        }

        stepsInfo.put("executionRrn", executionRrn);
        stepsInfo.put("operationRrn", operationRrn);
        stepsInfo.put("operationVer", operationVer);

        Map _stepInfo = getProcessStepVersion(executionRrn);
        stepsInfo.put("processStepVersion4wfl", _stepInfo.get("processStepVersion4wfl"));
        stepsInfo.put("processStepVersion", _stepInfo.get("processStepVersion"));
        stepsInfo.put("processVersion", parseProcessVer((String) _stepInfo.get("processStepVersion")));
        stepsInfo.put("processStepIdVersion", _stepInfo.get("processStepIdVersion"));
        stepsInfo.put("nextoperationRrn1", _stepInfo.get("nextoperationRrn1"));
        stepsInfo.put("nextoperationId1",
                      namedObjectManager.getInstanceId(MiscUtils.parseSQL((Long) stepsInfo.get("nextoperationRrn1"))));
        stepsInfo.put("nextprocessStepVersion1", _stepInfo.get("nextprocessStepVersion1"));
        stepsInfo.put("nextprocessStepIdVersion1", _stepInfo.get("nextprocessStepIdVersion1"));
        stepsInfo.put("nextoperationRrn2", _stepInfo.get("nextoperationRrn2"));
        stepsInfo.put("nextoperationId2",
                      namedObjectManager.getInstanceId(MiscUtils.parseSQL((Long) stepsInfo.get("nextoperationRrn2"))));
        stepsInfo.put("nextprocessStepVersion2", _stepInfo.get("nextprocessStepVersion2"));
        stepsInfo.put("nextprocessStepIdVersion2", _stepInfo.get("nextprocessStepIdVersion2"));

        stepsInfo.put("totalProcessTime", "100");
        stepsInfo.put("totalSteps", 10L);
        return stepsInfo;
    }

    @Override
    public Long getRouteFirstOperationRrn(Long processRrn, Integer processVersion, long routeRrn) {
        WorkflowStepModel workflowStepModel = workflowManager
                .getWorkflowStepForWFL(processRrn, processVersion, routeRrn);
        if (workflowStepModel == null) {
            return null;
        }

        WorkflowStepModel startTask = getWorkFlowStepForStartOrEnd(workflowStepModel.getActivityRrn(),
                                                                   workflowStepModel.getStepVersion(), TASK_START);

        List<WorkflowLinkModel> workflowLinkModels = workFlowStepDAO
                .getNextWorkFlowStepsByStepRrn(startTask.getStepRrn());
        if (CollectionUtils.isNotEmpty(workflowLinkModels)) {
            for (WorkflowLinkModel workflowLinkModel : workflowLinkModels) {
                WorkflowStepModel normalStepModel = workflowManagerService
                        .getWorkflowStepModel(workflowLinkModel.getNextStepRrn());
                if (StringUtils.equals(STEP_TYPE_TASK, normalStepModel.getStepType())) {
                    return NumberUtils.toLong(StringUtils.substringAfter(normalStepModel.getParameterValue1(),
                                                                         WorkflowStepModel.PARAMETER_PREFIX));
                }
            }
        }
        return null;
    }

    @Override
    public String getEffectiveMultipathWflLinkId(Long facilityRrn, String wflStepPath, Map<String, Object> contextKey) {
        String[] wflInfo = parseWflStepPath(wflStepPath);

        long operationStepRrn = NumberUtils.toLong(wflInfo[5]);

        return wflLinkContextValueManager
                .getEffectiveMultipathWflLinkId(facilityRrn, contextKey, isRouteLastStep(operationStepRrn));
    }

    private boolean isRouteLastStep(long operationStepRrn) {
        List<WorkflowLinkModel> workflowLinkModels = workFlowStepDAO.getNextWorkFlowStepsByStepRrn(operationStepRrn);
        if (CollectionUtils.isNotEmpty(workflowLinkModels)) {
            for (WorkflowLinkModel workflowLinkModel : workflowLinkModels) {
                WorkflowStepModel workflowStepModel = workflowManagerService
                        .getWorkflowStepModel(workflowLinkModel.getNextStepRrn());
                if (StringUtils.equals(STEP_TYPE_TASK, workflowStepModel.getStepType()) &&
                        TASK_END == workflowStepModel.getActivityRrn()) {
                    return true;
                }
            }
        }
        return false;
    }

    private Map traverseDescTressForStepNumber(List wflTree, long operationRrn) {
        wflTree = WipUtils.reBuildWflTree(wflTree);
        Map nodeMap = new HashMap();
        long wfloperationRrn = 0L;
        int wflTreeSize = wflTree.size();
        for (int i = (wflTreeSize - 1); i >= 0; i--) {
            Map node = (HashMap) wflTree.get(i);
            wfloperationRrn = MapUtils.getLongValue(node, "operationRrn");
            if (wfloperationRrn == operationRrn) {
                nodeMap = node;
                break;
            }
        }
        return nodeMap;
    }

    /**
     * @param wflTree
     * @return
     */
    private Map traverseAscTressForStepNumber(List wflTree, long operationRrn) {
        wflTree = WipUtils.reBuildWflTree(wflTree);
        Map nodeMap = new HashMap();
        long wfloperationRrn = 0L;
        int wflTreeSize = wflTree.size();
        for (int i = 0; i < wflTreeSize; i++) {
            Map node = (HashMap) wflTree.get(i);
            wfloperationRrn = MapUtils.getLongValue(node, "operationRrn");
            if (wfloperationRrn == operationRrn) {
                nodeMap = node;
                break;
            }
        }
        return nodeMap;
    }

    private Map getOperationNodeInfoByWflTree(Lot lot, long routeRrn, long operationRrn, boolean beforeFirst) {
        List<String[]> wflTree = null;
        Map node = null;
        if (beforeFirst) {
            wflTree = workflowManager.getWorkFlowTreeBefore(lot.getExecutionRrn());
            node = traverseDescTressForStepNumber(wflTree, routeRrn, operationRrn);
            if (node.size() <= 0) {
                wflTree = workflowManager.getWorkFlowTreeAfterCurrent(lot.getExecutionRrn());
                node = traverseAscTressForStepNumber(wflTree, routeRrn, operationRrn);
            }
        } else {
            wflTree = workflowManager.getWorkFlowTreeAfterCurrent(lot.getExecutionRrn());
            node = traverseAscTressForStepNumber(wflTree, routeRrn, operationRrn);
            if (node.size() <= 0) {
                wflTree = workflowManager.getWorkFlowTreeBefore(lot.getExecutionRrn());
                node = traverseDescTressForStepNumber(wflTree, routeRrn, operationRrn);
            }
        }

        if (node.size() <= 0) {
            node.put("stepInfo", lot.getWflStepPath());
            node.put("operationRrn", lot.getOperationRrn());
        }

        return node;
    }

    private Map traverseAscTressForStepNumber(List<String[]> wflTree, long routeRrn, long operationRrn) {
        List<Map> wflTreeInfo = WipUtils.reBuildWflTree(wflTree);
        String wflRouteRrn = null;
        String nodeType = null;
        Map nodeMap = new HashMap();
        String oprationIsFirstStep = null;
        String wflOperationRrn = null;
        int wflTreeSize = wflTree.size();

        for (Map node : wflTreeInfo) {

            nodeType = MapUtils.getString(node, "nodeType");
            wflRouteRrn = MapUtils.getString(node, "routeRrn");
            wflOperationRrn = MapUtils.getString(node, "operationRrn");
            oprationIsFirstStep = MapUtils.getString(node, "oprationIsFirstStep");
            if (operationRrn <= 0) {
                if (StringUtils.equals(nodeType, "OPERATION") && StringUtils.equals(wflRouteRrn, routeRrn + "") &&
                        StringUtils.equals(oprationIsFirstStep, "1")) {
                    nodeMap = node;
                    break;
                }
            } else {
                if (StringUtils.equals(nodeType, "OPERATION") && StringUtils.equals(wflRouteRrn, routeRrn + "") &&
                        StringUtils.equals(wflOperationRrn, operationRrn + "")) {
                    nodeMap = node;
                    break;
                }
            }
        }


        return nodeMap;
    }

    private void makeStr(Long rrn, String ver, StringBuffer sbRrn, StringBuffer sbId) {
        if ((rrn != null) && (rrn.longValue() != 0)) {
            String id = namedObjectManager.getInstanceId(rrn.longValue());

            if (ver == null) {
                ver = (new Integer(objectVersionManager.getActiveVersion(rrn.longValue(), true))).toString();
            }

            // sample: 111.1|222.3|444.3
            sbRrn.append(rrn);
            sbRrn.append(",");
            sbRrn.append(ver);

            // sample: xxx.1|yyy.2|zzz.3
            sbId.append(id);
            sbId.append(",");

            sbId.append(ver);
        }
    }

    private String parseNextStepPath(String s, String type) {

        int i = 1;

        String sub = "";
        String ret = "";

        i = s.indexOf("|");

        if ("process".equals(type) && i != -1) {
            sub = s.substring(0, i);

        } else {
            sub = s.substring(i + 1);
        }

        ret = getSingle(sub);

        return ret;

    }

    private String getSingle(String s) {
        int i = s.indexOf(".");
        int j = s.lastIndexOf(".");
        return s.substring(i + 1, j);
    }

    private int parseProcessVer(String processStep) {
        int processVer = 0;
        if (processStep != null && !processStep.trim().equals("")) {
            processVer = Integer
                    .parseInt(processStep.substring(processStep.indexOf(",", 1) + 1, processStep.indexOf("|", 1)));
        }
        return processVer;
    }

    private long createExecutionRrnFastByVersion(long workflowRrn, String stepPath, Map matchingRules,
                                                 int processVersion) {
        long executionRrn = workFlowExcuteManager
                .createExecutionRrnFastByVersion(workflowRrn, stepPath, matchingRules, processVersion);
        return executionRrn;
    }

	/*private String traverseDescTressForStepNumber(List<String[]> wflTree, String routeId,
	                                              String operationId) {
	    String wflRouteId = null;
	    String wflRouteSeq = null;
	    String wflOperationId = null;
	    String wflOperationSeq = null;
	    String stepNumber = null;
	    int wflTreeSize = wflTree.size();
	    boolean matchRoutFlag = false;
	    for (int i = 0 ; i < wflTreeSize; i++) {
	        String[] node = (String[]) wflTree.get(i);
	        if ("0".equals(node[7])) {
	        	if(matchRoutFlag) {
	        		continue;
	        	}
	            wflRouteId = StringUtils.substringAfter(node[2], "---");
	            wflRouteSeq = StringUtils.substringBefore(node[2], "---");
	            if (StringUtils.equals(wflRouteId, routeId)) {
	            	matchRoutFlag = true;
	            }
	        } else if ("1".equals(node[7]) && matchRoutFlag) {
	            wflOperationId = StringUtils.substringAfter(node[2], "---");
	            wflOperationSeq = StringUtils.substringBefore(node[2], "---");
	            if(StringUtils.equals(wflOperationId, operationId)) {
	            	stepNumber = node[6];
	            	return stepNumber;
	            }
	        }
	    }
	    return stepNumber;
	}*/

    private Map traverseDescTressForStepNumber(List<String[]> wflTree, long routeRrn, long operationRrn) {

        List<Map> wflTreeInfo = WipUtils.reBuildWflTree(wflTree);
        String wflRouteRrn = null;
        String nodeType = null;
        Map nodeMap = new HashMap();
        String oprationIsFirstStep = null;
        String wflOperationRrn = null;
        int wflTreeSize = wflTree.size();

        for (Map Node : wflTreeInfo) {
            nodeType = MapUtils.getString(Node, "nodeType");
            wflRouteRrn = MapUtils.getString(Node, "routeRrn");
            wflOperationRrn = MapUtils.getString(Node, "operationRrn");
            oprationIsFirstStep = MapUtils.getString(Node, "oprationIsFirstStep");
            if (operationRrn <= 0) {
                if (StringUtils.equals(nodeType, "OPERATION") && StringUtils.equals(wflRouteRrn, routeRrn + "") &&
                        StringUtils.equals(oprationIsFirstStep, "1")) {
                    nodeMap = Node;
                    break;
                }
            } else {
                if (StringUtils.equals(nodeType, "OPERATION") && StringUtils.equals(wflRouteRrn, routeRrn + "") &&
                        StringUtils.equals(wflOperationRrn, operationRrn + "")) {
                    nodeMap = Node;
                    break;
                }
            }
        }


        return nodeMap;
    }

    private String traverseTressForStepNumber(List<String[]> wflTree, String routeId, String operationId) {
        String wflRouteId = null;
        String wflRouteSeq = null;
        String wflOperationId = null;
        String wflOperationSeq = null;
        String stepNumber = null;
        int wflTreeSize = wflTree.size();
        boolean matchRoutFlag = false;
        for (int i = 0; i < wflTreeSize; i++) {
            String[] node = (String[]) wflTree.get(i);
            if ("0".equals(node[7])) {
                if (matchRoutFlag) {
                    continue;
                }
                wflRouteId = StringUtils.substringAfter(node[2], "---");
                wflRouteSeq = StringUtils.substringBefore(node[2], "---");
                if (StringUtils.equals(wflRouteId, routeId)) {
                    matchRoutFlag = true;
                }
            } else if ("1".equals(node[7]) && matchRoutFlag) {
                wflOperationId = StringUtils.substringAfter(node[2], "---");
                wflOperationSeq = StringUtils.substringBefore(node[2], "---");
                if (StringUtils.equals(wflOperationId, operationId)) {
                    stepNumber = node[6];
                    break;
                }
            }
        }
        return stepNumber;
    }

    private String getNextMultiStepInfoNextStepFinder(NextMultiStepInfoDO multiStepDO) {
        multiStepDO.v_current_step_rrn = workFlowExcuteManager.getStep(multiStepDO.v_current_step);
        Assert.state(multiStepDO.v_current_step_rrn != 0, Errors.create().content("Not found this step").build());
        multiStepDO.v_next_step_rrn = workFlowExcuteManager
                .getWflNextStepRrnForStep(multiStepDO.v_current_step_rrn, multiStepDO.v_matching_rules,
                                          multiStepDO.v_current_step, " ",
                                          workFlowExcuteManager.getCurrentRouteSeq(multiStepDO.v_current_step), " ");
        multiStepDO.v_temp_count = workFlowExcuteManager.getWorkflowTemplateDetailCount(multiStepDO.v_next_step_rrn);

        Assert.state(multiStepDO.v_temp_count != 0,
                     Errors.create().content("Not found this step in workflow_template_detail").build());
        multiStepDO.v_temp_string = String
                .valueOf(workFlowExcuteManager.getWflOrTaskRrnFromWorkflowTemplateDetail(multiStepDO.v_next_step_rrn));
        multiStepDO.v_next_route_rrn = workFlowExcuteManager
                .getWflRrnFromWorkflowTemplateDetail(multiStepDO.v_next_step_rrn);
        String value1 = PostgreSqlUtil
                .substr(workFlowExcuteManager.getParameterValue1FromWorkflowTemplateDetail(multiStepDO.v_next_step_rrn),
                        6);
        multiStepDO.v_operation_rrn = value1 == null ? null : NumberUtils.toLong(value1);

        multiStepDO.v_new_setp_path = multiStepDO.v_current_step
                .replace(multiStepDO.v_current_step_rrn + "#", multiStepDO.v_next_step_rrn + "#");
        /**
         check the v_temp_string
         v_temp_string
         100  operation
         110  start
         120  end
         130  split
         140  join
         */
        if (StringUtils.equals(multiStepDO.v_temp_string, "130")) {
            return getNextMultiStepInfoSplit(multiStepDO);
        } else if (StringUtils.equals(multiStepDO.v_temp_string, "140")) {
            return getNextMultiStepInfoJoin(multiStepDO);
        } else if (StringUtils.equals(multiStepDO.v_temp_string, "100")) {
            return getNextMultiStepInfoNextStep(multiStepDO);
        } else if (StringUtils.equals(multiStepDO.v_temp_string, "110")) {
            return getNextMultiStepInfoNextStep(multiStepDO);
        } else if (StringUtils.equals(multiStepDO.v_temp_string, "120") && multiStepDO.v_rework_flag == false) {
            return getNextMultiStepInfoTryGetNextStep(multiStepDO);
        } else {
            return getNextMultiStepInfoEnd(multiStepDO);
        }
    }

    private String getNextMultiStepInfoSplit(NextMultiStepInfoDO multiStepDO) {
        multiStepDO.v_and_or_flag = workFlowExcuteManager
                .getParameterValue1FromWorkflowTemplateDetail(multiStepDO.v_next_step_rrn);
        //or split
        if ("Value.1".equals(multiStepDO.v_and_or_flag)) {
            multiStepDO.v_next_step_rrn = workFlowExcuteManager
                    .getMinWflNextStepRrnFromWorkflowLink(multiStepDO.v_next_step_rrn, multiStepDO.v_str_executionrrn,
                                                          multiStepDO.v_str_executionrrn);
            multiStepDO.v_temp_count = workFlowExcuteManager
                    .getWorkflowTemplateDetailCount(multiStepDO.v_next_step_rrn);
            Assert.state(multiStepDO.v_temp_count != 0,
                         Errors.create().content("or split:Not found this step in " + "workflow_template_detail!")
                               .build());
            multiStepDO.v_new_setp_path = multiStepDO.v_current_step
                    .replace(multiStepDO.v_current_step_rrn + "#", multiStepDO.v_next_step_rrn + "#");
        }
        //and split
        if ("Value.0".equals(multiStepDO.v_and_or_flag)) {
            multiStepDO.v_temp_rrn = multiStepDO.v_next_step_rrn;
            multiStepDO.ss = multiStepDO.v_next_step_rrn.toString();
            multiStepDO.v_next_step_rrn = workFlowExcuteManager
                    .getMinWflNextStepRrnFromWorkflowLink(multiStepDO.v_next_step_rrn, multiStepDO.v_str_executionrrn,
                                                          multiStepDO.v_str_executionrrn);
            multiStepDO.v_temp_count = workFlowExcuteManager
                    .getWorkflowTemplateDetailCount(multiStepDO.v_next_step_rrn);
            Assert.state(multiStepDO.v_temp_count != 0,
                         Errors.create().content("and split:Not found this step in " + "workflow_template_detail!")
                               .build());
            multiStepDO.v_new_setp_path = multiStepDO.v_current_step
                    .replace(multiStepDO.v_current_step_rrn + "#", multiStepDO.v_next_step_rrn + "#");
        }
        workFlowExcuteManager
                .updateSplitProcessed2FromWorkflowLink(multiStepDO.v_str_executionrrn, multiStepDO.v_temp_rrn,
                                                       multiStepDO.v_next_step_rrn);
        return getNextMultiStepInfoNextStep(multiStepDO);
    }

    private String getNextMultiStepInfoJoin(NextMultiStepInfoDO multiStepDO) {
        String value1 = PostgreSqlUtil
                .substr(workFlowExcuteManager.getParameterValue1FromWorkflowTemplateDetail(multiStepDO.v_next_step_rrn),
                        6);
        multiStepDO.v_split_rrn = value1 == null ? null : NumberUtils.toLong(value1);
        multiStepDO.v_and_or_flag = workFlowExcuteManager
                .getParameterValue1FromWorkflowTemplateDetail(multiStepDO.v_split_rrn);

        if ("Value.1".equals(multiStepDO.v_and_or_flag)) {
            multiStepDO.v_new_setp_path = multiStepDO.v_current_step
                    .replace(multiStepDO.v_current_step_rrn + "#", multiStepDO.v_next_step_rrn + "#");
            multiStepDO.v_current_step = multiStepDO.v_new_setp_path;
        }
        // and join
        if ("Value.0".equals(multiStepDO.v_and_or_flag)) {
            multiStepDO.v_temp_count = workFlowExcuteManager
                    .getWorkflowLinkCount(multiStepDO.v_next_step_rrn, multiStepDO.v_str_executionrrn);
            if (multiStepDO.v_temp_count == 0) {
                multiStepDO.v_current_step = multiStepDO.v_new_setp_path;
                return getNextMultiStepInfoNextStepFinder(multiStepDO);
            }
            multiStepDO.v_new_setp_path = multiStepDO.v_current_step
                    .replace(multiStepDO.v_current_step_rrn + "#", multiStepDO.v_split_rrn + "#");
            multiStepDO.v_current_step = multiStepDO.v_new_setp_path;
        }
        return getNextMultiStepInfoNextStepFinder(multiStepDO);
    }

    private String getNextMultiStepInfoTryGetNextStep(NextMultiStepInfoDO multiStepDO) {
        multiStepDO.v_current_route = workFlowExcuteManager.getRoute(multiStepDO.v_current_step);
        return getNextMultiStepInfoTryGetNextStep2(multiStepDO);
    }

    private String getNextMultiStepInfoTryGetNextStep2(NextMultiStepInfoDO multiStepDO) {
        multiStepDO.v_next_route_step = workFlowExcuteManager
                .getWflNextStepRrnForTree(multiStepDO.v_current_route, multiStepDO.v_matching_rules,
                                          workFlowExcuteManager.getCurrentRoute(multiStepDO.v_current_step), "", " ",
                                          workFlowExcuteManager.getCurrentRouteSeq(multiStepDO.v_current_step), " ");
        Map wflOrTaskRrnAndVersionMap = workFlowExcuteManager
                .getWflOrTaskRrnAndVersionFromWorkflowTemplateDetail(multiStepDO.v_next_route_step);
        multiStepDO.v_temp_string = MapUtils.getString(wflOrTaskRrnAndVersionMap, "wfl_or_task_rrn");


        if ("130".equals(multiStepDO.v_temp_string)) {
            return getNextMultiStepInfoSplitWfl(multiStepDO);
        } else if ("140".equals(multiStepDO.v_temp_string)) {
            return getNextMultiStepInfoJoinWfl(multiStepDO);
        }

        return getNextMultiStepInfoGetOperation(multiStepDO);
    }

    private String getNextMultiStepInfoSplitWfl(NextMultiStepInfoDO multiStepDO) {
        multiStepDO.v_and_or_flag = workFlowExcuteManager
                .getParameterValue1FromWorkflowTemplateDetail(multiStepDO.v_next_route_step);
        // or split
        if ("Value.1".equals(multiStepDO.v_and_or_flag)) {
            multiStepDO.v_next_step_rrn = workFlowExcuteManager
                    .getMinWflNextStepRrnFromWorkflowLink(multiStepDO.v_next_step_rrn);
            multiStepDO.v_temp_count = workFlowExcuteManager
                    .getWorkflowTemplateDetailCount(multiStepDO.v_next_step_rrn);
            Assert.state(multiStepDO.v_temp_count != 0,
                         Errors.create().content("or split:Not found this step in " + "workflow_template_detail!")
                               .build());
            return getNextMultiStepInfoGetOperation(multiStepDO);
        }
        //and split
        if ("Value.0".equals(multiStepDO.v_and_or_flag)) {
            multiStepDO.v_temp_rrn = multiStepDO.v_next_route_step;
            multiStepDO.v_next_step_rrn = workFlowExcuteManager
                    .getMinWflNextStepRrnFromWorkflowLink(multiStepDO.v_next_step_rrn, multiStepDO.v_str_executionrrn,
                                                          multiStepDO.v_str_executionrrn);
            multiStepDO.v_temp_count = workFlowExcuteManager
                    .getWorkflowTemplateDetailCount(multiStepDO.v_next_step_rrn);
            Assert.state(multiStepDO.v_temp_count != 0,
                         Errors.create().content("and split:Not found this step in " + "workflow_template_detail!")
                               .build());
            workFlowExcuteManager
                    .updateSplitProcessed2FromWorkflowLink(multiStepDO.v_str_executionrrn, multiStepDO.v_temp_rrn,
                                                           multiStepDO.v_next_step_rrn);
            return getNextMultiStepInfoGetOperation(multiStepDO);
        }
        return getNextMultiStepInfoJoinWfl(multiStepDO);
    }

    private String getNextMultiStepInfoJoinWfl(NextMultiStepInfoDO multiStepDO) {
        String value1 = PostgreSqlUtil.substr(workFlowExcuteManager.getParameterValue1FromWorkflowTemplateDetail(
                multiStepDO.v_next_route_step), 6);
        multiStepDO.v_split_rrn = value1 == null ? null : NumberUtils.toLong(value1);
        multiStepDO.v_and_or_flag = workFlowExcuteManager
                .getParameterValue1FromWorkflowTemplateDetail(multiStepDO.v_split_rrn);
        //or join
        if ("Value.1".equals(multiStepDO.v_and_or_flag)) {
            multiStepDO.v_next_route_step = workFlowExcuteManager
                    .getWflNextStepRrnFromWorkflowLink(multiStepDO.v_next_route_step);
            return getNextMultiStepInfoGetOperation(multiStepDO);
        }
        //and join
        if ("Value.0".equals(multiStepDO.v_and_or_flag)) {
            multiStepDO.v_temp_count = workFlowExcuteManager
                    .getWorkflowLinkCount(multiStepDO.v_split_rrn, multiStepDO.v_str_executionrrn);
            if (multiStepDO.v_temp_count == 0) {
                multiStepDO.v_next_route_step = workFlowExcuteManager
                        .getWflNextStepRrnFromWorkflowLink(multiStepDO.v_next_route_step);
                return getNextMultiStepInfoGetOperation(multiStepDO);
            }
            multiStepDO.v_current_route = multiStepDO.v_split_rrn;
            return getNextMultiStepInfoTryGetNextStep2(multiStepDO);
        }
        return getNextMultiStepInfoGetOperation(multiStepDO);
    }

    private String getNextMultiStepInfoGetOperation(NextMultiStepInfoDO multiStepDO) {
        Map wflOrTaskRrnAndVersionMap = workFlowExcuteManager
                .getWflOrTaskRrnAndVersionFromWorkflowTemplateDetail(multiStepDO.v_next_route_step);
        multiStepDO.v_next_route_rrn = MapUtils.getLong(wflOrTaskRrnAndVersionMap, "wfl_or_task_rrn");
        multiStepDO.v_tem_route_ver = MapUtils.getLong(wflOrTaskRrnAndVersionMap, "wfl_or_task_version");
        if (multiStepDO.v_tem_route_ver > 0) {
            multiStepDO.v_next_route_ver = multiStepDO.v_tem_route_ver;
        } else {
            multiStepDO.v_next_route_ver = workFlowExcuteManager.getActiveVersion(multiStepDO.v_next_route_rrn);
        }
        if (120 == multiStepDO.v_next_route_rrn) {
            return getNextMultiStepInfoEnd(multiStepDO);
        }
        multiStepDO.v_temp_count = workFlowExcuteManager
                .getWorkflowTemplateCount(multiStepDO.v_next_route_rrn, multiStepDO.v_next_route_ver);
        Assert.state(multiStepDO.v_temp_count != 0,
                     Errors.create().content("Not found this step v_next_route_rrn->{}," + "v_next_route_ver->{}")
                           .args(multiStepDO.v_next_route_rrn, multiStepDO.v_next_route_ver).build());
        multiStepDO.v_next_step_rrn = workFlowExcuteManager
                .getFirstStepRrnFromWorkflowTemplate(multiStepDO.v_next_route_rrn,
                                                     multiStepDO.v_next_route_ver.intValue());
        multiStepDO.v_next_step_rrn = workFlowExcuteManager
                .getWflNextStepRrnForTree(multiStepDO.v_next_step_rrn, multiStepDO.v_matching_rules,
                                          multiStepDO.v_next_route_rrn.toString(), " ", " ", workFlowExcuteManager
                                                  .getCurrentRouteSeq(multiStepDO.v_next_route_step.toString()), " ");

        Map map = workFlowExcuteManager
                .getWflTaskRrnAndParameterValue1FromWorkflowTemplateDetail(multiStepDO.v_next_step_rrn);
        multiStepDO.v_temp_string = MapUtils.getString(map, "wfl_or_task_rrn");
        multiStepDO.v_next_route_rrn = MapUtils.getLong(map, "wfl_rrn");
        multiStepDO.v_operation_rrn = MapUtils.getLong(map, "parameter_value_1");
        if ("100".equals(multiStepDO.v_temp_string)) {
            return getNextMultiStepInfoMakeNewStepPath(multiStepDO);
        } else {
            throw new SystemIllegalStateException(
                    Errors.create().content("GetOperation: wfl_or_task_rrn {} error.").args(multiStepDO.v_temp_string)
                          .build());
        }
    }

    private String getNextMultiStepInfoMakeNewStepPath(NextMultiStepInfoDO multiStepDO) {
        multiStepDO.v_temp_string = PostgreSqlUtil
                .substr(multiStepDO.v_current_step, 0, PostgreSqlUtil.instr(multiStepDO.v_current_step, ".", 0, 2) + 1);
        multiStepDO.v_new_setp_path =
                multiStepDO.v_temp_string + multiStepDO.v_next_route_step + "|" + multiStepDO.v_next_route_rrn + "." +
                        multiStepDO.v_next_route_ver + "." + multiStepDO.v_next_step_rrn +  WorkflowPath.PATH_SUFFIX;
        return getNextMultiStepInfoNextStep(multiStepDO);
    }

    private String getNextMultiStepInfoNextStep(NextMultiStepInfoDO multiStepDO) {
        String processRrnStr = PostgreSqlUtil
                .substr(multiStepDO.v_new_setp_path, 0, PostgreSqlUtil.instr(multiStepDO.v_new_setp_path, ".", 0, 1));
        multiStepDO.v_process_rrn = StringUtils.isBlank(processRrnStr) ? null : Long.valueOf(processRrnStr);
        multiStepDO.v_temp_string = PostgreSqlUtil
                .substr(multiStepDO.v_new_setp_path, 0, multiStepDO.v_new_setp_path.length() - 2);
        multiStepDO.outList =
                multiStepDO.outList + multiStepDO.v_process_rrn + "," + multiStepDO.v_next_route_rrn + "," +
                        multiStepDO.v_operation_rrn + "," + multiStepDO.v_temp_string + "~";
        multiStepDO.v_time -= 1;
        if (multiStepDO.v_time < 1) {
            return getNextMultiStepInfoEnd(multiStepDO);
        } else {
            multiStepDO.v_current_step = multiStepDO.v_new_setp_path;
            return getNextMultiStepInfoNextStepFinder(multiStepDO);
        }
    }

    private String getNextMultiStepInfoEnd(NextMultiStepInfoDO multiStepDO) {
        workFlowExcuteManager.initSplitProcessed2FromWorkflowLink();
        return multiStepDO.outList;
    }

    WorkflowStepModel getWorkFlowStepForStartOrEnd(Long workflowRrn, Integer workflowVersion, Long activityRrn) {
        long workflowStep = workflowViewDAO.findStartOrEndStep(workflowRrn, workflowVersion, activityRrn);
        return workflowEditorService.getWorkFlowTemplateDetailByStepRrn(workflowStep);
    }

    protected void makeStr(Long rrn, String objectVersion, StringBuffer sbRrn) {
        if ((rrn != null) && (rrn.longValue() != 0)) {
            if (StringUtils.isEmpty(objectVersion)) {
                objectVersion = (new Integer(objectVersionManager.getActiveVersion(rrn.longValue(), true))).toString();
            }
            // sample: 111.1|222.3|444.3
            sbRrn.append(rrn);
            sbRrn.append(",");
            sbRrn.append(objectVersion);
        }
    }

}