AutoMonitorItemAction.java

package com.mycim.webapp.actions;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
import com.fa.sesa.i18n.I18nUtils;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.context.spring.SpringContext;
import com.mycim.framework.jdbc.Page;
import com.mycim.framework.utils.beans.BeanUtils;
import com.mycim.framework.utils.lang.BooleanUtils;
import com.mycim.framework.utils.lang.StringUtils;
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.edcchart.service.EdcChartService;
import com.mycim.utils.CheckRegexUtils;
import com.mycim.utils.NonRTMathUtil;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.SystemConstant;
import com.mycim.valueobject.automonitor.dto.AutoMonitorItemDTO;
import com.mycim.valueobject.automonitor.dto.AutoMonitorItemQueryDTO;
import com.mycim.valueobject.automonitor.entity.AutoMonitorItem;
import com.mycim.valueobject.automonitor.entity.AutoMonitorItemStep;
import com.mycim.valueobject.automonitor.util.AutoMonitorOperationConstants;
import com.mycim.valueobject.automonitor.util.AutoMonitorUtils;
import com.mycim.valueobject.ems.Entity;
import com.mycim.valueobject.ems.Equipment;
import com.mycim.valueobject.ems.Reticle;
import com.mycim.valueobject.prp.Recipe;
import com.mycim.valueobject.wip.Lot;
import com.mycim.webapp.WebUtils;
import org.apache.commons.collections.CollectionUtils;
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.util.*;

/**
 * @author finatice.yang
 */
public class AutoMonitorItemAction extends AutoMonitorAction {

    private static final String MAIN_EDC_SIGN = "M";

    private static final String RECIPE_CHAMBER_ID_SEPARATOR = "-";

    private static final String CHAMBER_FLAG = "_";

    protected EdcChartService edcChartService = SpringContext.getBean(EdcChartService.class);

    @Override
    public ActionForward init(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                              HttpServletResponse response) {
        request.setAttribute("mainEqptType",
                             AutoMonitorUtils.checkItemMainEqptType(WebUtils.getParameter("mainEqptType", request)));
        return mapping.findForward("init");
    }

    public ActionForward initItemInfo(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                      HttpServletResponse response) {
        request.setAttribute("workflowRrn", WebUtils.getParameter("workflowRrn", request));
        request.setAttribute("workflowVersion", WebUtils.getParameter("workflowVersion", request));
        request.setAttribute("mainEqptType",
                             AutoMonitorUtils.checkItemMainEqptType(WebUtils.getParameter("mainEqptType", request)));
        request.setAttribute("onlyShow", WebUtils.getParameter("onlyShow", request));
        request.setAttribute("canActive", WebUtils.getParameter("canActive", request));
        return mapping.findForward("iteminfo");
    }

    public Map queryItemPage(Map map) {
        int pageSize = MapUtils.getIntValue(map, "limit");
        int pageNo = MapUtils.getIntValue(map, "page");
        Map<String, Object> pageMap = MapUtils.newHashMap();
        AutoMonitorItemQueryDTO queryDTO = new AutoMonitorItemQueryDTO();

        queryDTO.setEqptId(CheckRegexUtils.formatSearchString(MapUtils.getString(map, "eqptId")));
        queryDTO.setItemType(CheckRegexUtils.formatSearchString(MapUtils.getString(map, "itemType")));
        queryDTO.setProductId(CheckRegexUtils.formatSearchString(MapUtils.getString(map, "productId")));
        queryDTO.setMainEqptType(AutoMonitorUtils.checkItemMainEqptType(MapUtils.getString(map, "mainEqptType")));

        Page page = new Page(pageNo, pageSize);

        page = autoMonitorItemInqService.getAutoMonitorItemPage(page, queryDTO);

        pageMap.put("totalItems", page.getTotalItems());
        pageMap.put("items", page.getResults());

        return pageMap;
    }

    public Map queryItemInfo(Map map) {
        Long workflowRrn = MapUtils.getLong(map, "workflowRrn");
        Integer workflowVersion = MapUtils.getInteger(map, "workflowVersion");

        AutoMonitorItemDTO itemDTO = autoMonitorItemInqService.getAutoMonitorItemInfo(workflowRrn, workflowVersion);

        return BeanUtils.copyBeanToMap(itemDTO);
    }

    public Map saveItemInfo(Map map) {
        AutoMonitorItemDTO monitorItemDTO = new AutoMonitorItemDTO();
        monitorItemDTO.setAutoMonitorItem(buildAutoMonitorItem(map));
        monitorItemDTO.setStepList(buildAutoMonitorItemSteps(map));

        autoMonitorItemReqService.saveAutoMonitorItem(monitorItemDTO);

        AutoMonitorItem item = autoMonitorItemInqService
                .getAutoMonitorItem(monitorItemDTO.getAutoMonitorItem().getEqptRrn(),
                                    monitorItemDTO.getAutoMonitorItem().getItemType());
        return BeanUtils.copyBeanToMap(item);
    }

    public Map activeItemInfo(Map map) {
        AutoMonitorItemDTO monitorItemDTO = new AutoMonitorItemDTO();
        monitorItemDTO.setAutoMonitorItem(buildAutoMonitorItem(map));
        monitorItemDTO.setStepList(buildAutoMonitorItemSteps(map));

        String errorMsg = validateMonitorItemForActive(monitorItemDTO);
        Assert.state(StringUtils.isBlank(errorMsg), Errors.create().content(errorMsg).build());

        autoMonitorItemReqService.activeAutoMonitorItem(monitorItemDTO);
        AutoMonitorItem item = autoMonitorItemInqService
                .getAutoMonitorItem(monitorItemDTO.getAutoMonitorItem().getEqptRrn(),
                                    monitorItemDTO.getAutoMonitorItem().getItemType());
        return BeanUtils.copyBeanToMap(item);
    }

    public Map deleteItemInfo(Map map) {
        Long workflowRrn = MapUtils.getLong(map, "workflowRrn");
        Integer workflowVersion = MapUtils.getInteger(map, "workflowVersion");
        AutoMonitorItemDTO itemDTO = autoMonitorItemInqService.getAutoMonitorItemInfo(workflowRrn, workflowVersion);
        if (Objects.isNull(itemDTO)) {
            itemDTO = new AutoMonitorItemDTO();

            AutoMonitorItem item = new AutoMonitorItem();
            item.setWorkflowRrn(workflowRrn);
            item.setWorkflowVersion(workflowVersion);
            itemDTO.setAutoMonitorItem(item);
        }
        autoMonitorItemReqService.deleteAutoMonitorItem(itemDTO);
        return BeanUtils.copyBeanToMap(itemDTO);
    }

    public Map disableItemInfo(Map map) {
        Long workflowRrn = MapUtils.getLong(map, "workflowRrn");
        Integer workflowVersion = MapUtils.getInteger(map, "workflowVersion");
        AutoMonitorItemDTO itemDTO = autoMonitorItemInqService.getAutoMonitorItemInfo(workflowRrn, workflowVersion);
        if (Objects.nonNull(itemDTO)) {
            autoMonitorItemReqService
                    .disableAutoMonitorItem(workflowRrn, !itemDTO.getAutoMonitorItem().getSysInActiveFlag());
        }
        return BeanUtils.copyBeanToMap(itemDTO);
    }

    public Map addVersion(Map map) {
        Long workflowRrn = MapUtils.getLong(map, "workflowRrn");
        Integer workflowVersion = MapUtils.getInteger(map, "workflowVersion");
        autoMonitorItemReqService.addAutoMonitorItemVersion(workflowRrn, workflowVersion);
        map.put("workflowRrn", workflowRrn);
        map.put("workflowVersion", workflowVersion + 1);
        return map;
    }

    public Map getProcessByProductId(Map param) {
        String productId = MapUtils.getString(param, "productId");
        long productRrn = getInstanceRrn(productId, LocalContext.getFacilityRrn(), ObjectList.PRODUCT_KEY);

        Map<String, Object> result = MapUtils.newHashMap();
        if (productRrn > 0) {
            List<Long> processRrns = prpService.getProcessRrnsByProductRrn(productRrn);
            if (CollectionUtils.isNotEmpty(processRrns)) {
                Long processRrn = processRrns.iterator().next();
                result.put("processId", getInstanceId(processRrn));
                result.put("processRrn", processRrn);
            }
        }
        return result;
    }

    public Map queryNonRTJobList(Map param) {
        String eqptId = MapUtils.getString(param, "eqptId");
        long eqptRrn = getInstanceRrn(eqptId, LocalContext.getFacilityRrn(), ObjectList.ENTITY_KEY);

        List<Map> resultList = new ArrayList<>();

        if (eqptRrn > 0) {
            resultList = edcChartService.getMainEqpNonRTJobList(eqptRrn);
        }

        Map msg = MapUtils.newHashMap();
        msg.put("resultInfo", resultList);

        return msg;
    }

    public Map queryItemVersion(Map map) {
        Map returnMap = MapUtils.newHashMap();
        String eqptId = MapUtils.getString(map, "eqptId");
        long eqptRrn = getInstanceRrn(eqptId, LocalContext.getFacilityRrn(), ObjectList.ENTITY_KEY);

        String itemType = MapUtils.getString(map, "itemType");
        AutoMonitorItem item = autoMonitorItemInqService.getAutoMonitorItem(eqptRrn, itemType);

        if (item != null) {
            returnMap.put("workflowRrn", item.getWorkflowRrn());
            returnMap.put("workflowVersion", item.getCurrentVersion());
        }
        return returnMap;
    }

    public Map queryItemVersionStepList(Map map) {
        String eqptId = MapUtils.getString(map, "eqptId");
        String itemType = MapUtils.getString(map, "itemType");

        String workflowId = AutoMonitorUtils.buildItemWorkflowId(eqptId, itemType);

        long workflowRrn = getInstanceRrn(workflowId, LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);
        Integer workflowVersion = MapUtils.getInteger(map, "workflowVersion");

        Assert.state(workflowRrn > 0, Errors.create().content("Monitor Item not found").build());

        AutoMonitorItemDTO itemDTO = autoMonitorItemInqService.getAutoMonitorItemInfo(workflowRrn, workflowVersion);
        return BeanUtils.copyBeanToMap(itemDTO);
    }

    public AutoMonitorItem buildAutoMonitorItem(Map map) {
        AutoMonitorItem itemInfo = new AutoMonitorItem();

        String eqptId = StringUtils.trimToUpperCase(MapUtils.getString(map, "eqptId"));
        String itemType = StringUtils.trimToUpperCase(MapUtils.getString(map, "itemType"));
        String isNewFlag = MapUtils.getString(map, "isNewFlag");
        long eqptRrn = getInstanceRrn(eqptId, LocalContext.getFacilityRrn(), ObjectList.ENTITY_KEY);
        Assert.state(eqptRrn > 0,
                     Errors.create().key(MessageIdList.EQUIPMENT_ID_NOT_EXIST).content("Equipment does not exist!")
                           .build());
        Assert.state(StringUtils.isNotBlank(itemType), Errors.create().content("Item type is null!").build());

        String workflowId = AutoMonitorUtils.buildItemWorkflowId(eqptId, itemType);
        Long workflowRrn = getInstanceRrn(workflowId, LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);
        if (workflowRrn != null && workflowRrn.longValue() > 0 && StringUtils.isNotBlank(isNewFlag)) {
            AutoMonitorItem item = autoMonitorItemInqService.getAutoMonitorItem(eqptRrn, itemType);

            if (item.getSysInActiveFlag()) {
                throw new SystemIllegalArgumentException(
                        Errors.create().content("Item deleted, please contact IT for recovery.").build());
            } else {
                throw new SystemIllegalArgumentException(Errors.create().content("Item is exsit!").build());
            }

        }

        itemInfo.setEqptId(eqptId);
        itemInfo.setEqptRrn(eqptRrn);
        itemInfo.setWorkflowId(workflowId);
        itemInfo.setWorkflowRrn(workflowRrn);
        itemInfo.setWorkflowVersion(MapUtils.getInteger(map, "currentVersion"));
        itemInfo.setItemType(itemType);

        itemInfo.setQty(MapUtils.getLong(map, "qty"));

        String productId = MapUtils.getString(map, "productId");
        long productRrn = getInstanceRrn(productId, LocalContext.getFacilityRrn(), ObjectList.PRODUCT_KEY);
        itemInfo.setProductId(productId);
        itemInfo.setProductRrn(productRrn);

        String processId = MapUtils.getString(map, "processId");
        long processRrn = getInstanceRrn(processId, LocalContext.getFacilityRrn(), ObjectList.WFL_KEY);
        itemInfo.setProcessId(processId);
        itemInfo.setProcessRrn(processRrn);

        itemInfo.setCurrentVersion(MapUtils.getInteger(map, "currentVersion"));
        itemInfo.setActiveVersion(MapUtils.getInteger(map, "activeVersion"));

        if (CheckRegexUtils.checkFlagOn(MapUtils.getString(map, "monitorCarrierFlag"))) {
            itemInfo.setMonitorCarrierFlag(Boolean.TRUE);
            itemInfo.setMonitorCarrierType(MapUtils.getString(map, "monitorCarrierType"));
            itemInfo.setStartSplitFlag(CheckRegexUtils.checkFlagOn(MapUtils.getString(map, "startSplitFlag")));
        }

        itemInfo.setMainEqptType(AutoMonitorUtils.checkItemMainEqptType(MapUtils.getString(map, "mainEqptType")));
        if (StringUtils
                .equals(AutoMonitorUtils.AutoMonitorItemMainEqptType.DIFF.toString(), itemInfo.getMainEqptType())) {
            itemInfo.setMonitorCarrierFlag(Boolean.TRUE);
            itemInfo.setMonitorCarrierType(AutoMonitorUtils.AutoMonitorItemMonitorCarrierType.SINGLE.toString());
        }

        return itemInfo;
    }

    public Map checkIfEquipmentIsNeedReticle(Map map) {
        Equipment equipment = emsService
                .getEquipment(MapUtils.getString(map, "equipmentId"), LocalContext.getFacilityRrn());
        Assert.state(Objects.nonNull(equipment) && equipment.getInstanceRrn() > 0,
                     Errors.create().content("Equipment {} does not exist!")
                           .args(MapUtils.getString(map, "equipmentId")).build());

        Map<String, Object> equipmentInfo = MapUtils.newHashMap();

        equipmentInfo.put("equipmentRrn", equipment.getInstanceRrn());
        equipmentInfo.put("equipmentId", equipment.getInstanceId());
        equipmentInfo.put("isNeedReticle", wipCheckService.checkIfEquipmentIsNeedReticle(equipment.getInstanceRrn()));

        return equipmentInfo;
    }

    public Map<String, Object> checkIfEquipmentGroupIsNeedReticle(Map<String, Object> params) {
        String equipmentGroupId = MapUtils.getString(params, "equipmentGroupId", StringUtils.EMPTY);
        long equipmentGroupRrn = getInstanceRrn(equipmentGroupId, LocalContext.getFacilityRrn(),
                                                ObjectList.ENTITYGROUP_KEY);
        Assert.state(equipmentGroupRrn > 0,
                     Errors.create().key(MessageIdList.ENTITY_MISSING_ENTITYGROUP_ID).content("Missing EQP group id!")
                           .build());

        Map<String, Object> equipmentInfo = new HashMap<>();
        equipmentInfo.put("equipmentGroupRrn", equipmentGroupRrn);
        equipmentInfo.put("equipmentGroupId", equipmentGroupId);
        equipmentInfo.put("isNeedReticle", wipCheckService.checkIfEquipmentGroupIsNeedReticle(equipmentGroupRrn));
        return equipmentInfo;
    }

    private List<AutoMonitorItemStep> buildAutoMonitorItemSteps(Map map) {
        Long facilityRrn = LocalContext.getFacilityRrn();

        List<AutoMonitorItemStep> operationList = new ArrayList<>();

        String stepList = MapUtils.getString(map, "operationList");
        List<Map> array = JsonUtils.toList(stepList, Map.class);
        for (int i = 0; i < array.size(); i++) {
            Map step = array.get(i);
            AutoMonitorItemStep monitorItemStep = new AutoMonitorItemStep();
            monitorItemStep.setStepSequence(new Long(i + 1));

            String eqptId = StringUtils.trimToUpperCase(MapUtils.getString(step, "equipmentId"));
            if (StringUtils.isNotBlank(eqptId)) {
                Equipment equipment = emsService.getEquipment(eqptId, facilityRrn);
                Assert.state(Objects.nonNull(equipment), Errors.create().key(MessageIdList.EQUIPMENT_ID_NOT_EXIST)
                                                               .content("Equipment does not exist!").build());
                Assert.state(Objects.isNull(equipment.getParentEntityRrn()) ||
                                     equipment.getParentEntityRrn().longValue() == 0,
                             Errors.create().content("Equipment is chamber Eqp").build());


                monitorItemStep.setEquipmentId(eqptId);
                monitorItemStep.setEquipmentRrn(equipment.getInstanceRrn());
            }

            String eqptGroupId = StringUtils.trimToUpperCase(MapUtils.getString(step, "equipmentGroupId"));
            if (StringUtils.isNotBlank(eqptGroupId)) {
                long eqptGroupRrn = getInstanceRrn(eqptGroupId, facilityRrn, ObjectList.ENTITYGROUP_KEY);
                Assert.state(eqptGroupRrn > 0,
                             Errors.create().key(MessageIdList.ENTITYGROUP_INVALID_ID).content("Invalid EQP group id!")
                                   .build());
                monitorItemStep.setEquipmentGroupId(eqptGroupId);
                monitorItemStep.setEquipmentGroupRrn(eqptGroupRrn);
            }

            monitorItemStep.setEqptType(StringUtils.trimToUpperCase(MapUtils.getString(step, "eqptType")));
            monitorItemStep.setFlowSeq(StringUtils.trimToUpperCase(MapUtils.getString(step, "flowSeq")));
            monitorItemStep.setOperationDesc(StringUtils.trim(MapUtils.getString(step, "operationDesc")));

            String recipeId = StringUtils.trimToUpperCase(MapUtils.getString(step, "recipeId"));
            if (StringUtils.isNotBlank(recipeId)) {
                long recipeRrn = getInstanceRrn(recipeId, facilityRrn, ObjectList.RECIPE_KEY);
                Assert.state(recipeRrn > 0,
                             Errors.create().key(MessageIdList.RECIPE_NOT_EXISTS).content("RECIPE:{} not exists!")
                                   .args(recipeId).build());
                monitorItemStep.setRecipeId(recipeId);
            }

            String slotType = StringUtils.trimToUpperCase(MapUtils.getString(step, "nonRTSlotType"));
            if (!AutoMonitorUtils.checkStepIsEdcStep(monitorItemStep.getEqptType())) {
                slotType = AutoMonitorOperationConstants.STEP_SLOT_TYPE_PROCESS;
            }

            if (StringUtils.equals(AutoMonitorOperationConstants.STEP_SLOT_TYPE_LOT, slotType)) {
                monitorItemStep.setNonRTJobIds(MapUtils.getString(step, "nonRTJobIds"));
                monitorItemStep.setNonRTJobNames(MapUtils.getString(step, "nonRTJobNames"));
            } else if (StringUtils.equals(AutoMonitorOperationConstants.STEP_SLOT_TYPE_WAFER, slotType)) {
                List jobIds = (List) MapUtils.getObject(step, "nonRTJobIds");
                List jobNames = (List) MapUtils.getObject(step, "nonRTJobNames");

                List<String> waferNonRTJobIds = new ArrayList<>();
                List<String> waferNonRTJobNames = new ArrayList<>();
                for (int j = 0; j < jobIds.size(); j++) {
                    waferNonRTJobIds.add((String) jobIds.get(j));
                    waferNonRTJobNames.add((String) jobNames.get(j));
                }
                monitorItemStep.setWaferNonRTJobIds(waferNonRTJobIds);
                monitorItemStep.setWaferNonRTJobNames(waferNonRTJobNames);
            }

            monitorItemStep.setNonRTSlotType(slotType);
            monitorItemStep.setStageId(StringUtils.trimToUpperCase(MapUtils.getString(step, "stageId")));

            String reticleId = StringUtils.trimToUpperCase(MapUtils.getString(step, "reticleId"));
            if (StringUtils.isNotBlank(reticleId)) {
                Reticle reticle = reticleService.getReticleInfo(reticleId, LocalContext.getFacilityRrn());

                long reticleRrn = getInstanceRrn(reticleId, facilityRrn, ObjectList.ENTITY_KEY);
                Assert.state(reticleRrn > 0,
                             Errors.create().key(MessageIdList.RETICLE_ID_NOEXIST).content("Reticle Id does not exist!")
                                   .build());
                monitorItemStep.setReticleId(reticleId);
                monitorItemStep.setReticleRrn(reticleRrn);
            }

            String reticleGroupId = StringUtils.trimToUpperCase(MapUtils.getString(step, "reticleGroupId"));
            if (StringUtils.isNotBlank(reticleGroupId)) {
                long reticleGroupRrn = getInstanceRrn(reticleGroupId, facilityRrn, ObjectList.RETICLEFAMILY_KEY);
                Assert.state(reticleGroupRrn > 0, Errors.create().key(MessageIdList.RETICLE_GROUP_NOT_EXISTS)
                                                        .content("Reticle Grp.:{} not exists!").args(reticleGroupId)
                                                        .build());
                monitorItemStep.setReticleGroupId(reticleGroupId);
                monitorItemStep.setReticleGroupRrn(reticleGroupRrn);
            }

            operationList.add(monitorItemStep);
        }

        return operationList;
    }

    private String validateMonitorItemForActive(AutoMonitorItemDTO itemDTO) {
        StringBuilder errorMsg = new StringBuilder();

        // 1. item info
        AutoMonitorItem autoMonitorItem = itemDTO.getAutoMonitorItem();

        Long qty = autoMonitorItem.getQty();
        Assert.state(Objects.nonNull(qty) && qty.longValue() > 0 && qty.longValue() <= 25,
                     Errors.create().key(MessageIdList.AUTOMONITOR_WAFER_QTY_ERROR).build());

        Long productRrn = autoMonitorItem.getProductRrn();
        Assert.state(Objects.nonNull(productRrn) && productRrn.longValue() > 0,
                     Errors.create().key(MessageIdList.PRODUCT_PRODUCT_MISSING).build());

        Long processRrn = autoMonitorItem.getProcessRrn();
        Assert.state(Objects.nonNull(processRrn) && processRrn.longValue() > 0,
                     Errors.create().key(MessageIdList.PROCESS_INVALID).build());

        Equipment equipment = emsService.getEquipment(autoMonitorItem.getEqptRrn());
        Assert.state(Objects.nonNull(equipment) && equipment.getInstanceRrn() > 0,
                     Errors.create().key(MessageIdList.EQUIPMENT_INVALID_ID).build());

        // 2. step info
        List<AutoMonitorItemStep> stepList = itemDTO.getStepList();

        List<Map> nonRTList = edcChartService.getMainEqpNonRTJobList(autoMonitorItem.getEqptRrn());
        List<String> flowSeqList = new ArrayList<>();
        List<String> processStepList = new ArrayList<>();
        for (AutoMonitorItemStep step : stepList) {
            // flow seq 是否重复
            StringBuilder stepMsg = new StringBuilder();
            if (StringUtils.isBlank(step.getFlowSeq())) {
                stepMsg.append(I18nUtils.getMessage(MessageIdList.SPEC_MISSING_FLOWSEQ));
            } else {
                if (flowSeqList.contains(step.getFlowSeq())) {
                    stepMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_FLOWSEQ_REPEAT));
                } else {
                    flowSeqList.add(step.getFlowSeq());
                }
            }

            // recipe 必填
            String recipeId = step.getRecipeId();
            if (StringUtils.isBlank(recipeId)) {
                stepMsg.append(I18nUtils.getMessage(MessageIdList.RECIPE_INVALID_ID));
            } else {
                Recipe recipe = recipeService.getRecipe(recipeId, LocalContext.getFacilityRrn());
                if (Objects.isNull(recipe) || recipe.getInstanceRrn() <= 0) {
                    stepMsg.append(I18nUtils.getMessage(MessageIdList.RECIPE_NOT_EXISTS,new Object[]{recipeId}));
                }
            }

            if (StringUtils.isBlank(step.getOperationDesc())) {
                stepMsg.append(I18nUtils.getMessage(MessageIdList.SPEC_MISSING_OPERATION_DESC));
            }

            String eqptType = step.getEqptType();
            String[] types = StringUtils.split(eqptType, AutoMonitorOperationConstants.STEP_TYPE_SEPARATOR);
            if (AutoMonitorUtils.checkStepIsPreEdcStep(eqptType)) {
                String processType = types.length > 1 ? types[1] : MAIN_EDC_SIGN;
                if (processStepList.contains(processType)) {
                    stepMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_PRE_AFTER_PROCESS));
                }
                if (NumberUtils.isDigits(processType) && processStepList.contains(MAIN_EDC_SIGN)) {
                    stepMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_PRE_AFTER_PROCESS));
                }

                stepMsg.append(checkStepNonRtSetup(step,equipment, stepList, nonRTList));
            } else if (AutoMonitorUtils.checkStepIsPostEdcStep(eqptType)) {
                String processType = types.length > 1 ? types[1] : MAIN_EDC_SIGN;
                if (!processStepList.contains(processType) &&
                        (!(NumberUtils.isDigits(processType) && processStepList.contains(MAIN_EDC_SIGN)))) {
                    stepMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_POST_BEFORE_PROCESS));
                }

                stepMsg.append(checkStepNonRtSetup(step,equipment,  stepList, nonRTList));
            } else if(StringUtils.equals(AutoMonitorOperationConstants.STEP_TYPE_MAIN, eqptType)){
                if (processStepList.contains(MAIN_EDC_SIGN)) {
                    stepMsg.append("Main 站点重复");
                }
                processStepList.add(MAIN_EDC_SIGN);
                if (!StringUtils.equals(autoMonitorItem.getEqptId(), step.getEquipmentId())) {
                    stepMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_MAIN_DIFFRENT_ITEM));
                }
            } else if (AutoMonitorUtils.checkStepIsProcessStep(eqptType)) {
                if (processStepList.contains(eqptType)) {
                    stepMsg.append("Process 站点重复");
                } else {
                    processStepList.add(eqptType);
                }
            } else {
                stepMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_EQPT_TYPE_NULL));
            }

            if (StringUtils.isNotBlank(stepMsg)) {
                Long stepSeq = step.getStepSequence();
                errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_STEP_SEQ, new Object[]{stepSeq}));
                errorMsg.append(stepMsg);
                errorMsg.append(SystemConstant.Str.BR);
            }
        }

        if (!processStepList.contains(MAIN_EDC_SIGN)) {
            errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_NOT_HAVE_MAIN));
        }

        return errorMsg.toString();
    }

    private String checkStepNonRtSetup(AutoMonitorItemStep step, Equipment mainEquipment,
                                       List<AutoMonitorItemStep> allStepList, List<Map> nonRtJobList) {
        StringBuilder errorMsg = new StringBuilder();

        String[] types = StringUtils.split(step.getEqptType(), AutoMonitorOperationConstants.STEP_TYPE_SEPARATOR);
        String processEqptType = types.length > 1 ? types[1] : MAIN_EDC_SIGN;
        if (StringUtils.equals(processEqptType, MAIN_EDC_SIGN)) {
            processEqptType = AutoMonitorOperationConstants.STEP_TYPE_MAIN;
        }
        String groupEqptType = buildGroupEqptType(step.getEqptType());

        List<String> stepEdcInfoList = new ArrayList<>();
        if (StringUtils.equals(AutoMonitorOperationConstants.STEP_SLOT_TYPE_WAFER, step.getNonRTSlotType())) {
            if (CollectionUtils.isEmpty(step.getWaferNonRTJobNames())) {
                errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_NONRT_JOB_NULL));
            } else {
                stepEdcInfoList = step.getWaferNonRTJobNames();
            }
        } else {
            if (StringUtils.isBlank(step.getNonRTJobNames())) {
                errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_NONRT_JOB_NULL));
            } else {
                stepEdcInfoList.add(step.getNonRTJobNames());
            }
        }

        Boolean stepNeedGroupStep = Boolean.FALSE;
        Boolean hadGroupStep = Boolean.FALSE;
        List<String> edcProcessEqptIdList = new ArrayList<>();
        for (String stepEdcInfo : stepEdcInfoList) {
            String[] nonRtJobNames = StringUtils.split(stepEdcInfo, StringUtils.COMMA_SIGN);
            for (String nonRtJobName : nonRtJobNames) {
                Map nonRtJobInfo = selectNonRtJobInfo(nonRtJobList, nonRtJobName);
                if (NonRTMathUtil.isNeedPreValue(MapUtils.getString(nonRtJobInfo, "Formula"))) {
                    stepNeedGroupStep = Boolean.TRUE;
                }
                if (!edcProcessEqptIdList.contains(MapUtils.getString(nonRtJobInfo, "eqptId"))) {
                    edcProcessEqptIdList.add(MapUtils.getString(nonRtJobInfo, "eqptId"));
                }
            }
        }

        if (edcProcessEqptIdList.size() > 1) {
            errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_EDC_NOT_SAME_CHAMBER));
        }

        for (AutoMonitorItemStep checkStep : allStepList) {
            if (StringUtils.equals(step.getFlowSeq(), checkStep.getFlowSeq())) {
                continue;
            }

            if (StringUtils.equals(checkStep.getEqptType(), AutoMonitorOperationConstants.STEP_TYPE_MAIN)) {
                if (BooleanUtils.toBoolean(mainEquipment.getIsChamberEquip())) {
                    String recipeId = checkStep.getRecipeId();
                    String chamberType = StringUtils.substringAfterLast(recipeId, RECIPE_CHAMBER_ID_SEPARATOR);

                    if (StringUtils.isBlank(chamberType)) {
                        errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_NEED_CHAMBER_RECIPE));
                        continue;
                    }

                    if (chamberType.length() > 1) {
                        errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_ONLY_ONE_CHAMBER));
                    }

                    String chamberEqptId = mainEquipment.getInstanceId() + CHAMBER_FLAG + chamberType;
                    if (!edcProcessEqptIdList.contains(chamberEqptId)) {
                        errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_CHAMBER_NOT_SAME_EDC,
                                                             new Object[]{chamberType}));
                    }
                }
            }

            if (stepNeedGroupStep && StringUtils.equals(checkStep.getEqptType(), groupEqptType)) {
                Boolean isGroupStep = Boolean.TRUE;

                List<String> checkEdcInfoList = new ArrayList<>();
                if (StringUtils.equals(AutoMonitorOperationConstants.STEP_SLOT_TYPE_WAFER, step.getNonRTSlotType())) {
                    checkEdcInfoList = step.getWaferNonRTJobNames();
                } else {
                    checkEdcInfoList.add(step.getNonRTJobNames());
                }

                if (stepEdcInfoList.size() != checkEdcInfoList.size()) {
                    errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_SPC_JOB_NOT_SAME));
                    continue;
                }

                for (int i = 0; i < stepEdcInfoList.size(); i++) {
                    List<String> edcJobName = StringUtils.splitAsList(stepEdcInfoList.get(i), StringUtils.COMMA_SIGN);
                    List<String> checkJobName = StringUtils
                            .splitAsList(checkEdcInfoList.get(i), StringUtils.COMMA_SIGN);
                    for (String nonRtJobName : edcJobName) {
                        Map nonRtJobInfo = selectNonRtJobInfo(nonRtJobList, nonRtJobName);
                        if (NonRTMathUtil.isNeedPreValue(MapUtils.getString(nonRtJobInfo, "Formula")) &&
                                !checkJobName.contains(nonRtJobName)) {
                            isGroupStep = Boolean.FALSE;
                        }
                    }
                }

                if (isGroupStep) {
                    hadGroupStep = Boolean.TRUE;
                }
            }
        }

        if (stepNeedGroupStep && !hadGroupStep) {
            errorMsg.append(I18nUtils.getMessage(MessageIdList.AUTOMONITOR_SPC_JOB_NOT_SAME));
        }

        return errorMsg.toString();
    }

    private Map selectNonRtJobInfo(List<Map> nonRtJobList, String nonRtJobName) {
        for (Map nonRtJobInfo : nonRtJobList) {
            if (StringUtils.equals(MapUtils.getString(nonRtJobInfo, "JobName"), nonRtJobName)) {
                return nonRtJobInfo;
            }
        }
        return null;
    }

    private String buildGroupEqptType(String eqptType) {
        String[] types = StringUtils.split(eqptType, AutoMonitorOperationConstants.STEP_TYPE_SEPARATOR);
        if (types.length > 1) {
            if (AutoMonitorUtils.checkStepIsPreEdcStep(eqptType)) {
                return AutoMonitorOperationConstants.STEP_TYPE_POST +
                        AutoMonitorOperationConstants.STEP_TYPE_SEPARATOR + types[1];
            }

            if (AutoMonitorUtils.checkStepIsPostEdcStep(eqptType)) {
                return AutoMonitorOperationConstants.STEP_TYPE_PRE + AutoMonitorOperationConstants.STEP_TYPE_SEPARATOR +
                        types[1];
            }
        }
        return StringUtils.EMPTY;
    }

    private String buildWaferNonRtNeedCheck(List<Map> nonRTList, AutoMonitorItemStep step) {
        Map<String, List<String>> map = MapUtils.newHashMap();
        for (int i = 0; i < step.getWaferNonRTJobNames().size(); i++) {
            String nonRTJobNames = step.getWaferNonRTJobNames().get(i);
            map.put(i + "", buildNeedCheckNonRTJobList(nonRTJobNames, nonRTList));
        }
        return map.toString();
    }

    private List<String> buildNeedCheckNonRTJobList(String nonRtJobNames, List<Map> nonRTList) {
        List<String> needCheckNonRTJobList = new ArrayList<>();

        if (StringUtils.isNotBlank(nonRtJobNames)) {
            String[] nonRtJobNameList = StringUtils.split(nonRtJobNames, StringUtils.COMMA_SIGN);
            for (String nonRtJobName : nonRtJobNameList) {
                for (Map nonRTJob : nonRTList) {
                    if (StringUtils.equals(MapUtils.getString(nonRTJob, "JobName"), nonRtJobName) &&
                            NonRTMathUtil.isNeedPreValue(MapUtils.getString(nonRTJob, "Formula"))) {
                        needCheckNonRTJobList.add(nonRtJobName);
                    }
                }
            }
        }
        return needCheckNonRTJobList;
    }

    private boolean checkNonRtJobInMainEqpt(String nonRtJobNames, List<Map> nonRTList) {
        boolean isEqpNonRTJob = false;
        if (StringUtils.isNotBlank(nonRtJobNames)) {
            String[] nonRtJobNameList = StringUtils.split(nonRtJobNames, StringUtils.COMMA_SIGN);
            for (String nonRtJobName : nonRtJobNameList) {
                for (Map nonRTJob : nonRTList) {
                    if (StringUtils.equals(MapUtils.getString(nonRTJob, "JobName"), nonRtJobName)) {
                        isEqpNonRTJob = true;
                    }
                }
            }
        }
        return isEqpNonRTJob;
    }

}