# 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);
            }
        }

    }