ViewFutureLotAction.java

package com.mycim.webapp.actions.lot.fetchstep;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.i18n.I18nUtils;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.utils.beans.BeanUtils;
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.lang.time.DateUtils;
import com.mycim.framework.utils.msg.JsonUtils;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.SystemConstant;
import com.mycim.valueobject.bas.ErrorMsg;
import com.mycim.valueobject.bas.Relation;
import com.mycim.valueobject.consts.ContextNames;
import com.mycim.valueobject.consts.EventName;
import com.mycim.valueobject.consts.LinkTypeList;
import com.mycim.valueobject.ems.Entity;
import com.mycim.valueobject.ems.EntityStatus;
import com.mycim.valueobject.ems.Equipment;
import com.mycim.valueobject.prp.*;
import com.mycim.valueobject.security.Station;
import com.mycim.valueobject.sys.Facility;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.LotSpecialInfo;
import com.mycim.valueobject.wip.dto.FetchStepItemDto;
import com.mycim.webapp.Constants;
import com.mycim.webapp.TemplateLocation;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.WipSetupAction;
import com.mycim.webapp.forms.lot.LotInfoForm;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

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

/**
 * fetch工步
 *
 * @author weike.li
 * @version 6.0.0
 * @date 2019/10/9
 **/
public class ViewFutureLotAction extends WipSetupAction {

    private static final String CN = "CN";

    private static final String KEY_LOT_RRN = "lotRrn";

    private static final String KEY_PRODUCT_RRN = "productRrn";

    private static final String KEY_PRODUCT_ID = "productId";

    private static final String KEY_PROCESS_RRN = "processRrn";

    private static final String KEY_PROCESS_ID = "processId";

    private static final String KEY_PROCESS_VERSION = "processVersion";

    private static final String KEY_PRODUCT_VERSION = "productVersion";

    private static final String KEY_QTY = "qty1";

    private static final String KEY_ROUTE_SEQ = "routeSeq";

    private static final String KEY_OPERATION_SEQ = "operationSeq";

    private static final String KEY_FLOW_SEQ = "flowSeq";

    private static final String KEY_REWORK_ROUTE_RRN = "reworkRouteRrn";

    private static final String KEY_REWORK_ROUTE_ID = "reworkRouteId";

    private static final String KEY_REWORK_ROUTE_VERSION = "reworkRouteVersion";

    private static final String KEY_MAX_REWORK_TIMES = "maxReworkTimes";

    private static final String KEY_WAITING_TIME = "waitingTime";

    private static final String KEY_QUEUE_TIME = "queueTime";

    private static final String KEY_POLLUCTION_LEVEL = "polluctionLevel";

    private static final String KEY_OPERATION_COMMENT = "operationComment";

    private static final String KEY_HAS_FUTURE_HOLD = "hasFutureHold";

    private static final String KEY_DISPATCH_AREA = "dispatchArea";

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) throws Exception {
        Long facility = LocalContext.getFacilityRrn();
        Map lotBaseInfo = new HashMap();
        request.setAttribute("lot_base_info", JsonUtils.toString(lotBaseInfo));
        request.setAttribute(SystemConstant.Str.SPECIAL_ROLE, isSpecialRole());
        registerOptionType(facility, Arrays.asList(new String[]{"LOTFUTURESTEPS"}), request);
        return mapping.findForward("lotFuture");
    }

    public ActionForward queryLot(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                  HttpServletResponse response) {
        ActionForward dest = WebUtils.NULLActionForward;
        LotInfoForm theform = (LotInfoForm) form;
        Long facility = LocalContext.getFacilityRrn();
        Map result = new HashMap();
        Map lotBaseInfo = new HashMap();
        String lotId = theform.getLotId();
        Map lotInfo = null;

        if (lotId != null) {
            Lot lot = lotQueryService.getLot(lotId.trim().toUpperCase(), facility);
            lotInfo = BeanUtils.copyBeanToMap(lot);
        }
        if (lotInfo == null) {
            if (StringUtils.equalsIgnoreCase("CN", I18nUtils.getCurrentLanguage().toString())) {
                result.put("Msg", "未查询到相关信息");
            } else {
                result.put("Msg", "Not querying the relevant information");
            }

            result.put("lotBaseInfo", "");
            WebUtils.writeJson(response, result.toString());
        } else {
            lotBaseInfo.put("lotId", lotInfo.get("lotId"));
            lotBaseInfo.put("productId", lotInfo.get("productId"));
            lotBaseInfo.put("lotType", lotInfo.get("lotType"));
            lotBaseInfo.put("carrierId", lotInfo.get("carrierId"));
            lotBaseInfo.put("priority", wipQueryService.getHotflagSplicingPriority(
                    NumberUtils.toInt(MapUtils.getString(lotInfo, "hotflag"), 0),
                    NumberUtils.toInt(MapUtils.getString(lotInfo, "priority"), 0), facility));
            lotBaseInfo.put("lotRrn", lotInfo.get("lotRrn"));

            request.setAttribute("lot_base_info", JsonUtils.toString(lotBaseInfo));
            request.setAttribute("from", "lot_location_4csec_action");
            request.setAttribute("lot_id", lotId);
            request.setAttribute("reworkFlag", MapUtils.getString(lotInfo, "reworkCategory"));
            registerOptionType(facility, Arrays.asList(new String[]{"LOTFUTURESTEPS"}), request);
            dest = mapping.findForward("lotFuture");

        }
        return dest;
    }


    public ActionForward export(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String lotId = StringUtils.trim(request.getParameter("lotId"));

        long facilityRrn = LocalContext.getFacilityRrn();

        Lot lotInfo = lotQueryService.getLot(StringUtils.trimToUpperCase(lotId), facilityRrn);
        String priority = wipQueryService.getHotflagSplicingPriority(NumberUtils.toInt(lotInfo.getHotFlag(), 0),
                                                                     NumberUtils.toInt(lotInfo.getPriority() + "", 0),
                                                                     facilityRrn);
        Map map = new HashMap();
        map.put("lotId", StringUtils.trim(request.getParameter("lotId")));
        map.put("pageSize", StringUtils.trim(request.getParameter("pageSize")));
        List<FetchStepItemDto> lotFutureInfo = (List<FetchStepItemDto>) viewLotFutureInfo(map).get("results");

        int i = 1;
        ArrayList<Map<String, Object>> maps = new ArrayList<>();
        for (FetchStepItemDto fetchStepItemDto : lotFutureInfo) {
            Map<String, Object> map1 = BeanUtils.copyBeanToMap(fetchStepItemDto);
            map1.put("seq", i++);
            map1.put("qty1", MapUtils.getInteger(map1, "qty1"));
            maps.add(map1);
        }

        Map<String, Object> titles = WebUtils.getExportTitles(request);
        if (CN.equals(I18nUtils.getCurrentLanguage())) {
            titles.put("title", "批次返工未来信息");
            titles.put("titleProductId", "产品号:" + lotInfo.getProductId());
            titles.put("titleLotId", "批次号:" + lotInfo.getLotId());
            titles.put("titleLotType", "批次类型:" + lotInfo.getLotType());
            titles.put("titlePriority", "优先级:" + priority);
            titles.put("reworkRouteId", "返工路径号");
            titles.put("recipeParam", "工艺规格");
            titles.put("plannedCycleTime", "计划周期");
            titles.put("arriveTime", "Arrive Time");
            titles.put("maxReworkTimes", "最大返工次数");
        } else {
            titles.put("title", "Lot rework future information");
            titles.put("titleProductId", "product Id:" + lotInfo.getProductId());
            titles.put("titleLotId", "lot Id:" + lotInfo.getLotId());
            titles.put("titleLotType", "lot Type:" + lotInfo.getLotType());
            titles.put("titlePriority", "priority:" + priority);
            titles.put("reworkRouteId", "RWK Sub Plan ID");
            titles.put("recipeParam", "Spec");
            titles.put("plannedCycleTime", "Cycle Time");
            titles.put("arriveTime", "Arrive Time");
            titles.put("maxReworkTimes", "Max RWK Count");
        }

        String exportDateTime = DateUtils.getNowTime(DateUtils.DATE_FORMAT4NOSPLICING);
        String fileName = "LOT_FUTURE_INFO_" + exportDateTime + ".xlsx";

        WebUtils.exportExcel(fileName, titles, maps, TemplateLocation.LOT_FUTURE_INFO, response);
        return WebUtils.NULLActionForward;
    }

    public ActionForward exportForRework(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String lotId = StringUtils.trim(request.getParameter("lotId"));

        long facilityRrn = LocalContext.getFacilityRrn();

        Lot lotInfo = lotQueryService.getLot(StringUtils.trimToUpperCase(lotId), facilityRrn);
        String priority = wipQueryService.getHotflagSplicingPriority(NumberUtils.toInt(lotInfo.getHotFlag(), 0),
                                                                     NumberUtils.toInt(lotInfo.getPriority() + "", 0),
                                                                     facilityRrn);
        Map map = new HashMap();
        map.put("lotId", StringUtils.trim(request.getParameter("lotId")));
        map.put("pageSize", StringUtils.trim(request.getParameter("pageSize")));
        List<Map> lotFutureInfo = (List<Map>) viewLotReworkFutureInfo(map).get("results");
        int i = 1;
        for (Map map1 : lotFutureInfo) {
            map1.put("seq", i++);
            map1.put("qty1", MapUtils.getInteger(map1, "qty1"));
        }

        Map<String, Object> titles = WebUtils.getExportTitles(request);
        if (CN.equals(I18nUtils.getCurrentLanguage())) {
            titles.put("title", "批次返工未来信息");
            titles.put("titleProductId", "产品号:" + lotInfo.getProductId());
            titles.put("titleLotId", "批次号:" + lotInfo.getLotId());
            titles.put("titleLotType", "批次类型:" + lotInfo.getLotType());
            titles.put("titlePriority", "优先级:" + priority);
            titles.put("reworkRouteId", "返工路径号");
            titles.put("recipeParam", "工艺规格");
            titles.put("plannedCycleTime", "计划周期");
            titles.put("arriveTime", "Arrive Time");
            titles.put("maxReworkTimes", "最大返工次数");
        } else {
            titles.put("title", "Lot rework future information");
            titles.put("titleProductId", "product Id:" + lotInfo.getProductId());
            titles.put("titleLotId", "lot Id:" + lotInfo.getLotId());
            titles.put("titleLotType", "lot Type:" + lotInfo.getLotType());
            titles.put("titlePriority", "priority:" + priority);
            titles.put("reworkRouteId", "RWK Sub Plan ID");
            titles.put("recipeParam", "Spec");
            titles.put("plannedCycleTime", "Cycle Time");
            titles.put("arriveTime", "Arrive Time");
            titles.put("maxReworkTimes", "Max RWK Count");
        }

        String exportDateTime = DateUtils.getNowTime(DateUtils.DATE_FORMAT4NOSPLICING);
        String fileName = "LOT_REWORK_FUTURE_INFO_" + exportDateTime + ".xlsx";

        WebUtils.exportExcel(fileName, titles, lotFutureInfo, TemplateLocation.LOT_REWORK_FUTURE_INFO, response);
        return WebUtils.NULLActionForward;
    }

    public ActionForward viewEqptList(ActionMapping mapping, HttpServletRequest request) {

        Long facility = LocalContext.getFacilityRrn();

        long lotRrn = WebUtils.getParameterLong("lotRrn", request);
        Lot tempLot = lotQueryService.getLot(lotRrn);
        String operationId = WebUtils.getParameter("operationId", request);
        String routeId = WebUtils.getParameter("routeId", request);
        String recipeId = WebUtils.getParameter("recipeId", request);
        long operationRrn = getInstanceRrn(operationId, facility, ObjectList.OPERATION_KEY);
        long routeRrn = getInstanceRrn(routeId, facility, ObjectList.WFL_KEY);
        String isFutureHold = WebUtils.getParameter("isFutureHold", request);
        String stepSequence = WebUtils.getParameter("stepSequence", request);
        String parameterSetId = WebUtils.getParameter("parameterSetId", request);
        String edcPlanInfoFlag = WebUtils.getParameter("edcPlanInfoFlag", request);
        String edcExportFlag = WebUtils.getParameter("edcExportFlag", request);
        String quantity = WebUtils.getParameter("quantity", request);

        tempLot.setOperationId(operationId);
        tempLot.setOperationRrn(operationRrn);
        tempLot.setProcessStepIdVersion(null);
        tempLot.setRouteId(routeId);
        tempLot.setRouteRrn(routeRrn);
        tempLot.setRecipeId(recipeId);

        String entityGroupId = WebUtils.getParameter("entityGroupId", request);

        List<Relation> eqptRelations = new ArrayList<>();
        List<String> entityGroupIdList = StringUtils.splitAsList(entityGroupId, StringUtils.COMMA_SIGN);
        for (String eqptId : entityGroupIdList) {
            if (StringUtils.isNotEmpty(eqptId.trim())) {
                long entityGroupRrn = getInstanceRrn(eqptId, facility, ObjectList.ENTITYGROUP_KEY);
                eqptRelations.addAll(baseService.getEntitiesRelationByGroupRrn(entityGroupRrn));
            }
        }

        List<Relation> eqptRelationsByLot = getEntitiesWithLotSpecial(tempLot);
        String lotId = lotQueryService.getLot(lotRrn).getLotId();

        List<Map> edcPlanInfo = new ArrayList<>();
        if (StringUtils.isNotBlank(stepSequence) && StringUtils.isNotBlank(parameterSetId)) {
            buildEdcPlanInfos(lotRrn, stepSequence, lotId, parameterSetId, quantity, edcPlanInfo);
        }
        for (Relation relation : eqptRelations) {
            if (StringUtils.isNotBlank(relation.getInstanceId())) {
                eqptRelations = eqptRelationsByLot;
            }
        }

        List availableEquipmentInfos = new ArrayList();
        for (Relation eqptRelation : eqptRelations) {
            String equipmentId = eqptRelation.getInstanceId();
            String equipmentDesc = eqptRelation.getInstanceDesc();
            long equipmentRrn = eqptRelation.getInstanceRrn();

            Equipment equipment = new Equipment();
            equipment.setInstanceRrn(equipmentRrn);

            Map equipmentInfo = new HashMap();
            equipmentInfo.put("equipmentId", equipmentId);
            equipmentInfo.put("equipmentDesc", equipmentDesc);
            equipmentInfo.put("equipmentRrn", equipmentRrn);
            // check equipment status
            String equipmenStatus = emsService.getEntityCurrentStatus(equipmentRrn);
            equipmentInfo.put("equipmentStatus", equipmenStatus);

            //查询上一次加工批次时使用的Reticle和Recipe
            equipmentInfo.putAll(emsService.getLastRecipeAndReticleForEqptRrn(equipmentRrn));
            if (StringUtils.equalsIgnoreCase(equipmenStatus, EventName.IDLE) ||
                    StringUtils.equalsIgnoreCase(equipmenStatus, EventName.RUN)) {
                equipmentInfo.put("equipmentAvailable", "AVAILABLE");
            } else {
                equipmentInfo.put("equipmentAvailable", "NOT_AVAILABLE");
            }

            // start: 检查批次在当前设备是否有constrain
            ErrorMsg errorMsg = constrainService.checkLotConstrain(equipment, tempLot);
            equipmentInfo.put("equipmentConstrain", new Boolean(errorMsg.getError()));
            // check recipe
            List<Map<String, Object>> equipmentRecipes = recipeService.getRecipeList4Equipment(equipmentRrn);
            boolean checkEqptRecipeAvailable = checkEqptRecipeAvailable(equipmentRecipes, recipeId);
            equipmentInfo.put("checkEqptRecipeAvailable", new Boolean(checkEqptRecipeAvailable));

            availableEquipmentInfos.add(equipmentInfo);
        }

        if (StringUtils.equals(isFutureHold, "1")) {
            //check if it is the future hold step (for EEN_CONTEXT_HOLDLOT and EEN_CONTEXT_HOLDPRODUCT)
            long contextRrn = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDLOT, facility, ObjectList.CONTEXT_KEY);

            List futureHoldLotList = ctxExecService.getFutureHoldLotList(contextRrn, routeRrn, operationRrn, lotRrn,
                                                                         null, null);

            contextRrn = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDPRODUCT, facility, ObjectList.CONTEXT_KEY);

            List futureHoldProductList = ctxExecService.getFutureHoldProductList(contextRrn, routeRrn, operationRrn,
                                                                                 lotRrn, tempLot.getProductRrn(),
                                                                                 tempLot.getProcessRrn());
            futureHoldLotList.addAll(futureHoldProductList);

            request.setAttribute("futureHoldList", futureHoldLotList);
        }

        request.setAttribute("availableEquipmentInfos", availableEquipmentInfos);
        request.setAttribute("processId", WebUtils.getParameter("processId", request));
        request.setAttribute("processVersion", WebUtils.getParameter("processVersion", request));
        request.setAttribute("flowseq", WebUtils.getParameter("flowseq", request));
        request.setAttribute("stageId", WebUtils.getParameter("stageId", request));
        request.setAttribute("entityGroupId", entityGroupId);
        request.setAttribute("operationId", operationId);
        request.setAttribute("recipeId", recipeId);
        request.setAttribute("operationDesc", WebUtils.getParameter("operationDesc", request));
        request.setAttribute("reticle", WebUtils.getParameter("reticle", request));
        request.setAttribute("stepType", WebUtils.getParameter("stepType", request));
        request.setAttribute("contamination", WebUtils.getParameter("contamination", request));
        request.setAttribute("isFutureHold", isFutureHold);
        request.setAttribute("routeSeq", WebUtils.getParameter("routeSeq", request));
        request.setAttribute("operationSeq", WebUtils.getParameter("stepSeq", request));
        request.setAttribute("clickPaperclip", WebUtils.getParameter("clickPaperclip", request));
        request.setAttribute("edcPlanInfo", edcPlanInfo);
        if (StringUtils.isNotBlank(stepSequence)) {
            request.setAttribute("historyFlag", "1");
        }
        if (StringUtils.isNotBlank(edcPlanInfoFlag)) {
            request.setAttribute("edcPlanInfoFlag", edcPlanInfoFlag);
        }
        if (StringUtils.isNotBlank(edcExportFlag)) {
            request.setAttribute("edcExportFlag", edcExportFlag);
            request.setAttribute("queryParams", request.getQueryString());
        }

        return mapping.findForward("eqptList");
    }

    public ActionForward exportViewEqptList(HttpServletRequest request, HttpServletResponse response) throws Exception {

        long lotRrn = WebUtils.getParameterLong("lotRrn", request);
        String stepSequence = WebUtils.getParameter("stepSequence", request);
        String parameterSetId = WebUtils.getParameter("parameterSetId", request);
        String edcPlanInfoFlag = WebUtils.getParameter("edcPlanInfoFlag", request);
        String quantity = WebUtils.getParameter("quantity", request);

        String lotId = lotQueryService.getLot(lotRrn).getLotId();

        List<Map> edcPlanInfo = new ArrayList<>();
        if (StringUtils.isNotBlank(stepSequence) && StringUtils.isNotBlank(parameterSetId)) {
            buildEdcPlanInfos(lotRrn, stepSequence, lotId, parameterSetId, quantity, edcPlanInfo);
        }
        //导出成Excel
        Map<String, Object> titles = WebUtils.getExportTitles(request);
        if (CN.equals(I18nUtils.getCurrentLanguage())) {
            titles.put("seq", "序号");
            titles.put("title", "批次采集参数");
            titles.put("titleLotId", "批次号:" + lotId);
            titles.put("parameterSetId", "参数集号:" + parameterSetId);
            titles.put("quantity", "片数:" + quantity);
            titles.put("lotId", "批次号");
            titles.put("edcPlan", "EDC Plan");
            titles.put("waferQty", "片数");
            titles.put("waferId", "片号");
            titles.put("parameterId", "参数号");
            titles.put("parameterValue", "EDC参数值");
            titles.put("collectionTimestamp", "数据采集时间");
        } else {
            titles.put("seq", "Seq.");
            titles.put("title", "Lot Parameter Collection");
            titles.put("titleLotId", "Lot ID: " + lotId);
            titles.put("parameterSetId", "Parameter Set ID: " + parameterSetId);
            titles.put("quantity", "Quantity: " + quantity);
            titles.put("lotId", "Lot ID");
            titles.put("edcPlan", "EDC Plan");
            titles.put("waferQty", "WaferQty");
            titles.put("waferId", "WaferId");
            titles.put("parameterId", "ParameterId");
            titles.put("parameterValue", "ParameterValue");
            titles.put("collectionTimestamp", "CollectionTimestamp");
        }

        String exportDateTime = DateUtils.getNowTime(DateUtils.DATE_FORMAT4NOSPLICING);
        String fileName = "EDC_PLAN_INFO_" + exportDateTime + ".xlsx";

        WebUtils.exportExcel(fileName, titles, edcPlanInfo, TemplateLocation.EDC_PLAN_INFO, response);
        return WebUtils.NULLActionForward;
    }

    public Map viewLotReworkFutureInfo(Map map) {

        Long facilityRrn = LocalContext.getFacilityRrn();
        String lotId = (String) map.get("lotId");

        Lot lotInfo = new Lot();
        if (StringUtils.isNotBlank(lotId)) {
            lotInfo = lotQueryService.getLot(StringUtils.trimToUpperCase(lotId), facilityRrn);
        }
        Assert.isFalse(lotInfo.equals(new Lot()), Errors.create().content("No such Lot exist!").build());

        Map result = new HashMap();
        try {
            int processVersion = lotInfo.getProcessVersion();

            Long pageSize = NumberUtils.toLong(StringUtils.toString(map.get("pageSize")), 10);

            String flowSeq = ctxExecService.getFlowSeqByProcessInfo(BeanUtils.copyBeanToMap(lotInfo));
            List<Map<String, Object>> reworkList = lotQueryService.getProcessAllReworkStepInfoByLot(lotInfo.getLotRrn(),
                                                                                                    lotInfo.getProductRrn(),
                                                                                                    flowSeq, pageSize,
                                                                                                    processVersion,
                                                                                                    lotInfo.getProductVersion());
            Map lotInfoMap = BeanUtils.copyBeanToMap(lotInfo);
            lotInfoMap.put("flowSeq", flowSeq);
            buildFuturyReworkInfo(facilityRrn, lotInfoMap, reworkList);

            result.put("results", reworkList);
            result.put("success", "true");
            result.put("rows", reworkList.size());
            result.put("processBaseInfo", new HashMap<>());
        } catch (Exception e) {
            result.put("success", "false");
            result.put("msg", e.getMessage());
            e.printStackTrace();
        }

        return result;
    }

    public Map viewLotFutureInfo(Map map) {
        Long facilityRrn = LocalContext.getFacilityRrn();
        String lotId = MapUtils.getString(map, "lotId");

        Lot lotInfo = new Lot();
        if (StringUtils.isNotBlank(lotId = StringUtils.trimToUpperCase(lotId))) {
            lotInfo = isSpecialRole()?lotInqService.getLotWhitDataPermission(lotId):lotInqService.getLot(lotId);
            if (Objects.isNull(lotInfo)) lotInfo = new Lot();
        }
        Assert.isFalse(lotInfo.equals(new Lot()), Errors.create().content("No such Lot exist!").build());
        Map<String, Object> lotInfo2 = BeanUtils.copyBeanToMap(lotInfo);
        Map result = new HashMap();
        try {
            Long pageSize = MapUtils.getLongValue(map, "pageSize");
            List<FetchStepItemDto> technologyInfos = queryFutureStep(lotInfo2, pageSize);
            result.put("results", technologyInfos);
            result.put("success", "true");
            result.put("rows", technologyInfos.size());
            result.put("processBaseInfo", new HashMap<>());
        } catch (Exception e) {
            result.put("success", "false");
            result.put("msg", e.getMessage());
            e.printStackTrace();
        }
        return result;
    }

    public List<FetchStepItemDto> queryFutureStep(Map<?, ?> lotInfo, Long pageSize) throws Exception {
        long lotRrn = MapUtils.getLongValue(lotInfo, KEY_LOT_RRN);
        long productRrn = MapUtils.getLongValue(lotInfo, KEY_PRODUCT_RRN);
        long processRrn = MapUtils.getLongValue(lotInfo, KEY_PROCESS_RRN);
        int processVersion = MapUtils.getIntValue(lotInfo, KEY_PROCESS_VERSION);
        int productVersion = MapUtils.getIntValue(lotInfo, KEY_PRODUCT_VERSION);
        String wflRouteSeq = MapUtils.getString(lotInfo, KEY_ROUTE_SEQ);
        String wflOperationSeq = MapUtils.getString(lotInfo, KEY_OPERATION_SEQ);

        String operationSeq = StringUtils.replace(wflOperationSeq, Constants.WFL_STEP_START, "0");
        String routeSeq = StringUtils.replace(wflRouteSeq, Constants.WFL_ROUTE_START, "0");
        List<FetchStepItemDto> processSteps = prpService.getFetureStepProcessAllStepInfo(processRrn, processVersion,
                                                                                         NumberUtils.toLong(
                                                                                                 operationSeq),
                                                                                         NumberUtils.toLong(routeSeq),
                                                                                         pageSize, productRrn,
                                                                                         productVersion, 0);
        List<Relation> allRelationByEquip = baseService.getAllRelationByEqpt();
        Map<String, Map<String, Object>> contextValues = getContextValuesForActiveWithOther(lotRrn, productRrn,
                                                                                            processRrn, processVersion);

        int seq = 0;
        List<FetchStepItemDto> result = new ArrayList<>();
        Item item = new Item(productRrn);
        List<Map> productLinkList = prpService.getProductLinkList(item, LinkTypeList.PRODUCT_TO_SAPPHIRES);


        Map<String, String> flipTypeMap = processSpecService.getFlipTypeKeyMap();

        for (FetchStepItemDto fetchStepItemDto : processSteps) {
            long routeRrn = fetchStepItemDto.getRouteRrn();
            long operationRrn = fetchStepItemDto.getOperationRrn();
            fetchStepItemDto.setStepSeq(++seq);
            fetchStepItemDto.setLotRrn(lotRrn);
            fetchStepItemDto.setQty1(MapUtils.getInteger(lotInfo, KEY_QTY));
            fetchStepItemDto.setProcessRrn(processRrn);
            fetchStepItemDto.setProductId(MapUtils.getString(lotInfo, KEY_PRODUCT_ID));
            fetchStepItemDto.setProcessId(MapUtils.getString(lotInfo, KEY_PROCESS_ID));
            fetchStepItemDto.setProcessVersion(processVersion);


            Map<String, Object> stepContextValue = contextValues.get(
                    buildKeyByProduct(productRrn, processRrn, processVersion, routeRrn, operationRrn));

            // Operation Description
            fetchStepItemDto.setWaitingTime(MapUtils.getString(stepContextValue, KEY_WAITING_TIME, StringUtils.EMPTY));
            fetchStepItemDto.setoPollutionLevel(
                    MapUtils.getString(stepContextValue, KEY_POLLUCTION_LEVEL, StringUtils.EMPTY));

            List<OperationParameterRelation> parameterGroup = prpService.getOperationParameters(operationRrn);
            StringBuffer parameters = new StringBuffer();
            for (OperationParameterRelation operationParameterRelation : parameterGroup) {
                parameters.append(operationParameterRelation.getParameterId() + ",");
            }
            fetchStepItemDto.setParameterGroup(parameters.toString());

            // Rework
            fetchStepItemDto.setReworkRouteId(
                    MapUtils.getString(stepContextValue, KEY_REWORK_ROUTE_ID, StringUtils.EMPTY));
            fetchStepItemDto.setMaxReworkTimes(
                    MapUtils.getString(stepContextValue, KEY_MAX_REWORK_TIMES, StringUtils.EMPTY));
            boolean isFutureHold = MapUtils.getBooleanValue(stepContextValue, KEY_HAS_FUTURE_HOLD);
            if (isFutureHold) {
                fetchStepItemDto.setIsFutureHold("1");
            }
            // QTime
            fetchStepItemDto.setQueueTime(MapUtils.getString(stepContextValue, KEY_QUEUE_TIME, StringUtils.EMPTY));

            // Entity
            String entityGroupRrns = specService.getEqptGroupRrns(processRrn, fetchStepItemDto.getProcessVersion(),
                                                                  routeRrn, operationRrn);

            fetchStepItemDto.setDispatchArea(
                    MapUtils.getString(getDispatchArea(entityGroupRrns, allRelationByEquip), KEY_DISPATCH_AREA));
            fetchStepItemDto.setEntityGroupId(
                    specService.getEqptGroupIds(processRrn, processVersion, routeRrn, operationRrn));

            fetchStepItemDto.setOrientateCurrByFLowSeq(MapUtils.getString(lotInfo, KEY_FLOW_SEQ));

            if (CollectionUtils.isNotEmpty(productLinkList)) {
                for (Map map : productLinkList) {
                    String stepId = MapUtils.getString(map, "stepId");
                    String bondingTag = MapUtils.getString(map, "attributedata5");
                    if (StringUtils.isNotBlank(stepId) && StringUtils.isNotBlank(bondingTag) &&
                            StringUtils.equals(stepId, fetchStepItemDto.getOperationId())) {
                            if (StringUtils.equals(Constants.BONDING_TAG_TYPE.BOTTOM, bondingTag)) {
                                fetchStepItemDto.setBondingTag(Constants.BONDING_TAG_TYPE.TOP);
                            } else if (StringUtils.equals(Constants.BONDING_TAG_TYPE.TOP, bondingTag)) {
                                fetchStepItemDto.setBondingTag(Constants.BONDING_TAG_TYPE.BOTTOM);
                            }
                    }
                }
            }
            if (StringUtils.isBlank(fetchStepItemDto.getBondingTag())) {
                fetchStepItemDto.setBondingTag(StringUtils.EMPTY);
            }
            result.add(fetchStepItemDto);
        }

        setMultipathAndDefaultStepFlag(result);
        return result;
    }

    /**
     * 将process对应的multipath和default step都做上标记
     **/
    private void setMultipathAndDefaultStepFlag(List<FetchStepItemDto> nodes) {
        List<ProcessSpecItemDto> processSpecItemList = new ArrayList<>();
        for(FetchStepItemDto node : nodes){
            ProcessSpecItemDto processSpecItem = new ProcessSpecItemDto();
            processSpecItem.setProcessRrn(node.getProcessRrn());
            processSpecItem.setProcessVersion(node.getProcessVersion());
            processSpecItem.setRouteRrn(node.getRouteRrn());
            processSpecItem.setOperationRrn(node.getOperationRrn());
            processSpecItemList.add(processSpecItem);
        }
        List<ProcessSpecItemDto> processSpecItemDtos = processSpecService.setMultipathAndDefaultStepFlag(processSpecItemList);

        for(ProcessSpecItemDto processSpecItemDto : processSpecItemDtos){
            for(FetchStepItemDto node : nodes){
                if(node.getRouteRrn().equals(processSpecItemDto.getRouteRrn()) &&
                        node.getOperationRrn().equals(processSpecItemDto.getOperationRrn())){
                    node.setMultipathAndDefaultStepFlag(processSpecItemDto.getMultipathAndDefaultStepFlag());
                }
            }
        }
    }

    public Map validLot(Map map) {
        boolean flag = map.get("from") != null;
        Long facilityRrn = LocalContext.getFacilityRrn();
        Map result = new HashMap();
        Map lotBaseInfo = new HashMap();
        String lotId = (String) map.get("lotId");
        Lot lotInfo = new Lot();

        if (StringUtils.isNotEmpty(lotId = StringUtils.trimToUpperCase(lotId))) {
            lotInfo = isSpecialRole()?lotInqService.getLotWhitDataPermission(lotId):lotInqService.getLot(lotId);
            if (Objects.isNull(lotInfo)) lotInfo = new Lot();
        }
        if (lotInfo.equals(new Lot())) {
            if (StringUtils.equalsIgnoreCase("CN", I18nUtils.getCurrentLanguage().toString())) {
                result.put("Msg", "未查询到相关信息");
            } else {
                result.put("Msg", "Not querying the relevant information");
            }

            result.put("lotBaseInfo", "");
            return result;
        } else {
            lotBaseInfo.put("lotId", lotInfo.getLotId());
            lotBaseInfo.put("productId", lotInfo.getProductId());
            lotBaseInfo.put("lotType", lotInfo.getLotType());
            lotBaseInfo.put("carrierId", lotInfo.getCarrierId());
            lotBaseInfo.put("priority",
                            wipQueryService.getHotflagSplicingPriority(NumberUtils.toInt(lotInfo.getHotFlag(), 0),
                                                                       NumberUtils.toInt(lotInfo.getPriority() + "", 0),
                                                                       facilityRrn));
            lotBaseInfo.put("lotRrn", lotInfo.getLotRrn());

            result.put("lotBaseInfo", JsonUtils.toString(lotBaseInfo));
            result.put("reworkFlag", lotInfo.getReworkCategory() == null ? false : lotInfo.getReworkCategory());
            result.put("success", true);
            return result;
        }
    }

    private void buildFuturyReworkInfo(Long facilityRrn, Map lotInfo, List<Map<String, Object>> reworkProcessInfoList) {
        int seq = 0;
        if (CollectionUtils.isNotEmpty(reworkProcessInfoList)) {
            for (int i = 0; i < reworkProcessInfoList.size(); i++) {
                Map<String, Object> reworkMap = reworkProcessInfoList.get(i);
                buildEquipAndReticleContext(facilityRrn, reworkMap);
                reworkMap.put("stepSeq", ++seq);
                reworkMap.put("qty1", MapUtils.getInteger(lotInfo, "qty"));
                reworkMap.put("productRrn", MapUtils.getString(lotInfo, "productRrn"));
                reworkMap.put("productId", MapUtils.getString(lotInfo, "productId"));
                reworkMap.put("routeRrn", MapUtils.getString(lotInfo, "routeRrn"));
                reworkMap.put("operationRrn", MapUtils.getString(lotInfo, "operationRrn"));
                reworkMap.put("lotRrn", MapUtils.getString(lotInfo, "lotRrn"));
                reworkMap.put("recipeId", MapUtils.getString(reworkMap, "recipePhysicalId"));
                reworkMap.put("facilityRrn", facilityRrn);
                reworkMap.put("orientateCurrByFLowSeq", MapUtils.getLong(lotInfo, "flowSeq"));
                try {
                    checkFutureHoldStep(facilityRrn, MapUtils.getString(lotInfo, "lotRrn"), reworkMap);


                    Map seqAndWait = getOperationSeqAndWait(reworkMap);
                    reworkMap.put("waitingTime", seqAndWait.get("WAITING_TIME"));
                    reworkMap.put("queueTime", getOperationQueueTime(reworkMap));
                    reworkMap.put("oPollutionLevel",
                                  MapUtils.getString(seqAndWait, "oPollutionLevel", StringUtils.EMPTY));

                    // get edc parameter
                    Map edcParameter = getEdcContextValueByLot(reworkMap);
                    if (edcParameter.get("PARAMETERSET") != null &&
                            NumberUtils.isNumber((String) edcParameter.get("PARAMETERSET"))) {
                        String parameterSetId = getInstanceId(MapUtils.getLongValue(edcParameter, "PARAMETERSET"));
                        reworkMap.put("parameterSet", parameterSetId);

                        List paramters = getParameters(MapUtils.getLongValue(edcParameter, "PARAMETERSET"));
                        StringBuffer paramterIds = new StringBuffer();
                        for (Object obj : paramters) {
                            Map parameter = (Map) obj;
                            paramterIds.append(parameter.get("parameterId") + ",");
                        }
                        reworkMap.put("edcParam", paramterIds.toString());
                    }

                    ctxExecService.buildContextValueForEdcLot(facilityRrn, reworkMap);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private List<Map<String, Object>> queryFutureStepForLot(Long pageSize, Long facilityRrn, Lot lotInfo,
                                                            long processRrn, int processVersion, long productRrn,
                                                            int productVersion) throws Exception {
        String operationSeq = StringUtils.replace(lotInfo.getOperationSeq(), Constants.WFL_STEP_START, "0");
        String routeSeq = StringUtils.replace(lotInfo.getRouteSeq(), Constants.WFL_ROUTE_START, "0");

        List<Map<String, Object>> allProcessStep = prpService.getProcessAllStepInfo(processRrn, processVersion,
                                                                                    NumberUtils.toLong(operationSeq),
                                                                                    NumberUtils.toLong(routeSeq),
                                                                                    pageSize, productRrn,
                                                                                    productVersion, 0);
        Lot lot = new Lot();

        BeanUtils.copyProperties(lotInfo, lot);

        int seq = 0;
        for (int i = 0; i < allProcessStep.size(); i++) {
            Map<String, Object> mainProStep = allProcessStep.get(i);
            mainProStep.put("stepSeq", ++seq);
            mainProStep.put("routeSeq", MapUtils.getString(mainProStep, "routeProcessSeq"));
            mainProStep.put("qty1", lotInfo.getQty1());
            mainProStep.put("operationSeq", MapUtils.getString(mainProStep, "operationRouteSeq"));
            mainProStep.put("productRrn", lotInfo.getProductRrn() + "");
            mainProStep.put("productVersion", lotInfo.getProductVersion());
            mainProStep.put("productId", lotInfo.getProductId());
            mainProStep.put("processId", lotInfo.getProcessId());
            mainProStep.put("processVersion", processVersion);
            mainProStep.put("facilityRrn", facilityRrn);
            mainProStep.put("orientateCurrByFLowSeq", lotInfo.getFlowSeq());
            lot.setRouteRrn(MapUtils.getLong(mainProStep, "routeRrn"));
            lot.setOperationRrn(MapUtils.getLong(mainProStep, "operationRrn"));

            mainProStep.put("workArea", lotQueryService.getWorkArea(lot));
            mainProStep.put("operationType", lotQueryService.getOperationType(lot));

            checkFutureHoldStep(facilityRrn, lotInfo.getLotRrn() + "", mainProStep);

            reBuildProcessInfo(facilityRrn, mainProStep);

        }

        return allProcessStep;
    }

    private void reBuildProcessInfo(Long facilityRrn, Map process) throws Exception {
        long productRrn = MapUtils.getLongValue(process, "productRrn");
        Recipe recipe = getRecipeByProcessInfo(productRrn, process);
        process.put("recipeId", recipe.getInstanceId());
        process.put("recipeParam", recipe.getRecipeParam());
        process.put("recipeDesc", recipe.getInstanceDesc());

        // get product and route recipe
        getRecipe4RouteAndProduct(productRrn, process);

        // get seq and waiting time
        Map seqAndWait = getOperationSeqAndWait(process);
        process.put("waitingTime", seqAndWait.get("WAITING_TIME"));
        process.put("queueTime", getOperationQueueTime(process));

        process.put("oPollutionLevel", MapUtils.getString(seqAndWait, "oPollutionLevel", StringUtils.EMPTY));

        if (StringUtils.isNotEmpty((String) seqAndWait.get("oOperationComment"))) {
            process.put("oOperationComment", seqAndWait.get("oOperationComment"));
        }

        // get entities
        buildEquipAndReticleContext(facilityRrn, process);

        // get operation type
        if (process.get("operationType") != null) {
            String operationType = sysService.referenceDetailExchangeNull("$OPERATION_TYPE",
                                                                          MapUtils.getString(process, "operationType"),
                                                                          "DATA_1_VALUE");
            process.put("operationType", operationType);
        } else {
            process.put("operationType", StringUtils.EMPTY);
        }

        // get operation work area
        if (process.get("workArea") != null) {
            String workArea = sysService.referenceDetailExchangeNull("$$WORK_AREA",
                                                                     MapUtils.getString(process, "workArea"),
                                                                     "DATA_1_VALUE");
            process.put("workArea", workArea);
        } else {
            process.put("workArea", StringUtils.EMPTY);
        }

        // get rework operation
        Map reworkRoute = getReworkRoute(process);
        long reworkRouteRrn = MapUtils.getLongValue(reworkRoute, "reworkRouteRrn");
        int maxReworkTimes = MapUtils.getIntValue(reworkRoute, "maxReworkTimes");
        if (reworkRouteRrn > 0) {
            String reworkRouteId = getInstanceId(reworkRouteRrn);
            process.put("reworkRouteId", reworkRouteId);
        }
        if (maxReworkTimes > 0) {
            process.put("maxReworkTimes", reworkRoute.get("maxReworkTimes"));
        }

        // get edc paramter
        Map edcParamter = getEdcContextValueByLot(process);
        if (edcParamter.get("PARAMETERSET") != null &&
                NumberUtils.isCreatable((String) edcParamter.get("PARAMETERSET"))) {
            String parameterSetId = getInstanceId(MapUtils.getLongValue(edcParamter, "PARAMETERSET"));
            process.put("parameterSet", parameterSetId);

            List paramters = getParameters(MapUtils.getLongValue(edcParamter, "PARAMETERSET"));
            StringBuffer paramterIds = new StringBuffer();
            for (Iterator iterator2 = paramters.iterator(); iterator2.hasNext(); ) {
                HashMap parameter = (HashMap) iterator2.next();
                paramterIds.append(parameter.get("parameterId") + ",");
            }
            process.put("edcParam", paramterIds.toString());
        }

        // get operation parameter
        long operationRrn = MapUtils.getLongValue(process, "operationRrn");
        List<OperationParameterRelation> parameterGroup = prpService.getOperationParameters(operationRrn);
        StringBuffer parameters = new StringBuffer();
        for (OperationParameterRelation operationParameterRelation : parameterGroup) {
            parameters.append(operationParameterRelation.getParameterId() + ",");
        }

        process.put("parameterGroup", parameters.toString());

        process.put("facilityRrn", LocalContext.getFacilityRrn());
        process.put("recipePhysicalId",
                    recipeService.buildRecipePhysicalId(MapUtils.getString(process, "recipeId"), process));
        process.put("flowSeq", ctxExecService.getFlowSeqByProcessInfo(process));
        process.put("operationDesc", ctxExecService.getOperationDescByProcessInfo(process));

        Facility facility = new Facility(facilityRrn);
        process.put("processRrn", MapUtils.getLong(process, "processRrn"));
        process.put("productRrn", MapUtils.getLong(process, "productRrn"));
        process.put("operationRrn", MapUtils.getLong(process, "operationRrn"));
        process.put("routeRrn", MapUtils.getLong(process, "routeRrn"));
        process.putAll(ctxExecService.buildContextValueForProcessLocation(facilityRrn, process));
        process.putAll(ctxExecService.buildContextValueForEdcLot(facilityRrn, process));
        Map map = ctxExecService.buildContextValueForStage(facilityRrn, process);
        process.put("stageId", MapUtils.getString(map, "stageId"));
    }

    private void checkFutureHoldStep(Long facilityRrn, String lotRrn, Map<String, Object> mainProStep) {
        mainProStep.put("isFutureHold", '0');// 初始化0

        //check if it is the future hold step (for EEN_CONTEXT_HOLDLOT and EEN_CONTEXT_HOLDPRODUCT)
        long contextRrn = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDLOT, facilityRrn, ObjectList.CONTEXT_KEY);
        mainProStep.put("refRrn", new Long(contextRrn));
        mainProStep.put("lotRrn", lotRrn);

        Long refRrn = MapUtils.getLong(mainProStep, "refRrn");
        Long routeRrn = MapUtils.getLong(mainProStep, "routeRrn");
        Long operationRrn = MapUtils.getLong(mainProStep, "operationRrn");
        Long routeSeq = MapUtils.getLong(mainProStep, "routeSeq");// 获取路径序号
        Long operationSeq = MapUtils.getLong(mainProStep, "operationSeq");// 获取步骤序号
        Long lotRrn1 = MapUtils.getLong(mainProStep, "lotRrn");
        Long productRrn = MapUtils.getLong(mainProStep, "productRrn");
        Long processRrn = MapUtils.getLong(mainProStep, "processRrn");

        List futureHoldLotList = ctxExecService.getFutureHoldLotList(refRrn, routeRrn, operationRrn, lotRrn1, routeSeq,
                                                                     operationSeq);
        if (futureHoldLotList != null && futureHoldLotList.size() > 0) {
            mainProStep.put("isFutureHold", '1');
        } else {
            contextRrn = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDPRODUCT, facilityRrn, ObjectList.CONTEXT_KEY);
            mainProStep.put("refRrn", new Long(contextRrn));
            List futureHoldProductList = ctxExecService.getFutureHoldProductList(
                    MapUtils.getLong(mainProStep, "refRrn"), routeRrn, operationRrn, lotRrn1, productRrn, processRrn);
            if (futureHoldProductList != null && futureHoldProductList.size() > 0) {
                mainProStep.put("isFutureHold", '1');
            }
        }
    }

    private Recipe getRecipeByProcessInfo(long productRrn, Map process) throws Exception {

        Recipe recipe = new Recipe();

        String recipeString = MapUtils.getString(process, "recipe");
        if (StringUtils.isEmpty(recipeString)) {

            // get recipe through context
            Map tempInfo = new HashMap();
            tempInfo.put("operationRrn", new Long(((String) process.get("operationRrn"))));
            tempInfo.put("productRrn", new Long(productRrn));
            tempInfo.put("routeRrn", process.get("routeRrn"));
            tempInfo.put("technologyRrn", new Long(((String) process.get("processRrn"))));
            tempInfo.put("productLayer", MapUtils.getString(process, "productLayer"));
            tempInfo.put("entityRrn", MapUtils.getLong(process, "entityRrn"));
            tempInfo.put("equipmentModel", MapUtils.getLong(process, "equipmentModel"));
            tempInfo.put("lotRrn", MapUtils.getLong(process, "lotRrn"));
            tempInfo.put("routeSeq", MapUtils.getString(process, "routeProcessSeq"));
            tempInfo.put("operationSeq", MapUtils.getString(process, "operationRouteSeq"));
            tempInfo.put("processVersion", MapUtils.getString(process, "processVersion"));
            tempInfo.put("productVersion", MapUtils.getIntValue(process, "productVersion"));
            recipeString = ctxExecService.getRecipeString(tempInfo);
        }
        recipe = paraseRecipeString(recipeString);

        return recipe;
    }

    private void buildEquipAndReticleContext(Long facilityRrn, Map process) {
        LotSpecialInfo lotSpecialInfo = new LotSpecialInfo();
        LotSpecialEquipContextValue lotSpecialEquipContextValue = new LotSpecialEquipContextValue();
        lotSpecialEquipContextValue.setSequenceNumber(new Integer(1));
        lotSpecialEquipContextValue.setProductRrn(MapUtils.getLong(process, "productRrn"));
        lotSpecialEquipContextValue.setProcessRrn(MapUtils.getLong(process, "processRrn"));
        lotSpecialEquipContextValue.setRouteRrn(MapUtils.getLong(process, "routeRrn"));
        lotSpecialEquipContextValue.setOperationRrn(MapUtils.getLong(process, "operationRrn"));
        lotSpecialEquipContextValue.setLotRrn(MapUtils.getLong(process, "lotRrn"));
        lotSpecialEquipContextValue.setRouteSeq(MapUtils.getString(process, "routeSeq"));
        lotSpecialEquipContextValue.setOperationSeq(MapUtils.getString(process, "operationSeq"));
        ContextValue contextValue = ctxService.getContextValueNoFilter(lotSpecialEquipContextValue);
        if (contextValue != null) {
            BeanUtils.copyProperties(lotSpecialEquipContextValue, contextValue);
            lotSpecialInfo.setTargetEquipmentRrns(lotSpecialEquipContextValue.getEquipmentRrns());
            lotSpecialInfo.setTargetCheckEquipConstrain(lotSpecialEquipContextValue.getCheckEquipConstrain());
        }

        LotSpecialReticleContextValue lotSpecialReticleContextValue = new LotSpecialReticleContextValue();
        lotSpecialReticleContextValue.setSequenceNumber(new Integer(1));
        lotSpecialReticleContextValue.setProductRrn(MapUtils.getLong(process, "productRrn"));
        lotSpecialReticleContextValue.setProcessRrn(MapUtils.getLong(process, "processRrn"));
        lotSpecialReticleContextValue.setRouteRrn(MapUtils.getLong(process, "routeRrn"));
        lotSpecialReticleContextValue.setOperationRrn(MapUtils.getLong(process, "operationRrn"));
        lotSpecialReticleContextValue.setLotRrn(MapUtils.getLong(process, "lotRrn"));
        lotSpecialReticleContextValue.setRouteSeq(MapUtils.getString(process, "routeSeq"));
        lotSpecialReticleContextValue.setOperationSeq(MapUtils.getString(process, "operationSeq"));
        contextValue = ctxService.getContextValueNoFilter(lotSpecialReticleContextValue);
        if (contextValue != null) {
            BeanUtils.copyProperties(lotSpecialReticleContextValue, contextValue);
            lotSpecialInfo.setTargetReticleRrns(lotSpecialReticleContextValue.getReticleRrns());
        }

        lotSpecialInfo = buildLotSpecialInfo(lotSpecialInfo);
        if (StringUtils.isNotEmpty(lotSpecialInfo.getTargetEquipmentRrns())) {
            process.put("entityGroupId", "");
        } else {
            process.put("entityGroupId", specService.getEqptGroupIds(MapUtils.getLong(process, "processRrn"),
                                                                     MapUtils.getInteger(process, "processVersion"),
                                                                     MapUtils.getLong(process, "routeRrn"),
                                                                     MapUtils.getLong(process, "operationRrn")));


            String entityGroupRrns = specService.getEqptGroupRrns(MapUtils.getLong(process, "processRrn"),
                                                                  MapUtils.getInteger(process, "processVersion"),
                                                                  MapUtils.getLong(process, "routeRrn"),
                                                                  MapUtils.getLong(process, "operationRrn"));
            List entities = new ArrayList();
            for (String entityGroupRrn : entityGroupRrns.split(",")) {
                entities.addAll(baseService.getEntitiesRelationByGroupRrn(NumberUtils.toLong(entityGroupRrn)));
            }

            if (entities.size() > 0) {
                StringBuffer euipRrn = new StringBuffer();
                for (Iterator iterator3 = entities.iterator(); iterator3.hasNext(); ) {
                    Relation relation = (Relation) iterator3.next();
                    euipRrn.append(relation.getInstanceRrn()).append(",");
                }
                // get work area
                List<String> euipRrns = Arrays.asList(euipRrn.toString().split(","));
                euipRrns = euipRrns.stream().distinct().collect(Collectors.toList());
                List stations = new ArrayList();
                for (String rrn : euipRrns) {
                    List<Station> stationsByEquips = securityService.getStationsByEquips(NumberUtils.toLong(rrn));
                    stations.addAll(stationsByEquips);
                }

                StringBuffer stationInfo = new StringBuffer("");
                for (Iterator iterator = stations.iterator(); iterator.hasNext(); ) {
                    Station station = (Station) iterator.next();
                    stationInfo.append(station.getInstanceId()).append(" ");
                }
                process.put("dispatchArea", stationInfo.toString());
            }
        }

        if (StringUtils.isNotEmpty(lotSpecialInfo.getTargetReticleRrns())) {
            process.put("reticleFamilyId", StringUtils.EMPTY);
            process.put("rectileInfo", lotSpecialInfo.getTargetReticleIds());
        } else {
            long productRrn = MapUtils.getLongValue(process, "productRrn");
            long processRrn = MapUtils.getLongValue(process, "processRrn");
            int processVersion = MapUtils.getIntValue(process, "processVersion");
            Integer productVersion = MapUtils.getIntValue(process, "productVersion");
            long routeRrn = MapUtils.getLongValue(process, "routeRrn");
            long operationRrn = MapUtils.getLongValue(process, "operationRrn");
            long reticleFamilyRrn = ctxExecService.getReticleFamilyRrn(productRrn, productVersion, processRrn,
                                                                       processVersion, routeRrn, operationRrn);
            boolean hasReticleFamily = reticleFamilyRrn > 0;
            String reticleFamilyId = hasReticleFamily ? getInstanceId(reticleFamilyRrn) : StringUtils.EMPTY;
            String reticles = hasReticleFamily ? buildReticlesString(reticleFamilyRrn) : StringUtils.EMPTY;
            process.put("reticleFamilyId", reticleFamilyId);
            process.put("rectileInfo", reticles);
        }
    }

    private LotSpecialInfo buildLotSpecialInfo(LotSpecialInfo lotSpecialInfo) {

        if (StringUtils.isNotEmpty(lotSpecialInfo.getTargetEquipmentRrns())) {
            String targetEquipmentRrns = lotSpecialInfo.getTargetEquipmentRrns();
            String targetEquipmentIds = buildInstanceIds(targetEquipmentRrns);
            lotSpecialInfo.setTargetEquipmentIds(targetEquipmentIds);
        }

        if (lotSpecialInfo.getTargetRecipeRrn() > 0) {
            String targetRecipeId = baseService.getNamedObjectId(lotSpecialInfo.getTargetRecipeRrn());
            lotSpecialInfo.setTargetRecipeId(targetRecipeId);
        }

        if (StringUtils.isNotEmpty(lotSpecialInfo.getTargetReticleRrns())) {
            String targetReticleRrns = lotSpecialInfo.getTargetReticleRrns();
            String targetReticleIds = buildInstanceIds(targetReticleRrns);
            lotSpecialInfo.setTargetReticleIds(targetReticleIds);
        }

        if (StringUtils.isNotEmpty(lotSpecialInfo.getTargetMvInParameterSetRrns())) {
            String targetMvInParameterSetRrns = lotSpecialInfo.getTargetMvInParameterSetRrns();
            String targetMvInParameterSetIds = buildInstanceIds(targetMvInParameterSetRrns);
            lotSpecialInfo.setTargetMvInParameterSetIds(targetMvInParameterSetIds);
        }

        if (StringUtils.isNotEmpty(lotSpecialInfo.getTargetMvOutParameterSetRrns())) {
            String targetMvOutParameterSetRrns = lotSpecialInfo.getTargetMvOutParameterSetRrns();
            String targetMvOutParameterSetIds = buildInstanceIds(targetMvOutParameterSetRrns);
            lotSpecialInfo.setTargetMvOutParameterSetIds(targetMvOutParameterSetIds);
        }

        return lotSpecialInfo;
    }

    private void getRecipe4RouteAndProduct(long productRrn, Map process) {

        String recipeString = null;
        Recipe recipe = null;
        try {
            // get recipe through context
            Map tempInfo = new HashMap();
            tempInfo.put("operationRrn", new Long(((String) process.get("operationRrn"))));
            tempInfo.put("productRrn", new Long(productRrn));
            tempInfo.put("routeRrn", process.get("routeRrn"));
            tempInfo.put("technologyRrn", new Long(((String) process.get("processRrn"))));
            tempInfo.put("routeSeq", MapUtils.getString(process, "routeSeq"));
            tempInfo.put("operationSeq", MapUtils.getString(process, "operationSeq"));
            tempInfo.put("processVersion", MapUtils.getString(process, "processVersion"));

            Map recipeMap = ctxExecService.getRecipe4ViewPrpAction(tempInfo);
            if (recipeMap.get("product") != null) {
                recipeString = (String) recipeMap.get("product");
                recipe = paraseRecipeString(recipeString);

                process.put("recipeId4Product", recipe.getInstanceId());
                process.put("recipeDesc4Product", recipe.getInstanceDesc());
                process.put("recipeParam4Product", recipe.getRecipeParam());
            }
            if (recipeMap.get("route") != null) {
                recipeString = (String) recipeMap.get("route");
                recipe = paraseRecipeString(recipeString);

                process.put("recipeId4Route", recipe.getInstanceId());
                process.put("recipeDesc4Route", recipe.getInstanceDesc());
                process.put("recipeParam4Route", recipe.getRecipeParam());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private Recipe paraseRecipeString(String recipeString) throws Exception {
        Recipe recipe = new Recipe();
        if (StringUtils.isBlank(recipeString) || StringUtils.equalsIgnoreCase("null", recipeString)) {
            recipe.setInstanceId("");
            recipe.setRecipeParam("");
        } else {
            // /recipeId|recipeParam
            int index = recipeString.indexOf("|");
            long recipeRrn = 0;
            String para = "";
            if (index >= 0) {
                recipeRrn = NumberUtils.toLong(StringUtils.substring(recipeString, 0, index));
                para = recipeString.substring(index + 1, recipeString.length());
            } else {
                if (StringUtils.isNotBlank(recipeString)) {
                    recipeRrn = NumberUtils.toLong(recipeString);
                }
            }
            recipe = recipeService.getRecipe(Long.valueOf(recipeRrn).longValue());
            if (recipe != null) {
                recipe.setRecipeParam(para);
            } else {
                recipe = new Recipe();
                recipe.setInstanceId(StringUtils.EMPTY);
                recipe.setRecipeParam(StringUtils.EMPTY);
            }
        }
        return recipe;
    }

    /**
     * 获取步骤的跨站时间限制
     *
     * @param process 当前工艺
     * @return 跨站时间限制
     */
    private String getOperationQueueTime(Map process) {
        StringBuilder sb = new StringBuilder();
        TimeLimitSetup timeLimitSetupTempLimitSetup = new TimeLimitSetup();
        timeLimitSetupTempLimitSetup.setStartProductRrn(MapUtils.getLongValue(process, "productRrn"));
        timeLimitSetupTempLimitSetup.setStartProcessRrn(MapUtils.getLongValue(process, "processRrn"));
        timeLimitSetupTempLimitSetup.setStartProcessVersion(MapUtils.getIntValue(process, "processVersion"));
        timeLimitSetupTempLimitSetup.setStartRouteRrn(MapUtils.getLongValue(process, "routeRrn"));
        timeLimitSetupTempLimitSetup.setStartOperationRrn(MapUtils.getLongValue(process, "operationRrn"));
        List<TimeLimitSetup> timeLimitSetupsByStartInfo = prpService.getTimeLimitSetupsByStartInfo(
                timeLimitSetupTempLimitSetup);
        for (TimeLimitSetup timeLimitSetup : timeLimitSetupsByStartInfo) {
            sb.append(timeLimitSetup.getInstanceId()).append(",");
        }
        String ret = sb.toString();
        return StringUtils.isNotEmptyTrim(ret) ? StringUtils.substringBeforeLast(ret, ",") : ret;
    }

    private Map getOperationSeqAndWait(Map process) {
        Map seqAndWait = new HashMap();
        String seq = "";
        String waitingTime = "";
        String oPollutionLevel = "";
        String oOperationComment = "";
        try {
            String seqAndWaitString = (String) process.get("seqAndWaitString");
            if (seqAndWaitString == null || seqAndWaitString.trim().equals("")) {
                HashMap tempInfo = new HashMap();
                tempInfo.put("facilityRrn", process.get("facilityRrn"));
                tempInfo.put("operationRrn", new Long((process.get("operationRrn")).toString()));
                tempInfo.put("routeRrn", process.get("routeRrn"));
                tempInfo.put("technologyRrn", new Long((process.get("processRrn")).toString()));
                tempInfo.put("productRrn", new Long((process.get("productRrn")).toString()));
                tempInfo.put("processVersion", MapUtils.getString(process, "processVersion"));

                seqAndWaitString = ctxExecService.getOperationSeqAndWait(MapUtils.getLong(process, "productRrn"),
                                                                         MapUtils.getLong(process, "processRrn"),
                                                                         MapUtils.getLong(process, "routeRrn"),
                                                                         MapUtils.getLong(process, "operationRrn"));
            }

            if (seqAndWaitString == null || "null".equalsIgnoreCase(seqAndWaitString.trim()) ||
                    seqAndWaitString.length() == 0) {

            } else {
                // /seq|waitingTime
                int firstIndex = seqAndWaitString.indexOf("|", 0);
                int secondIndex = seqAndWaitString.indexOf("|", firstIndex + 1);
                int lastIndex = seqAndWaitString.lastIndexOf("|");

                if (firstIndex >= 0) {
                    seq = seqAndWaitString.substring(0, firstIndex);
                    waitingTime = seqAndWaitString.substring(firstIndex + 1, secondIndex);
                    oPollutionLevel = seqAndWaitString.substring(secondIndex + 1, lastIndex);
                    oOperationComment = seqAndWaitString.substring(lastIndex + 1, seqAndWaitString.length());
                } else {
                    if (!"".equalsIgnoreCase(seqAndWaitString.trim())) {
                        seq = seqAndWaitString;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        seqAndWait.put("SEQ", seq);
        seqAndWait.put("WAITING_TIME", waitingTime);
        seqAndWait.put("oPollutionLevel", oPollutionLevel);
        seqAndWait.put("oOperationComment", oOperationComment);
        return seqAndWait;
    }

    private Map getEdcContextValueByLot(Map process) {
        Map result = new HashMap();
        try {
            Map tempInfo = new HashMap();
            tempInfo.put("facilityRrn", process.get("facilityRrn"));
            tempInfo.put("operationRrn", new Long((process.get("operationRrn")).toString()));
            tempInfo.put("routeRrn", process.get("routeRrn"));
            tempInfo.put("technologyRrn", new Long((process.get("processRrn")).toString()));
            tempInfo.put("productRrn", new Long((process.get("productRrn")).toString()));
            tempInfo.put("routeSeq", process.get("routeSeq"));
            tempInfo.put("operationSeq", process.get("operationSeq"));
            tempInfo.put("processVersion", process.get("processVersion"));
            tempInfo.put("lotRrn", process.get("lotRrn"));
            tempInfo.put("", process.get("processRrn"));

            result = ctxExecService.getEdcContextValueByLot(tempInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    private Map getReworkRoute(Map processInfo) {
        Map result = new HashMap();

        ReworkRouteContextValue contextValue = new ReworkRouteContextValue();
        contextValue.setContextRrn(
                getInstanceRrn(contextValue.getContextId(), LocalContext.getFacilityRrn(), ObjectList.CONTEXT_KEY));
        contextValue.setContextKey1(MapUtils.getString(processInfo, "productRrn"));
        contextValue.setContextKey2(MapUtils.getString(processInfo, "processRrn"));
        contextValue.setContextKey3(MapUtils.getString(processInfo, "routeRrn"));
        contextValue.setContextKey4(MapUtils.getString(processInfo, "operationRrn"));
        contextValue.setContextKey8(MapUtils.getString(processInfo, "processVersion"));

        ContextValue actionCondition = ctxService.simulateContextValue(contextValue);
        if (actionCondition != null) {
            String reworkRouteRrn = actionCondition.getResultValue1();
            String maxReworkTimes = actionCondition.getResultValue4();
            result.put("reworkRouteRrn", reworkRouteRrn);
            result.put("maxReworkTimes", maxReworkTimes);
        }
        return result;
    }

    private List getParameters(long parameterSetRrn) {
        return edcService.getParameters(parameterSetRrn);
    }

    private String buildEquipInfoForlotSpecial(String targetEquipmentRrns) {

        StringBuilder instanceIds = new StringBuilder();
        String[] instanceRrnArray = StringUtils.split(targetEquipmentRrns, LotSpecialEquipContextValue.SEPARATOR);

        for (int i = 0; i < instanceRrnArray.length; i++) {
            String instanceRrn = instanceRrnArray[i];
            if (StringUtils.isBlank(instanceRrn)) {
                continue;
            }
            if (StringUtils.isNumeric(instanceRrn)) {
                Entity entity = emsService.getEntity(new Entity(Long.valueOf(instanceRrn)));
                if (StringUtils.isNotEmpty(entity.getInstanceId())) {
                    List entityStatuss = emsService.getEntityStatuss(Long.valueOf(instanceRrn));
                    Iterator entityStatussIt = entityStatuss.iterator();
                    String currentStatus = "";
                    while (entityStatussIt.hasNext()) {
                        EntityStatus entityStatus = (EntityStatus) entityStatussIt.next();
                        currentStatus = entityStatus.getCurrentStatus();
                    }
                    instanceIds.append(entity.getInstanceId())
                               .append((StringUtils.isBlank(currentStatus)) ? " " : "(" + currentStatus + ") ")
                               .append(StringUtils.isBlank(entity.getPollutionLevel()) ? " " :
                                               "(" + entity.getPollutionLevel() + ") ");
                }
            }
            if (i < instanceRrnArray.length - 1) {
                instanceIds.append(",");
            }
        }

        return instanceIds.toString();
    }

    private String buildInstanceIds(String instanceRrns) {
        StringBuffer instanceIds = new StringBuffer();
        String[] instanceRrnArray = StringUtils.split(instanceRrns, LotSpecialEquipContextValue.SEPARATOR);

        for (int i = 0; i < instanceRrnArray.length; i++) {
            String instanceRrn = instanceRrnArray[i];
            if (StringUtils.isBlank(instanceRrn)) {
                continue;
            }
            if (NumberUtils.isNumber(instanceRrn)) {
                String instanceId = baseService.getNamedObjectId(NumberUtils.toLong(instanceRrn));
                if (StringUtils.isNotEmpty(instanceId)) {
                    instanceIds.append(instanceId);
                }
            }
            if (i < instanceRrnArray.length - 1) {
                instanceIds.append(",");
            }
        }

        return instanceIds.toString();
    }

    private void buildEdcPlanInfos(long lotRrn, String stepSequence, String lotId, String parameterSetId,
                                   String quantity, List<Map> edcPlanInfo) {
        List parameterData = edcService.getParameterData(lotRrn, stepSequence);
        if (CollectionUtils.isNotEmpty(parameterData)) {
            int i = 1;
            for (Object parameterDatum : parameterData) {
                Map m2 = (Map) parameterDatum;
                Map newMap = new HashMap();
                newMap.put("seq", i);
                newMap.put("lotId", lotId);
                newMap.put("edcPlan", parameterSetId);
                newMap.put("waferQty", quantity);
                newMap.put("waferId", m2.get("unitId"));
                newMap.put("parameterId", m2.get("edcId"));
                newMap.put("parameterValue", m2.get("dataValue"));
                newMap.put("collectionTimestamp", m2.get("collectionTimeStamp"));
                edcPlanInfo.add(newMap);
                i++;
            }
        }
    }

    private Map<String, Map<String, Object>> getContextValuesForActiveWithOther(Long lotRrn, Long productRrn,
                                                                                Long processRrn,
                                                                                Integer processVersion) {
        Map<String, Map<String, Object>> contextValues = getContextValuesForActive(productRrn, processRrn,
                                                                                   processVersion);

        buildFutureHoldToValueMap(lotRrn, productRrn, processRrn, processVersion, contextValues);


        buildTimeLimitToValueMap(productRrn, processRrn, processVersion, contextValues);

        return contextValues;
    }

    private Map<String, Map<String, Object>> getContextValuesForActive(Long productRrn, Long processRrn,
                                                                       Integer processVersion) {
        Map<String, Map<String, Object>> result = new HashMap<>();
        buildFlowSeqContextToValueMap(productRrn, processRrn, processVersion, result);
        buildOperationContextToValueMap(productRrn, processRrn, processVersion, result);
        buildReworkContextToValueMap(productRrn, processRrn, processVersion, result);

        return result;
    }

    private void buildFlowSeqContextToValueMap(Long productRrn, Long processRrn, Integer processVersion,
                                               Map<String, Map<String, Object>> map) {
        Map<String, Object> obj;
        List<ContextValue> contextValues;
        contextValues = ctxExecService.getFlowSeqContextValueList(processRrn, processVersion);
        for (ContextValue contextValue : contextValues) {
            long processRrnTemp = NumberUtils.toLong(contextValue.getContextKey1());
            int processVersionTemp = NumberUtils.toInt(contextValue.getContextKey2());
            long routeRrnTemp = NumberUtils.toLong(contextValue.getContextKey3());
            long operationRrnTemp = NumberUtils.toLong(contextValue.getContextKey4());

            String key = buildKeyByProduct(productRrn, processRrnTemp, processVersionTemp, routeRrnTemp,
                                           operationRrnTemp);

            obj = map.get(key);
            if (obj == null) {
                obj = new HashMap<>();
                map.put(key, obj);
            }

            obj.put("queryContextRrn", contextValue.getContextRrn());
            obj.put(KEY_FLOW_SEQ, contextValue.getResultValue1());
            obj.put("reworkFlag", contextValue.getResultValue2());
            obj.put("flowSeqStatus", contextValue.getStatus());
        }
    }

    private void buildOperationContextToValueMap(Long productRrn, Long processRrn, Integer processVersion,
                                                 Map<String, Map<String, Object>> map) {
        Map<String, Object> obj;
        List<ContextValue> contextValues;
        contextValues = ctxExecService.getPollutionLevelContextValueList(NumberUtils.LONG_ZERO, processRrn,
                                                                         processVersion);
        for (ContextValue contextValue : contextValues) {
            String key = buildKeyByProduct(productRrn, NumberUtils.toLong(contextValue.getContextKey3()),
                                           NumberUtils.toInt(contextValue.getContextKey8()),
                                           NumberUtils.toLong(contextValue.getContextKey2()),
                                           NumberUtils.toLong(contextValue.getContextKey1()));
            obj = map.get(key);
            if (obj == null) {
                obj = new HashMap<>();
                map.put(key, obj);
            }

            obj.put(KEY_WAITING_TIME, contextValue.getResultValue2());
            obj.put(KEY_POLLUCTION_LEVEL, contextValue.getResultValue3());
            obj.put(KEY_OPERATION_COMMENT, contextValue.getResultValue4());
        }
    }

    private void buildReworkContextToValueMap(Long productRrn, Long processRrn, Integer processVersion,
                                              Map<String, Map<String, Object>> map) {
        Map<String, Object> obj;
        List<ContextValue> contextValues;
        contextValues = ctxExecService.getReworkContextValueList(processRrn, processVersion);
        for (ContextValue contextValue : contextValues) {
            String key = buildKeyByProduct(productRrn, NumberUtils.toLong(contextValue.getContextKey2()),
                                           NumberUtils.toInt(contextValue.getContextKey8()),
                                           NumberUtils.toLong(contextValue.getContextKey3()),
                                           NumberUtils.toLong(contextValue.getContextKey4()));

            obj = map.get(key);
            if (obj == null) {
                obj = new HashMap<>();
                map.put(key, obj);
            }

            long reworkRouteRrn = NumberUtils.toLong(contextValue.getResultValue1());
            obj.put(KEY_REWORK_ROUTE_RRN, reworkRouteRrn);
            obj.put(KEY_REWORK_ROUTE_ID, getInstanceId(reworkRouteRrn));
            obj.put(KEY_REWORK_ROUTE_VERSION, contextValue.getResultValue5());
            obj.put(KEY_MAX_REWORK_TIMES, contextValue.getResultValue4());
        }
    }


    private void buildFutureHoldToValueMap(Long lotRrn, Long productRrn, Long processRrn, Integer processVersion,
                                           Map<String, Map<String, Object>> map) {
        Map<String, Object> obj;
        List<Map> contextValues;
        long refRrnByLot = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDLOT, LocalContext.getFacilityRrn(),
                                          ObjectList.CONTEXT_KEY);
        contextValues = ctxExecService.getFutureHoldListByLot(refRrnByLot, lotRrn);
        for (Map contextValue : contextValues) {
            String key = buildKeyByProduct(productRrn, processRrn, processVersion,
                                           NumberUtils.toLong(MapUtils.getString(contextValue, "routeRrn")),
                                           NumberUtils.toLong(MapUtils.getString(contextValue, "operationRrn")));

            obj = map.get(key);
            if (obj == null) {
                obj = new HashMap<>();
                map.put(key, obj);
            }

            obj.put(KEY_HAS_FUTURE_HOLD, true);
        }
        long refRrnByProd = getInstanceRrn(ContextNames.EEN_CONTEXT_HOLDPRODUCT, LocalContext.getFacilityRrn(),
                                           ObjectList.CONTEXT_KEY);

        contextValues = ctxExecService.getFutureHoldListByProduct(refRrnByProd, productRrn, processRrn, lotRrn);
        for (Map contextValue : contextValues) {
            String key = buildKeyByProduct(productRrn, processRrn, processVersion,
                                           NumberUtils.toLong(MapUtils.getString(contextValue, "routeRrn")),
                                           NumberUtils.toLong(MapUtils.getString(contextValue, "operationRrn")));

            obj = map.get(key);
            if (obj == null) {
                obj = new HashMap<>();
                map.put(key, obj);
            }

            obj.put(KEY_HAS_FUTURE_HOLD, true);
        }
    }

    private void buildTimeLimitToValueMap(Long productRrn, Long processRrn, Integer processVersion,
                                          Map<String, Map<String, Object>> contextValues) {
        Map<String, Object> obj;
        List<TimeLimitSetup> timeLimitSetupForActiveByPro = prpService.getTimeLimitSetupForActiveByPro(
                NumberUtils.LONG_ZERO, processRrn, processVersion);
        for (TimeLimitSetup timeLimitSetup : timeLimitSetupForActiveByPro) {
            if (!(timeLimitSetup.getStartProductRrn() == null || timeLimitSetup.getStartProductRrn() == 0 ||
                    StringUtils.equals(StringUtils.toString(productRrn),
                                       StringUtils.toString(timeLimitSetup.getStartProductRrn())))) {
                continue;
            }

            String key = buildKeyByProduct(productRrn, timeLimitSetup.getStartProcessRrn(),
                                           timeLimitSetup.getStartProcessVersion(), timeLimitSetup.getStartRouteRrn(),
                                           timeLimitSetup.getStartOperationRrn());

            obj = contextValues.get(key);
            if (obj == null) {
                obj = new HashMap<>();
                contextValues.put(key, obj);
            }

            String qTime = MapUtils.getString(obj, KEY_QUEUE_TIME);
            qTime = StringUtils.isEmpty(qTime) ? StringUtils.EMPTY : qTime;
            qTime += timeLimitSetup.getInstanceId() + " " + timeLimitSetup.getTimeLimit() + ";";

            obj.put(KEY_QUEUE_TIME, qTime);
        }
    }

    private String buildKeyByProduct(Long productRrn, Long processRrn, Integer processVersion, Long routeRrn,
                                     Long operationRrn) {
        StringBuilder keyByProduct = new StringBuilder();
        keyByProduct.append(productRrn).append("|");
        keyByProduct.append(processRrn).append("|");
        keyByProduct.append(processVersion).append("|");
        keyByProduct.append(routeRrn).append("|");
        keyByProduct.append(operationRrn);
        return keyByProduct.toString();
    }

    private Map getDispatchArea(String entityGroupRrns, List<Relation> allRelationByEquip) {
        List<Long> relationRrns = new ArrayList<>();
        List buildRelations = new ArrayList();
        Map result = new HashMap();
        List<Relation> relations = new ArrayList<>();
        for (String entityGroupRrn : entityGroupRrns.split(",")) {
            relations.addAll(baseService.getRelationsUseToRrn(NumberUtils.toLong(entityGroupRrn),
                                                              LinkTypeList.ENTITY_ENTITYROUP_KEY));
        }
        relations = relations.stream().distinct().collect(Collectors.toList());
        for (Relation relation : relations) {
            relationRrns.add(relation.getFromRrn());
        }
        for (Long equipmentRrn : relationRrns) {
            for (Relation relation : allRelationByEquip) {
                Long relationEquipmentRrn = relation.getToRrn();
                if (relationEquipmentRrn.equals(equipmentRrn)) {
                    buildRelations.add(relation);
                }
            }
        }
        StringBuffer relationInfo = new StringBuffer("");
        for (Object relation : buildRelations) {
            Relation relationInstance = (Relation) relation;
            if (StringUtils.isNotBlank(relationInstance.getInstanceId()))
                relationInfo.append(relationInstance.getInstanceId()).append(" ");
        }
        result.put("dispatchArea", relationInfo.toString());
        return result;
    }

}