SpecTableGridAction.java

package com.mycim.webapp.actions.wflinfo;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.context.spring.SpringContext;
import com.mycim.framework.utils.lang.ObjectUtils;
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.utils.msg.JsonUtils;
import com.mycim.server.wip.service.LotQueryService;
import com.mycim.server.wip.service.LotRunCardQueryService;
import com.mycim.utils.WflLinkContextSetupAttributeUtil;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.SystemConstant;
import com.mycim.valueobject.bas.NamedObject;
import com.mycim.valueobject.consts.ContextNames;
import com.mycim.valueobject.consts.TransRoutineNames;
import com.mycim.valueobject.consts.TransactionNames;
import com.mycim.valueobject.ems.pilot.PiLotView;
import com.mycim.valueobject.prp.*;
import com.mycim.valueobject.wip.Lot;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.PrpSetupAction;
import com.mycim.webapp.forms.WflInfoForm;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.Override;
import java.util.*;

/**
 * @author Sola
 * @date 2021/12/21
 **/
public class SpecTableGridAction extends PrpSetupAction {

    private final String TREE_AFTER = "TREE_AFTER";

    private final String TREE_GRID_ALL = "TREE_GRID_ALL";

    private final String TREE_REWORK_ALL = "TREE_REWORK_ALL";

    private final String MOVEOUT_AUTOBONDED_STD = "MOVEOUT_AUTOBONDED_STD";

    private final String MOVEOUT_AUTODEBONDED_STD = "MOVEOUT_AUTODEBONDED_STD";

    private final String RUNCARD_TREE = "RUNCARD_TREE";

    private final String FH_FLAG = "isFutureHold";

    @Autowired
    private LotRunCardQueryService lotRunCardQueryService =  SpringContext.getBean(LotRunCardQueryService.class);

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        WflInfoForm theform = (WflInfoForm) form;

        parseCondtionForWflInfo(theform, request);

        request.setAttribute("from", WebUtils.getParameterNoTrim("from", request));
        request.setAttribute("qryActiveOrFrozenVersionFlag", WebUtils.getParameter("qryActiveOrFrozenVersionFlag", request));
        request.setAttribute("isRework", WebUtils.getParameterBoolean("isRework", request));
        request.setAttribute("orientateCurrByFLowSeq", WebUtils.getParameter("orientateCurrByFLowSeq", request));
        request.setAttribute("containsRework", WebUtils.getParameter("containsRework", request));
        request.setAttribute("showContextSet", WebUtils.getParameter("showContextSet", request));
        request.setAttribute("callbackFlag", request.getParameter("callbackFlag"));
        request.setAttribute("noEditFlag", WebUtils.getParameter("noEditFlag", request));
        request.setAttribute("isActive", WebUtils.getParameter("isActive", request));
        request.setAttribute("processVer", WebUtils.getParameter("processVersion", request));
        if(StringUtils.isBlank(WebUtils.getParameter("processVersion", request))){
            request.setAttribute("processVer",WebUtils.getParameter("processVer", request));
        }
        request.setAttribute("showStageFlag", WebUtils.getParameter("showStageFlag", request));
        request.setAttribute("routeSeq", request.getParameter("routeSeq"));
        request.setAttribute("routeId", WebUtils.getParameter("routeId", request));
        request.setAttribute("operationSeq", request.getParameter("operationSeq"));
        request.setAttribute("lotRrn", WebUtils.getParameterLong("lotRrn", request));
        request.setAttribute("lotId", WebUtils.getParameterNoTrim("lotId", request));
        request.setAttribute("CONDTIONFORM_INIT_VALUES", JsonUtils.toString(theform));
        request.setAttribute("IDS", JsonUtils.toString(theform));

        String filterType = WebUtils.getParameter("filterType", request);
        String targetReqCode = StringUtils.EMPTY;
        if(filterType.equals(TREE_GRID_ALL)) {
            targetReqCode = "qrySpecGridForTreeGridAll";
        }
        else if(filterType.equals(TREE_AFTER)) {
            targetReqCode = "qrySpecGridForTreeAfter";
        }
        else if(filterType.equals(TREE_REWORK_ALL)) {
            targetReqCode = "qrySpecGridForTreeReworkAll";
        }
        else if(filterType.equals(MOVEOUT_AUTODEBONDED_STD) || filterType.equals(MOVEOUT_AUTOBONDED_STD)) {
            targetReqCode = "qrySpecGridForTreeBondedOrDebond";
        }
        else if(filterType.equals(RUNCARD_TREE)) {
            targetReqCode = "qrySpecGridForRunCard";
        }
        else {
            targetReqCode = "qrySpecGridForTreeAllStep";
        }
        request.setAttribute("targetReqCode", targetReqCode);

        return mapping.findForward("init");
    }


    /**
     * filterType : TREE_GRID_ALL
     **/
    public List<Map<String, Object>> qrySpecGridForTreeGridAll(Map<String, Object> theform, HttpServletRequest request){

        checkAndGetProductProcessRrn(theform);

        Long productRrn = MapUtils.getLong(theform, "productRrn");
        String productId = MapUtils.getString(theform, "productId");
        if(StringUtils.isEmpty(productId) && productRrn!=null){
            productId = getInstanceId(productRrn);
        }
        int productVersion = MapUtils.getIntValue(theform, "productVersion");
        String processId = MapUtils.getString(theform, "processId");
        Long processRrn = MapUtils.getLong(theform, "processRrn");
        int processVersion = MapUtils.getIntValue(theform,"processVersion");
        int processVer = MapUtils.getIntValue(theform, "processVer");
        processVersion = processVersion <= 0 && processVer > 0 ? processVer : processVersion;
        if(processVersion <= 0) {
            processVersion = specService.getLatestActivatedProcessVersion(productRrn, processRrn);
        }
        String lotId = MapUtils.getString(theform, "lotId");
        long lotRrn = MapUtils.getLongValue(theform, "lotRrn");
        if(lotRrn <= 0) {
            lotRrn = lotQueryService.getLotRrn(lotId);
        }

        Map<String, Object> matchingRules = new HashMap<>();
        matchingRules.put("productRrn", productRrn);
        matchingRules.put("processRrn", processRrn);
        matchingRules.put("qryActiveOrFrozenVersionFlag", MapUtils.getString(theform, "qryActiveOrFrozenVersionFlag"));
        List wflTree = prpService.getWorkFlowTree(processRrn, processVersion, matchingRules);

        List<Map<String, Object>> nodes = new ArrayList<>();
        if (CollectionUtils.isEmpty(wflTree)) {
            return nodes;
        }
        if(StringUtils.isNotEmptyTrim(lotId)) {
            lotRrn = lotQueryService.getLotRrn(lotId);
        }

        //一次性获取process所有step设置的FH
        List<FutureHold> allFutureHoldList = getAllFutureHoldList(processRrn, productRrn, lotRrn);
        //一次性获取process的情景值
        List<ProductSpecItemDto> productSpecItemDtos = specService.queryTheCompleteProcessSpecification(productRrn, productVersion, processId, processVersion);

        //build notes
        String routeSeq = null;
        String routeId = null;
        String routeDesc = null;
        long routeRrn = 0;
        int stepSeq = 0;
        for (int i = 0; i < wflTree.size(); i++) {
            Map<String, Object> node = new HashMap<>();
            String[] treeNodes = (String[]) wflTree.get(i);
            if ("0".equals(treeNodes[7])) {
                routeSeq = StringUtils.substringBefore(treeNodes[2], "---");
                routeId = StringUtils.substringAfter(treeNodes[2], "---");
                routeRrn = NumberUtils.toLong(treeNodes[4], 0);
                routeDesc = treeNodes[5];
                node.put("routeSeq", routeSeq);
                node.put("routeId", routeId);
                node.put("routeDesc", routeDesc);
                node.put("routeRrn", routeRrn);
                node.put("isRoute", new Boolean(true));
            } else if ("1".equals(treeNodes[7])) {
                String wflStep = treeNodes[6];
                node.put("operationSeq", StringUtils.substringBefore(treeNodes[2], "---"));
                node.put("operationId", StringUtils.substringAfter(treeNodes[2], "---"));
                node.put("operationRrn", NumberUtils.toLong(treeNodes[4], 0));
                node.put("routeSeq", routeSeq);
                node.put("routeId", routeId);
                node.put("routeDesc", routeDesc);
                node.put("routeRrn", routeRrn);
                node.put("productId", MapUtils.getString(theform, "productId"));
                node.put("productRrn", productRrn);
                node.put("processId", processId);
                node.put("processRrn", processRrn);
                node.put("processVersion", processVersion);
                node.put("facilityRrn", LocalContext.getFacilityRrn());
                node.put("stepPath", wflStep);
                node.put("stepNumber", wflStep);
                node.put("stepSeq", ++stepSeq);
                node.put("lotRrn", lotRrn);
                node.put("lotId", lotId);

                buildStepInfo(node,productSpecItemDtos);

                if(CollectionUtils.isNotEmpty(allFutureHoldList)){
                    checkFutureHoldStep(node,allFutureHoldList);
                }
                nodes.add(node);
            }
        }
        return nodes;
    }

    /**
     * filterType : TREE_AFTER
     **/
    public List<Map<String, Object>> qrySpecGridForTreeAfter(Map<String, Object> theform, HttpServletRequest request){

        checkAndGetProductProcessRrn(theform);

        Long productRrn = MapUtils.getLong(theform, "productRrn");
        String productId = MapUtils.getString(theform, "productId");
        if(StringUtils.isEmpty(productId) && productRrn!=null){
            productId = getInstanceId(productRrn);
        }
        int productVersion = MapUtils.getIntValue(theform,"productVersion");
        String processId = MapUtils.getString(theform, "processId");
        Long processRrn = MapUtils.getLong(theform, "processRrn");
        int processVersion = MapUtils.getIntValue(theform,"processVersion");
        int processVer = MapUtils.getIntValue(theform, "processVer");
        processVersion = processVersion <= 0 && processVer > 0 ? processVer : processVersion;
        if(processVersion <= 0) {
            processVersion = specService.getLatestActivatedProcessVersion(productRrn, processRrn);
        }
        long executionRrn = MapUtils.getLongValue(theform, "executionRrn");

        String lotId = MapUtils.getString(theform, "lotId");
        Long lotRrn = lotQueryService.getLotRrnByExecutionRrn(executionRrn);
        if(lotRrn == null || lotRrn <= 0) {
            lotRrn = lotQueryService.getLotRrn(lotId);
        }
        Lot lot = lotQueryService.getLot(lotRrn);

        List<Map<String, Object>> viewProcessInfo = prpService.getProcessAllMainStepInfo(processRrn, processVersion);
        List<Map<String, Object>> allProcessStep = prpService.getProcessAllStepInfo(processRrn, processVersion, null, null, new Long(99999), null, null, 0);

        //一次性获取process所有step设置的FH
        List<FutureHold> allFutureHoldList = getAllFutureHoldList(processRrn, productRrn, lotRrn);
        //一次性获取process的情景值
        List<ProductSpecItemDto> productSpecItemDtos = specService.queryTheCompleteProcessSpecification(productRrn, productVersion, processId, processVersion);

        //buildViewProcessInfoForTreeAfter
        viewProcessInfo = buildViewProcessInfoForTreeAfter(viewProcessInfo,allProcessStep,productSpecItemDtos,lot);

        List<Map<String, Object>> nodes = new ArrayList<>();
        int stepSeq = 0;
        for (Map treeNodes : viewProcessInfo) {
            treeNodes.put("routeSeq", MapUtils.getString(treeNodes, "routeProcessSeq"));
            treeNodes.put("operationSeq",MapUtils.getString(treeNodes, "operationRouteSeq"));
            treeNodes.put("productRrn", productRrn);
            treeNodes.put("productId", productId);
            treeNodes.put("stepSeq", ++stepSeq);
            treeNodes.put("lotId",lotId);
            treeNodes.put("lotRrn",lotRrn);
            String wflStep = buildWflStep(treeNodes);
            treeNodes.put("stepPath", wflStep);
            treeNodes.put("stepNumber", wflStep);

            buildStepInfo(treeNodes,productSpecItemDtos);

            if(CollectionUtils.isNotEmpty(allFutureHoldList)){
                checkFutureHoldStep(treeNodes,allFutureHoldList);
            }

            nodes.add(treeNodes);
        }
        //defalut step标记
        setMultipathAndDefaultStepFlag(nodes);

        return nodes;
    }

    /**
     * filterType : TREE_REWORK_ALL
     **/
    public List<Map<String, Object>> qrySpecGridForTreeReworkAll(Map<String, Object> theform, HttpServletRequest request){

        checkAndGetProductProcessRrn(theform);

        Long productRrn = MapUtils.getLong(theform, "productRrn");
        String productId = MapUtils.getString(theform, "productId");
        if(StringUtils.isEmpty(productId) && productRrn!=null){
            productId = getInstanceId(productRrn);
        }
        int productVersion = MapUtils.getIntValue(theform,"productVersion");
        String processId = MapUtils.getString(theform, "processId");
        Long processRrn = MapUtils.getLong(theform, "processRrn");
        int processVersion = MapUtils.getIntValue(theform,"processVersion");
        int processVer = MapUtils.getIntValue(theform, "processVer");
        processVersion = processVersion <= 0 && processVer > 0 ? processVer : processVersion;
        if(processVersion <= 0) {
            processVersion = specService.getLatestActivatedProcessVersion(productRrn, processRrn);
        }

        String lotId = MapUtils.getString(theform, "lotId");
        long lotRrn = MapUtils.getLongValue(theform, "lotRrn");
        if(lotRrn <= 0) {
            lotRrn = lotQueryService.getLotRrn(lotId);
        }

        List<Map<String, Object>> allProcessStep = prpService.getProcessAllStepInfo(processRrn, processVersion, null, null, 99999L, productRrn, null, 0);

        //一次性获取process所有step设置的FH
        List<FutureHold> allFutureHoldList = getAllFutureHoldList(processRrn, productRrn, lotRrn);
        //一次性获取process的情景值
        List<ProductSpecItemDto> productSpecItemDtos = specService.queryTheCompleteProcessSpecification(productRrn, productVersion, processId, processVersion);

        List<Map<String, Object>> reworkLists = new ArrayList<>();
        List<Map<String, Object>> reworkNodes = new ArrayList<>();
        for (Map<String, Object> mainProStep : allProcessStep) {
            reworkNodes = buildReworkWflInfo(mainProStep,productSpecItemDtos);
            for(Map<String, Object> reworkNode : reworkNodes){
                if(!reworkLists.contains(reworkNode)){
                    reworkLists.add(reworkNode);
                }
            }
        }

        int stepSeq = 0;
        List<Map<String, Object>> nodes = new ArrayList<>();
        for (Map<String, Object> treeNodes : reworkLists) {
            treeNodes.put("routeSeq", MapUtils.getString(treeNodes, "routeProcessSeq"));
            treeNodes.put("operationSeq",MapUtils.getString(treeNodes, "operationRouteSeq"));
            treeNodes.put("productRrn", productRrn);
            treeNodes.put("productId", productId);
            treeNodes.put("stepSeq", ++stepSeq);
            treeNodes.put("lotId", lotId);
            treeNodes.put("lotRrn", lotRrn);
            String wflStep = buildWflStep(treeNodes);
            treeNodes.put("stepPath", wflStep);
            treeNodes.put("stepNumber", wflStep);

            if(CollectionUtils.isNotEmpty(allFutureHoldList)){
                checkFutureHoldStep(treeNodes,allFutureHoldList);
            }

            nodes.add(treeNodes);
        }
        //defalut step标记
        setMultipathAndDefaultStepFlag(nodes);

        return nodes;
    }

    /**
     * filterType : MOVEOUT_AUTOBONDED_STD | MOVEOUT_AUTODEBONDED_STD
     **/
    public List<Map<String, Object>> qrySpecGridForTreeBondedOrDebond(Map<String, Object> theform, HttpServletRequest request){

        checkAndGetProductProcessRrn(theform);

        String filterType = MapUtils.getString(theform, "filterType");
        Long productRrn = MapUtils.getLong(theform, "productRrn");
        String productId = MapUtils.getString(theform, "productId");
        if(StringUtils.isEmpty(productId) && productRrn!=null){
            productId = getInstanceId(productRrn);
        }
        int productVersion = MapUtils.getIntValue(theform,"productVersion");
        String processId = MapUtils.getString(theform, "processId");
        Long processRrn = MapUtils.getLong(theform, "processRrn");
        int processVersion = MapUtils.getIntValue(theform,"processVersion");
        int processVer = MapUtils.getIntValue(theform, "processVer");
        processVersion = processVersion <= 0 && processVer > 0 ? processVer : processVersion;
        if(processVersion <= 0) {
            // 获取最新的process 和 context 都 active的version
            ProductSpecInfo productSpecInfo = specService.getLatestActivatedProductSpecItemInfo(productRrn, processRrn);
            if (!Objects.isNull(productSpecInfo)) {
                processVersion = productSpecInfo.getProcessVersion();
            }
        }

        String lotId = MapUtils.getString(theform, "lotId");
        long lotRrn = MapUtils.getLongValue(theform, "lotRrn");
        if(lotRrn <= 0) {
            lotRrn = lotQueryService.getLotRrn(lotId);
        }

        List<Map<String, Object>> allProcessStep = prpService.getProcessAllStepInfo(processRrn, processVersion, null, null, 99999L, productRrn, null, 0);
        Map<String,Object> map = new HashMap<>();
        map.put("productRrn",productRrn);
        map.put("productId",productId);
        map.put("productVersion",productVersion);
        map.put("processRrn",processRrn);
        map.put("processId",processId);
        map.put("processVersion",processVersion);

        return qrySpecGridForTreeDebonded(allProcessStep, map, filterType, request);
    }


    /**
     * filterType : RUNCARD_TREE
     **/
    public List<Map<String, Object>> qrySpecGridForRunCard(Map<String, Object> theform, HttpServletRequest request){
        checkAndGetProductProcessRrn(theform);
        String lotId = MapUtils.getString(theform,"lotId");
        String productId = MapUtils.getString(theform,"productId");
        Long productRrn = MapUtils.getLong(theform,"productRrn");
        Long processRrn = MapUtils.getLong(theform,"processRrn");
        long lotRrn = MapUtils.getLongValue(theform, "lotRrn");
        if(lotRrn <= 0) {
            lotRrn = lotQueryService.getLotRrn(lotId);
        }
        //一次性获取process所有step设置的FH
        List<FutureHold> allFutureHoldList = getAllFutureHoldList(processRrn, productRrn, lotRrn);

        List<Map<String,Object>> nodes = lotRunCardQueryService.getRunCardGridInfo(lotId);

        int stepSeq = 0;
        for(Map<String,Object> node : nodes){
            node.put("productId",productId);
            node.put("productRrn",productRrn);
            node.put("stepSeq",++stepSeq);
            node.put("lotId",lotId);
            node.put("lotRrn",lotRrn);
            if(StringUtils.isEmpty(MapUtils.getString(node,"reticleFamilyId"))){
                node.put("reticleFamilyId","");
            }
            if(StringUtils.isEmpty(MapUtils.getString(node,"eqptGroupId"))){
                node.put("eqptGroupId","");
            }
            if(StringUtils.isEmpty(MapUtils.getString(node,"contamination"))){
                node.put("contamination","");
            }
            checkFutureHoldStep(node,allFutureHoldList);
        }
        return nodes;
    }


    public List<Map<String, Object>> qrySpecGridForTreeAllStep(Map<String, Object> theform, HttpServletRequest request){

        checkAndGetProductProcessRrn(theform);

        boolean containsReworkFlag = StringUtils.equalsIgnoreCase("Y", MapUtils.getString(theform, "containsRework"));
        Long productRrn = MapUtils.getLong(theform, "productRrn");
        String productId = MapUtils.getString(theform, "productId");
        if(StringUtils.isEmpty(productId) && productRrn!=null){
            productId = getInstanceId(productRrn);
        }
        int productVersion = MapUtils.getIntValue(theform,"productVersion");
        String processId = MapUtils.getString(theform, "processId");
        Long processRrn = MapUtils.getLong(theform, "processRrn");
        int processVersion = MapUtils.getIntValue(theform,"processVersion");
        int processVer = MapUtils.getIntValue(theform, "processVer");
        processVersion = processVersion <= 0 && processVer > 0 ? processVer : processVersion;

        if(processVersion <= 0) {
            processVersion = specService.getLatestActivatedProcessVersion(productRrn, processRrn);
        }

        String lotId = MapUtils.getString(theform, "lotId");
        long lotRrn = MapUtils.getLongValue(theform, "lotRrn");
        if(lotRrn <= 0) {
            lotRrn = lotQueryService.getLotRrn(lotId);
        }

        List<Map<String, Object>> allProcessStep = prpService.getProcessAllStepInfo(processRrn, processVersion, null, null, 99999L, productRrn, productVersion, 0);

        //一次性获取process所有step设置的FH
        List<FutureHold> allFutureHoldList = getAllFutureHoldList(processRrn,productRrn,lotRrn);
        //一次性获取process的情景值
        List<ProductSpecItemDto> productSpecItemDtos = specService.queryTheCompleteProcessSpecification(productRrn, null, processId, processVersion);

        int stepSeq = 0;
        List<Map<String, Object>> reworkLists = new ArrayList();
        List<Map<String, Object>> nodes = new ArrayList<>();
        for (Map<String, Object> map : allProcessStep) {
            if (containsReworkFlag) {
                // 添加 rework 信息
                List<Map<String, Object>> reworkNodes = buildReworkWflInfo(map,productSpecItemDtos);
                for(Map<String, Object> reworkNode : reworkNodes){
                    if(!reworkLists.contains(reworkNode)){
                        reworkLists.add(reworkNode);
                    }
                }
            }
            nodes.add(map);
        }

        nodes.addAll(reworkLists);

        for (Map<String, Object> node : nodes) {
            node.put("routeSeq", MapUtils.getString(node, "routeProcessSeq"));
            node.put("operationSeq",MapUtils.getString(node, "operationRouteSeq"));
            node.put("productRrn", productRrn);
            node.put("productId", productId);
            node.put("facilityRrn", LocalContext.getFacilityRrn());
            node.put("lotRrn",lotRrn);
            node.put("lotId",lotId);
            node.put("stepSeq", ++stepSeq);
            String wflStep = buildWflStep(node);
            node.put("stepPath", wflStep);
            node.put("stepNumber", wflStep);

            buildStepInfo(node,productSpecItemDtos);

            if(CollectionUtils.isNotEmpty(allFutureHoldList)){
                checkFutureHoldStep(node,allFutureHoldList);
            }
        }

        //defalut step标记
        setMultipathAndDefaultStepFlag(nodes);

        // 处理pilot 子母批跳步 #41886
        if (lotRrn > 0){
            return buildPilotRepositionStep(lotRrn,nodes);
        } else {
            return nodes;
        }
    }

    /**
     * 将process对应的multipath和default step都做上标记
     **/
    private void setMultipathAndDefaultStepFlag(List<Map<String, Object>> nodes) {
        List<ProcessSpecItemDto> processSpecItemList = new ArrayList<>();
        for(Map<String, Object> node : nodes){
            ProcessSpecItemDto processSpecItem = new ProcessSpecItemDto();
            processSpecItem.setProcessRrn(MapUtils.getLong(node,"processRrn"));
            processSpecItem.setProcessVersion(MapUtils.getInteger(node,"processVersion"));
            processSpecItem.setRouteRrn(MapUtils.getLong(node,"routeRrn"));
            processSpecItem.setOperationRrn(MapUtils.getLong(node,"operationRrn"));
            processSpecItemList.add(processSpecItem);
        }
        List<ProcessSpecItemDto> processSpecItemDtos = processSpecService.setMultipathAndDefaultStepFlag(processSpecItemList);

        for(ProcessSpecItemDto processSpecItemDto : processSpecItemDtos){
            for(Map<String, Object> node : nodes){
                if(MapUtils.getLong(node,"routeRrn").equals(processSpecItemDto.getRouteRrn()) &&
                        MapUtils.getLong(node,"operationRrn").equals(processSpecItemDto.getOperationRrn())){
                    node.put("multipathAndDefaultStepFlag",processSpecItemDto.getMultipathAndDefaultStepFlag());
                }
            }
        }
    }

    /**
     * 构建pilot子母批 跳步
     **/
    private List<Map<String, Object>> buildPilotRepositionStep(Long lotRrn, List<Map<String, Object>> nodes){
        Lot lot = lotQueryService.getLot(lotRrn);
        PiLotView view = wipQueryService.getPiLotViewByLotRrn(lot.getBasedLotRrn());
        Map<String, Object> startMap = new HashMap<>();
        Map<String, Object> endMap = new HashMap<>();
        if(ObjectUtils.isNotEmpty(view)){
            for (Map<String, Object> map : nodes) {
                if(StringUtils.equalsIgnoreCase(view.getStartRoute(), MapUtils.getString(map,"routeId")) &&
                        StringUtils.equalsIgnoreCase(view.getStartStep(), MapUtils.getString(map, "operationId"))){
                    startMap = map;
                }
                if (StringUtils.equalsIgnoreCase(view.getEndRoute(), MapUtils.getString(map,"routeId")) &&
                        StringUtils.equalsIgnoreCase(view.getEndStep(), MapUtils.getString(map, "operationId"))){
                    endMap = map;
                }
            }
            List<Map<String, Object>> mapList = new ArrayList<>();
            for (Map<String, Object> pilotMap : nodes){
                if (MapUtils.getLongValue(pilotMap, "flowSeq") >= MapUtils.getLongValue(startMap, "flowSeq") &&
                        MapUtils.getLongValue(pilotMap, "flowSeq") < MapUtils.getLongValue(endMap, "flowSeq")) {
                    mapList.add(pilotMap);
                }
            }
            return mapList;
        } else {
            return nodes;
        }
    }


    private List<Map<String, Object>> buildViewProcessInfoForTreeAfter(List<Map<String, Object>> viewProcessInfo,List<Map<String, Object>> allProcessStep,List<ProductSpecItemDto> productSpecItemDtos,Lot lot){
        //buildViewProcessInfo4Branch
        if (CollectionUtils.isNotEmpty(viewProcessInfo) && CollectionUtils.isNotEmpty(allProcessStep)) {
            for (int i = 0; i < viewProcessInfo.size(); i++) {
                Map<String, Object> mainProStep = viewProcessInfo.get(i);
                for (int j = 0; j < allProcessStep.size(); j++) {
                    Map<String, Object> tempStep = allProcessStep.get(j);
                    if (MapUtils.getLongValue(mainProStep, "routeRrn") == MapUtils.getLongValue(tempStep, "routeRrn") &&
                            MapUtils.getLongValue(mainProStep, "operationRrn") ==
                                    MapUtils.getLongValue(tempStep, "operationRrn") && StringUtils
                            .equals(MapUtils.getString(mainProStep, "routeProcessSeq"),
                                    MapUtils.getString(tempStep, "routeProcessSeq")) && StringUtils
                            .equals(MapUtils.getString(mainProStep, "operationRouteSeq"),
                                    MapUtils.getString(tempStep, "operationRouteSeq"))) {
                        mainProStep.put("flowSeq",MapUtils.getString(tempStep,"flowSeq"));
                        mainProStep.put("stageId",MapUtils.getString(tempStep,"stageId"));
                        mainProStep.put("contextOperationDesc",MapUtils.getString(tempStep,"contextOperationDesc"));
                        mainProStep.put("isMain", '1');
                        allProcessStep.set(j, mainProStep);
                        break;
                    }
                }
            }
            viewProcessInfo = allProcessStep;
        }

        //buildViewProcessInfo4Type
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        List<Map<String, Object>> reworkList = new ArrayList<Map<String, Object>>();
        Long operationRrn = lot.getOperationRrn();
        Long routeRrn = lot.getRouteRrn();
        String operationSeq = lot.getOperationSeq();
        boolean opreationFlag = false;
        for (Map<String, Object> mainProStep : viewProcessInfo) {
            Long tempOperationRrn = MapUtils.getLong(mainProStep, "operationRrn");
            Long tempRouteRrn = MapUtils.getLong(mainProStep, "routeRrn");
            String stepSeq = MapUtils.getString(mainProStep, "operationRouteSeq");
            mainProStep.put("routeSeq", MapUtils.getString(mainProStep, "routeProcessSeq"));
            mainProStep.put("operationSeq", MapUtils.getString(mainProStep, "operationRouteSeq"));
            mainProStep.put("productRrn", lot.getProductRrn());
            mainProStep.put("productId",lot.getProductId());
            String stepNumber = buildWflStep(mainProStep);
            mainProStep.put("stepNumber", stepNumber);
            mainProStep.put("stepPath", stepNumber);
            if (opreationFlag) {
                list.add(mainProStep);
            }
            if (operationRrn.longValue() == tempOperationRrn.longValue() &&
                    routeRrn.longValue() == tempRouteRrn.longValue() &&
                    StringUtils.equalsIgnoreCase(operationSeq, stepSeq)) {
                opreationFlag = true;
            }
        }

        if (!opreationFlag) {
            for (Map<String, Object> mainProStep : viewProcessInfo) {
                List reworkinfo = buildReworkWflInfo(mainProStep,productSpecItemDtos);
                if (CollectionUtils.isNotEmpty(reworkinfo) && !reworkList.containsAll(reworkinfo)) {
                    reworkList.addAll(reworkinfo);
                }
            }
            viewProcessInfo.addAll(reworkList);
        }else {
            viewProcessInfo = list;
        }

        return viewProcessInfo;
    }


    private List<Map<String, Object>> qrySpecGridForTreeDebonded(List<Map<String, Object>> allProcessStep,Map<String,Object> map, String filterType, HttpServletRequest request) {
        Long productRrn = MapUtils.getLong(map, "productRrn");
        String productId = MapUtils.getString(map, "productId");
        Long processRrn = MapUtils.getLong(map, "processRrn");
        String processId = MapUtils.getString(map, "processId");
        int processVersion = MapUtils.getIntValue(map, "processVersion");

        //一次性获取process所有step设置的FH
        List<FutureHold> allFutureHoldList = getAllFutureHoldList(processRrn,productRrn,0);
        //一次性获取process的情景值
        List<ProductSpecItemDto> productSpecItemDtos = specService.queryTheCompleteProcessSpecification(productRrn, null, processId, processVersion);

        int stepSeq = 0;
        List<Map<String, Object>> nodes = new ArrayList<>();
        for (Map<String, Object> node : allProcessStep) {
            long operationRrn = MapUtils.getLong(node, "operationRrn");
            Operation oper = prpService.getOperation(operationRrn);
            if (StringUtils.isNotBlank(filterType) && (!StringUtils.equals(oper.getMvouWflId(), filterType))) {
                continue;
            }

            buildStepInfo(node,productSpecItemDtos);

            node.put("routeSeq", MapUtils.getString(node, "routeProcessSeq"));
            node.put("operationSeq",MapUtils.getString(node, "operationRouteSeq"));
            node.put("productId",productId);
            node.put("produceRrn",productRrn);
            node.put("stepSeq",++stepSeq);
            String wflStep = buildWflStep(node);
            node.put("stepPath", wflStep);
            node.put("stepNumber", wflStep);

            if(CollectionUtils.isNotEmpty(allFutureHoldList)){
                checkFutureHoldStep(node,allFutureHoldList);
            }

            nodes.add(node);
        }

        //defalut step标记
        setMultipathAndDefaultStepFlag(nodes);

        return nodes;
    }

    /**
     * 校验Product Process
     */
    private void checkAndGetProductProcessRrn(Map<String, Object> theform) {
        String productId = MapUtils.getString(theform, "productId");
        String processId = MapUtils.getString(theform, "processId");

        Long productRrn = null;
        if (StringUtils.isNotBlank(productId)) {
            productId = StringUtils.trimToUpperCase(productId);
            NamedObject productObj = baseService.getNamedObject(
                    new NamedObject(productId, getNamedSpace(ObjectList.PRODUCT_KEY, LocalContext.getFacilityRrn()),
                                    ObjectList.PRODUCT_KEY));
            Assert.notNull(productObj,
                           Errors.create().key(MessageIdList.PRODUCT_PRODUCT_MISSING).content("Product does not exist!")
                                 .build());
            productRrn = productObj.getInstanceRrn();
        }

        Long processRrn = null;
        Assert.isTrue(StringUtils.isNotBlank(processId), Errors.create().content("process.empty_id").build());
        processId = StringUtils.trimToUpperCase(processId);
        NamedObject processObj = baseService.getNamedObject(
                new NamedObject(processId, getNamedSpace(ObjectList.WFL_KEY, LocalContext.getFacilityRrn()),
                                ObjectList.WFL_KEY));
        Assert.notNull(processObj, Errors.create().key(MessageIdList.PROCESS_PROCESS_MISSING).content("Process does not exist!").build());
        processRrn = processObj.getInstanceRrn();

        theform.put("productRrn",productRrn);
        theform.put("processRrn",processRrn);
    }

    /**
     * 一次性查询到lot/process对应所有step的future hold设置
     **/
    private List<FutureHold> getAllFutureHoldList(Long processRrn,Long productRrn,long lotRrn){
        long contextRrn = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDLOT, LocalContext.getFacilityRrn(), ObjectList.CONTEXT_KEY);
        List<FutureHold> allFutureHoldList = new ArrayList<>();
        if(lotRrn > 0) {
            List<FutureHold> futureHoldListByLot = ctxExecService.getAllFutureHoldListByLot(contextRrn, lotRrn);
            allFutureHoldList.addAll(futureHoldListByLot);
        }
        long contextRrnByProduct = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDPRODUCT,LocalContext.getFacilityRrn(), ObjectList.CONTEXT_KEY);
        List<FutureHold> futureHoldListByProduct = ctxExecService.getAllFutureHoldListByProduct(contextRrnByProduct,productRrn,processRrn);
        allFutureHoldList.addAll(futureHoldListByProduct);
        return allFutureHoldList;
    }

    /**
     * 校验当前步是否设置Future Hold
     **/
    private void checkFutureHoldStep(Map node,List<FutureHold> futureHoldList) {
        Long routeRrn = MapUtils.getLong(node, "routeRrn");
        Long operationRrn = MapUtils.getLong(node, "operationRrn");

        for(FutureHold futureHold : futureHoldList) {
            Long routeRrnFH = futureHold.getRouteRrn();
            Long operationRrnFH = futureHold.getOperationRrn();
            Long lotRrnFH = futureHold.getLotRrn();
            if(routeRrn.equals(routeRrnFH) && operationRrn.equals(operationRrnFH)){
                node.put(FH_FLAG,TRUE);
                break;
            }
        }
    }

    /**
     * 该step设置的futureHold详细信息
     **/
    public ActionForward viewFutureHoldlist(ActionMapping mapping, HttpServletRequest request) {
        Long facility = LocalContext.getFacilityRrn();
        String operationId = WebUtils.getParameter("operationId", request);
        String routeId = WebUtils.getParameter("routeId", request);
        String productId = WebUtils.getParameter("productId", request);
        String processId = WebUtils.getParameter("processId", request);
        long lotRrn = WebUtils.getParameterLong("lotRrn", request);

        long operationRrn = getInstanceRrn(operationId, facility, ObjectList.OPERATION_KEY);
        long routeRrn = getInstanceRrn(routeId, facility, ObjectList.WFL_KEY);
        long productRrn = getInstanceRrn(productId, getNamedSpace(ObjectList.PRODUCT_KEY, facility),
                                         ObjectList.PRODUCT_KEY);
        long processRrn = getInstanceRrn(processId, LocalContext.getFacilityRrn(),
                                         ObjectList.WFL_KEY);

        List futureHoldLotList = new ArrayList();
        Lot tempLot = lotQueryService.getLot(lotRrn);

        //check if it is future hold step (for EEN_CONTEXT_HOLDLOT and EEN_CONTEXT_HOLDPRODUCT)
        if(tempLot!=null){
            long contextRrnbyLot = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDLOT, facility, ObjectList.CONTEXT_KEY);
            futureHoldLotList = ctxExecService.getFutureHoldLotList(contextRrnbyLot, routeRrn, operationRrn, lotRrn, null, null);
        }
        long contextRrnbyProduct = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDPRODUCT, facility, ObjectList.CONTEXT_KEY);
        List futureHoldProductList = ctxExecService.getFutureHoldProductList(contextRrnbyProduct, routeRrn, operationRrn, lotRrn, productRrn, processRrn);
        futureHoldLotList.addAll(futureHoldProductList);

        request.setAttribute("futureHoldList", futureHoldLotList);
        request.setAttribute("processId", WebUtils.getParameter("processId", request));
        request.setAttribute("processVersion", WebUtils.getParameter("processVersion", request));
        request.setAttribute("routeSeq", WebUtils.getParameter("routeSeq", request));
        request.setAttribute("operationSeq", WebUtils.getParameter("stepSeq", request));
        request.setAttribute("operationId", operationId);
        request.setAttribute("operationDesc", WebUtils.getParameter("operationDesc", request));
        request.setAttribute("stepType", WebUtils.getParameter("stepType", request));
        request.setAttribute("flowseq", WebUtils.getParameter("flowseq", request));
        request.setAttribute("recipeId", WebUtils.getParameter("recipeId", request));
        request.setAttribute("stageId", WebUtils.getParameter("stageId", request));
        request.setAttribute("reticle", WebUtils.getParameter("reticle", request));
        request.setAttribute("contamination", WebUtils.getParameter("contamination", request));
        request.setAttribute("eqptGroupId", WebUtils.getParameter("eqptGroupId", request));
        return mapping.findForward("futureHoldList");
    }


    /**
     * 获取所有流程中的返工node信息
     **/
    private List<Map<String, Object>> buildReworkWflInfo(Map<String, Object> operationInfo, List<ProductSpecItemDto> productSpecItemDtos) {
        List<Map<String, Object>> wflInfos = new ArrayList<>();
        long reworkRouteRrn = ctxExecService.getProcessReworkRouteRrn(operationInfo);

        ReworkRouteContextValue reworkRouteContextValue = ctxExecService.buildNewReworkRouteContextValue();
        reworkRouteContextValue.setContextKey2(MapUtils.getString(operationInfo, "processRrn"));
        reworkRouteContextValue.setContextKey3(MapUtils.getString(operationInfo, "routeRrn"));
        reworkRouteContextValue.setContextKey4(MapUtils.getString(operationInfo, "operationRrn"));
        reworkRouteContextValue.setContextKey8(MapUtils.getString(operationInfo, "processVersion"));
        ContextValue contextValue = ctxService.simulateContextValue(reworkRouteContextValue);

        if (reworkRouteRrn > 0) {
            int reworkRouteVersion = 0;
            if (StringUtils.isNotBlank(contextValue.getResultValue5())) {
                reworkRouteVersion = Integer.parseInt(contextValue.getResultValue5());
            }
            List<String[]> wflTree = new ArrayList<>();
            if (reworkRouteVersion > 0) {
                wflTree = prpService.getWorkFlowTree(reworkRouteRrn, reworkRouteVersion, new HashMap());
            } else {
                wflTree = prpService.getWorkFlowTree(reworkRouteRrn, new HashMap());
            }

            String routeSeq = StringUtils.EMPTY;
            Long routeRrn = reworkRouteRrn;
            String routeId = getInstanceId(reworkRouteRrn);
            String routeDesc = getInstanceDesc(reworkRouteRrn);
            for (String[] treeNodes : wflTree) {
                Map<String, Object> wflInfo = new HashMap<>();
                if ("0".equals(treeNodes[7])) {
                    routeSeq = StringUtils.substringBefore(treeNodes[2], "-");
                    routeId = StringUtils.substringAfterLast(treeNodes[2], "---");
                    routeRrn = NumberUtils.createLong(treeNodes[4]);
                    routeDesc = treeNodes[5];
                } else if ("1".equals(treeNodes[7])) {
                    wflInfo.put("productId",MapUtils.getString(operationInfo,"productId"));
                    wflInfo.put("productVersion", MapUtils.getIntValue(operationInfo, "productVersion"));
                    wflInfo.put("processRrn", MapUtils.getLong(operationInfo, "processRrn"));
                    wflInfo.put("processVersion", MapUtils.getLong(operationInfo, "processVersion"));
                    wflInfo.put("routeRrn", routeRrn);
                    wflInfo.put("routeStepRrn",routeRrn);
                    wflInfo.put("routeVersion",MapUtils.getIntValue(operationInfo, "routeVersion"));
                    wflInfo.put("routeSeq", routeSeq);
                    wflInfo.put("routeProcessSeq", routeSeq);
                    wflInfo.put("routeId", routeId);
                    wflInfo.put("routeDesc", routeDesc);
                    wflInfo.put("operationRrn", NumberUtils.createLong(treeNodes[4]));
                    wflInfo.put("operationId", StringUtils.substringAfterLast(treeNodes[2], "---"));
                    wflInfo.put("operationSeq", StringUtils.substringBefore(treeNodes[2], "-"));
                    wflInfo.put("operationRouteSeq", StringUtils.substringBefore(treeNodes[2], "-"));
                    wflInfo.put("operationStepRrn",NumberUtils.createLong(treeNodes[4]));
                    wflInfo.put("stepPath", treeNodes[6]);
                    wflInfo.put("stepNumber", MapUtils.getString(wflInfo, "stepPath"));
                    wflInfo.put("facilityRrn", LocalContext.getFacilityRrn());
                    wflInfo.put("isRework", "1");
                    wflInfo.put("isMain", "0");

                    buildStepInfo(wflInfo,productSpecItemDtos);

                    wflInfos.add(wflInfo);
                }
            }
        }

        return wflInfos;
    }

    /**
     * build node信息
     **/
    private void buildNodeInfo(Map node,Map map,List<ProductSpecItemDto> productSpecItemDtos){
        node.put("isMain", MapUtils.getString(map, "isMain", "1"));
        node.put("operationRrn", MapUtils.getString(map, "operationRrn"));
        node.put("operationId", MapUtils.getString(map, "operationId"));
        node.put("operationSeq", MapUtils.getString(map, "operationRouteSeq"));
        node.put("routeRrn", MapUtils.getString(map, "routeRrn"));
        node.put("routeId", MapUtils.getString(map, "routeId"));
        node.put("processStepIdVersion", MapUtils.getString(map, "routeId"));
        node.put("routeSeq", MapUtils.getString(map, "routeProcessSeq"));
        node.put("routeDesc", MapUtils.getString(map, "routeDesc"));
        node.put("processRrn", MapUtils.getString(map, "processRrn"));
        node.put("processId", MapUtils.getString(map, "processId"));
        node.put("processVersion", MapUtils.getString(map, "processVersion"));
        node.put("productRrn", MapUtils.getString(map, "productRrn"));
        node.put("productId", MapUtils.getString(map, "productId"));

        String wflStep = buildWflStep(map);
        node.put("stepPath", wflStep);
        node.put("stepNumber", wflStep);
        node.put("facilityRrn", LocalContext.getFacilityRrn());
        node.put("flipType", MapUtils.getString(map, "flipType"));
        buildStepInfo(node,productSpecItemDtos);
    }

    /**
     * build step情景值
     **/
    private void buildStepInfo(Map<String, Object> node,List<ProductSpecItemDto> productSpecItemDtos){
        Long routeRrn = MapUtils.getLong(node, "routeRrn");
        Long operationRrn = MapUtils.getLong(node, "operationRrn");

        for(ProductSpecItemDto productSpecItemDto : productSpecItemDtos){
            if(routeRrn==productSpecItemDto.getRouteRrn().longValue()
                    && operationRrn==productSpecItemDto.getOperationRrn().longValue()
                    && SystemConstant.Str.ACTIVE.equalsIgnoreCase(productSpecItemDto.getStatus())){
                node.put("eqptGroupId",productSpecItemDto.getEquipmentGroupId());
                node.put("recipeId", productSpecItemDto.getRecipeId());
                node.put("processLocation",productSpecItemDto.getProcessLocation());
                node.put("stageId",productSpecItemDto.getStageId());
                node.put("operationType",productSpecItemDto.getOperationType());
                node.put("operationDesc",productSpecItemDto.getOperationDesc());
                node.put("flowSeq",productSpecItemDto.getFlowSeq());
                node.put("reSeq",productSpecItemDto.getFlowSeq());
                String reticleFamilyId = productSpecItemDto.getReticleFamilyId();
                String pollutionLevel = productSpecItemDto.getPollutionLevel();
                if(StringUtils.isEmpty(reticleFamilyId)){
                    reticleFamilyId = "";
                }
                if(StringUtils.isEmpty(pollutionLevel)){
                    pollutionLevel = "";
                }
                node.put("reticleFamilyId",reticleFamilyId);
                node.put("contamination",pollutionLevel);
                break;
            }
        }
    }

    private String buildWflStep(Map map){
        return  MapUtils.getString(map, "processRrn") + "." + MapUtils.getString(map, "processVersion") + "." +
                MapUtils.getString(map, "routeStepRrn") + "|" + MapUtils.getString(map, "routeRrn") + "." +
                MapUtils.getString(map, "routeVersion") + "." + MapUtils.getString(map, "operationStepRrn");
    }
}