MoveInAction.java

package com.mycim.webapp.actions.operation.run;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.cache.utils.CacheUtils;
import com.mycim.framework.utils.beans.PropertyUtils;
import com.mycim.framework.utils.lang.ArrayUtils;
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.lang.time.DateUtils;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.NamedObject;
import com.mycim.valueobject.consts.JobStatus;
import com.mycim.valueobject.consts.LinkTypeList;
import com.mycim.valueobject.consts.ObjectStatus;
import com.mycim.valueobject.consts.SessionNames;
import com.mycim.valueobject.ems.Entity;
import com.mycim.valueobject.prp.Operation;
import com.mycim.valueobject.prp.RecipeCondition;
import com.mycim.valueobject.prp.RecipeVersion;
import com.mycim.valueobject.security.User;
import com.mycim.valueobject.wip.Job;
import com.mycim.valueobject.wip.Lot;
import com.mycim.valueobject.wip.LotStatus;
import com.mycim.webapp.Constants;
import com.mycim.webapp.WebUtils;
import com.mycim.webapp.actions.WipSetupAction;
import com.mycim.webapp.forms.JobInfoForm;
import com.mycim.webapp.forms.RootForm;
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.*;
import java.util.stream.Collectors;

/**
 * @author Johnson.Wang
 * @version 6.0.0
 * @date 2019/10/3
 **/
public class MoveInAction extends WipSetupAction {

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

        Map parameters = (Map) request.getAttribute(SessionNames.PARAMETERSINFO_KEY);
        if (parameters == null) {
            parameters = (HashMap) WebUtils.getCacheString2Obj(theform.getCacheParametersInfo());
            request.setAttribute(SessionNames.PARAMETERSINFO_KEY, parameters);
        }

        Job job = (Job) request.getAttribute("job");
        if (job == null) {
            job = (Job) WebUtils.getCacheString2Obj(theform.getCacheJob());
            request.setAttribute("job", job);
        }

        List lots = (List) request.getAttribute(SessionNames.COLLECTION_KEY);
        if (lots == null) {
            lots = (List) WebUtils.getCacheString2Obj(theform.getCacheCollection());
            request.setAttribute(SessionNames.COLLECTION_KEY, lots);
            request.setAttribute("currentlots", lots);
        }

        Map lotMap = (Map) lots.iterator().next();
        Operation operation = new Operation();
        operation.setInstanceRrn(MapUtils.getLongValue(lotMap, "operationRrn"));
        operation = getOperation(operation);
        if (operation.isBondedOperation()) {
            wipService.validAndBuildBondingAfterLock(lots, parameters);
            //bond的普通job in时check lot materialId是否相同,若不同则给出提示
            String forceBondJobInFlag = request.getParameter("forceBondJobInFlag");
            if (StringUtils.equals("1", forceBondJobInFlag)) {
              wipService.checkBondLotMaterial(lots);
            }
        } else if (operation.isDeBondOperation()) {
            Assert.isFalse(lots.size() > 1, Errors.create().content("Only one lot is allowed in this step !").build());
        }

        Assert.isFalse(parameters == null || job == null || lots == null,
                       Errors.create().content("Parameters are not enough!").build());

        String comments = request.getParameter("comments");


        if (request.getParameter(Constants.OK_KEY) != null || parameters.get(Constants.OK_KEY) != null) {
            return movein(job, lots, parameters, request, response, mapping);
        }

        // when come from jobservice
        JobInfoForm jobInfoForm = new JobInfoForm();
        PropertyUtils.copyProperties(jobInfoForm, job);
        long totalWaferQty = 0L;
        for (Object lot : lots) {
            Map lotInfo = (Map) lot;
            long qty = MapUtils.getDouble(lotInfo, "qty1").longValue();
            totalWaferQty += qty;
        }
        // set recipe
        for (Object lot : lots) {
            Map lotInfo = (Map) lot;
            if (StringUtils.isBlank(MapUtils.getString(lotInfo, "recipePhysicalId")) &&
                    StringUtils.isNotBlank(MapUtils.getString(lotInfo, "recipeId"))) {
                lotInfo.put("eqptID", MapUtils.getString(lotInfo, "equipmentId"));
                String id = recipeService.buildRecipePhysicalId(MapUtils.getString(lotInfo, "recipeId"), lotInfo);
                lotInfo.put("recipePhysicalId", id);
            }
            setChildRecipe(request, lotInfo, totalWaferQty);
            replaceChildRecipeId(lotInfo);
            selectRecipeId(request, lotInfo);
        }
        buildLotinfo(job, lots);
        int i = 0;
        for (Object lot : lots) {
            HashMap item = (HashMap) lot;
            request.setAttribute("reticleString" + i, item.get("reticleString" + i));
            i++;
        }
        request.setAttribute("jobInfoForm", jobInfoForm);

        setCache4WFL(request, jobInfoForm);
        String automovein = WebUtils.getParameter("automovein", request);
        if (StringUtils.isNotBlank(automovein)) {
            request.setAttribute("automovein", automovein);
        }
        return mapping.findForward("movein");
    }

    @Override
    public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                                HttpServletResponse response) throws Exception {
        String lotId = WebUtils.getParameter("lotIdShow", request);
        request.getRequestDispatcher(mapping.findForward("jobmanagement4lot").getPath() + "&lotId=" + lotId)
               .forward(request, response);
        return null;
    }

    public ActionForward ok(ActionMapping mapping, ActionForm form, HttpServletRequest request,
                            HttpServletResponse response) throws Exception {
        RootForm theform = (RootForm) form;

        Map parameters = (Map) request.getAttribute(SessionNames.PARAMETERSINFO_KEY);
        if (parameters == null) {
            parameters = (HashMap) WebUtils.getCacheString2Obj(theform.getCacheParametersInfo());
            request.setAttribute(SessionNames.PARAMETERSINFO_KEY, parameters);
        }

        Job job = (Job) request.getAttribute("job");
        if (job == null) {
            job = (Job) WebUtils.getCacheString2Obj(theform.getCacheJob());
            request.setAttribute("job", job);
        }

        List lots = (List) request.getAttribute(SessionNames.COLLECTION_KEY);
        if (lots == null) {
            lots = (List) WebUtils.getCacheString2Obj(theform.getCacheCollection());
            request.setAttribute(SessionNames.COLLECTION_KEY, lots);
            request.setAttribute("currentlots", lots);
        }
        // 1.525如果设置了资源清单列表;进行物料库存校验 且检验是否过期
        lotService.checkLotMaterial(lots);
        Map lotMap = (Map) lots.iterator().next();
        Operation operation = prpService.getOperation(MapUtils.getLongValue(lotMap, "operationRrn"));
        if (operation.isBondedOperation()) {
            wipService.validAndBuildBondingAfterLock(lots, parameters);
        } else if (operation.isDeBondOperation()) {
            Assert.isFalse(lots.size() > 1, Errors.create().content("Only one lot is allowed in this step !").build());
        }

        Assert.isFalse(parameters == null || job == null || lots == null,
                       Errors.create().content("Parameters are not enough!").build());

        String comments = request.getParameter("comments");

        return movein(job, lots, parameters, request, response, mapping);
    }

    public ActionForward movein(Job job, List<Map> lots, Map parameters, HttpServletRequest request,
                                HttpServletResponse response, ActionMapping mapping) throws Exception {
        Lot item = null;
        String eqptRrn = "";
        // List<Lot> lockLots = new ArrayList<>();
        String comments = request.getParameter("comments");

        Job my_job = wipQueryService.getJob(job.getJobRrn());

        Assert.isFalse(my_job == null,
                       Errors.create().key(MessageIdList.JOB_MISSING).content("job不存在!请关闭当前tab页面重新创建!").build());

        Assert.isFalse(StringUtils.equalsIgnoreCase(JobStatus.RUNNING, my_job.getJobStatus()),
                       Errors.create().key(MessageIdList.JOB_STATUS_IS_RUNNING).content("job status is running")
                             .build());

        validateTask(parameters, "movein");

        // check if it is valid for movein transaction
        // 1.check if lots are held in future action
        // 2.check if product,process,operation,eauipment is held

        NamedObject object = new NamedObject();
        object.setInstanceRrn(job.getOperationRrn());
        object = baseService.getNamedObject(object);
        Assert.isFalse(object.getInstanceStatus() != null && object.getInstanceStatus().equals(ObjectStatus.HOLD_KEY),
                       Errors.create().key(MessageIdList.STEP_IS_HOLD).content("Step is held now,MoveIn is forbidden!")
                             .build());

        object.setInstanceRrn(job.getEqptRrn());
        object = baseService.getNamedObject(object);
        Assert.isFalse(object.getInstanceStatus() != null && object.getInstanceStatus().equals(ObjectStatus.HOLD_KEY),
                       Errors.create().key(MessageIdList.EQUIPMENT_IS_HOLD)
                             .content("Equipment is held now,MoveIn is forbidden!").build());

        String isReticleRequired = null;

        for (Iterator it = lots.iterator(); it.hasNext(); ) {
            HashMap lotMap = (HashMap) it.next();
            isReticleRequired = (String) lotMap.get("isReticleRequired");
            object.setInstanceRrn(this.getInstanceRrn((String) lotMap.get("recipeId"),
                                                      getNamedSpace(ObjectList.RECIPE_KEY,
                                                                    LocalContext.getFacilityRrn()),
                                                      ObjectList.RECIPE_KEY));
            if (object.getInstanceRrn() > 0) {
                object = baseService.getNamedObject(object);
                Assert.isFalse(
                        object.getInstanceStatus() != null && object.getInstanceStatus().equals(ObjectStatus.HOLD_KEY),
                        Errors.create().key(MessageIdList.RECIPE_IS_HOLD)
                              .content("Recipe in lot ({}) is held now,MoveIn is forbidden!").args(lotMap.get("lotId"))
                              .build());
            }
        }

        // 判定carrier是否有禁止进站的PM计划
        for (Iterator it = lots.iterator(); it.hasNext(); ) {
            HashMap lotMap = (HashMap) it.next();
            Long carrierRrn = MapUtils.getLong(lotMap, "carrierRrn");
            boolean boo = carrierService.isThisCarrierPmNotMoveIn(carrierRrn);
            Assert.isFalse(boo, Errors.create().key(MessageIdList.CARRIER_HAS_UNTREATED_PM).content(
                    "The Carrier has an untreated PM plan and can't get into the " + "station")
                                      .args(lotMap.get("lotId")).build());
        }

        List<Lot> lots4job = lotInqService.getLotListByJobRrn(job.getJobRrn());
        Long productRrn = null;
        Long processRrn = null;

        for (Iterator it = lots4job.iterator(); it.hasNext(); ) {
            item = (Lot) it.next();
            productRrn = item.getProductRrn();
            processRrn = item.getProcessRrn();


            Assert.isFalse(item.getLotStatus() != null && item.getLotStatus().equals(LotStatus.HOLD),
                           Errors.create().key(MessageIdList.CARRIER_HAS_UNTREATED_PM)
                                 .content("Lot({}) is held" + " now," + "Please " + "release" + " it " + "first!")
                                 .args(item.getLotId()).build());

            if (StringUtils.isBlank(item.getRecipePhysicalId())) {
                buildRecipeId(item);
            }

            String checkResult = wipCheckService
                    .checkAvailableEquipment(item, job.getEqptRrn(), LocalContext.getUserRrn());

            Assert.isFalse(StringUtils.isNotBlank(checkResult), Errors.create().content(checkResult).build());

            checkResult = wipCheckService
                    .checkHasAvailableDispatchRecipe(item, job.getEqptRrn(), item.getRecipePhysicalId(),
                                                     item.getQty1());
            Assert.isFalse(StringUtils.isNotBlank(checkResult), Errors.create().content(checkResult).build());
            // lockLots.add(item);
        }


        object.setInstanceRrn(productRrn);
        object = baseService.getNamedObject(object);
        Assert.isFalse(object.getInstanceStatus() != null && object.getInstanceStatus().equals(ObjectStatus.HOLD_KEY),
                       Errors.create().key(MessageIdList.PRODUCT_IS_HOLD)
                             .content("Product is held now,MoveIn is forbidden!").build());

        object.setInstanceRrn(processRrn);
        object = baseService.getNamedObject(object);
        Assert.isFalse(object.getInstanceStatus() != null && object.getInstanceStatus().equals(ObjectStatus.HOLD_KEY),
                       Errors.create().key(MessageIdList.PROCESS_IS_HOLD)
                             .content("Process is held now,MoveIn is forbidden!").build());

        Operation o = prpService.getOperation(job.getOperationRrn());

        for (Iterator it = lots4job.iterator(); it.hasNext(); ) {
            item = (Lot) it.next();
            eqptRrn = Long.toString(item.getEqptRrn());

            boolean triggered = false;
            String alarmId = null;
            String subject = "";
            String content = "";
            Job newJob = new Job();
            long jobRrn = job.getJobRrn();
            newJob = wipQueryService.getJob(jobRrn);
            long runRrn = newJob.getRunRrn();

            long spent = DateUtils.getDistanceTime4Now(item.getQueueTimestamp());

            if ((spent < DateUtils.getSecondsTime(o.getMinQueueTime())) &&
                    (DateUtils.getSecondsTime(o.getMinQueueTime()) > 0)) {

                alarmId = o.getExceedMinQTimeAlarmId();

                subject = "Lot " + item.getLotId() + " not exceed the min Q-Time in this step,Please waiting " +
                        item.getOperationId();
                content = subject;

                if (alarmId != null) {
                    triggered = true;

                    // todo alarm
                    //                    triggerProcessAlarm(item.getProductRrn().longValue(), alarmId,
                    //                    userRrn, subject, content,
                    //                                        jobRrn, runRrn);
                }

                throw new SystemIllegalArgumentException(Errors.create().content(content).build());
            }

        }

        request.removeAttribute("reticleRrns");
        parameters.put("comments", request.getParameter("comments"));
        String[] reticleRrns = request.getParameterValues("showReticleRrn");
        reticleRrns = ArrayUtils.isNotEmpty(reticleRrns) ? reticleRrns : (String[]) parameters.get("showReticleRrn");

        if (reticleRrns != null && "1".equals(isReticleRequired)) {
            String _reticleRrn = null;
            for (int j = 0; j < lots.size(); j++) {
                _reticleRrn = reticleRrns[j];

                Assert.isFalse(_reticleRrn == null || _reticleRrn.equals(""),
                               Errors.create().key(MessageIdList.RETICLE_REQUIRED).content("Reticle is required!")
                                     .build());

                Entity entity = new Entity(NumberUtils.toLong(_reticleRrn));
                wipCheckService.doValidateReticlePermissions(LocalContext.getUserRrn(), entity.getInstanceRrn());

            }
            request.setAttribute("reticleRrns", reticleRrns);
        }

        String reticleRrn = request.getParameter("reticleRrn");
        reticleRrn = StringUtils.isNotEmptyTrim(reticleRrn) ? reticleRrn : (String) parameters.get("reticleRrn");
        parameters.put("reticleRrn", reticleRrn);

        String[] loadPosition = request.getParameterValues("loadPosition");
        loadPosition = ArrayUtils.isNotEmpty(loadPosition) ? loadPosition : (String[]) parameters.get("loadPosition");

        int n = 0;
        String _loadPosition = null;

        if (loadPosition != null) {
            for (Iterator it = lots.iterator(); it.hasNext(); ) {
                HashMap _lot = (HashMap) it.next();

                if (n == 0) {
                    _loadPosition = loadPosition[n];
                } else {
                    if (((String) _lot.get("isUniqueCarrierFlag")).equals("1")) {
                        _loadPosition = loadPosition[n];
                    } else {
                        loadPosition[n] = _loadPosition;
                    }
                }

                if ((loadPosition[n] == null) || loadPosition[n].equals("")) {
                    loadPosition[n] = new String("0");
                }

                n++;
            }
        }

        HashMap transInfo = new HashMap();
        transInfo.put("job", job);

        // job.get
        transInfo.put("facilityRrn", LocalContext.getFacilityRrn());
        transInfo.put("comments", comments);
        transInfo.put("loadPosition", loadPosition);
        transInfo.put("reticleRrns", reticleRrns);
        transInfo.put("transPerformedby", LocalContext.getUserId());


        Iterator lotCollection = lots.iterator();

        while (lotCollection.hasNext()) {
            HashMap lot = (HashMap) lotCollection.next();
            eqptRrn = Long.toString((long) lot.get("equipmentRrn"));
            String lotid = (String) lot.get("lotId");
            String operationid = job.getOperationId();

            String temp = (String) lot.get("routeRrn");

            String routeid = "";

            // log.debug("Route id"+temp);
            if (temp != null) {
                int i = 0;
                int j = 0;
                i = temp.indexOf("|");

                // find first '|'
                if (i != -1) {
                    j = temp.indexOf("|", i + 1);

                    // find se '|'
                    // string is aaa|bbb|cccc
                    if (j > 0) {
                        routeid = temp.substring(i + 1, j);
                    } else if (i > 0) { // aaa|bbb
                        routeid = temp.substring(0, i);
                    }
                }
            }

            String qty = (String) lot.get("qty1");

            // *************
            // add by ben from nonStdMoveout(move lot from a operation
            // to b operation)
            transInfo.put("lotid", lotid + "");

            transInfo.put("qty", qty + "");

            transInfo.put("tooperation", operationid + "");
            transInfo.put("toroute", routeid + "");
        }
        String recipeId = request.getParameter("recipeId");
        recipeId = StringUtils.isNotEmptyTrim(recipeId) ? recipeId : (String) parameters.get("recipeId");
        transInfo.put("selectRecipe",
                      getInstanceRrn(recipeId, LocalContext.getFacilityRrn(), ObjectList.RECIPE_KEY) + "");
        String[] recipeIds = request.getParameterValues("recipeId");
        recipeIds = ArrayUtils.isNotEmpty(recipeIds) ? recipeIds : (String[]) parameters.get("recipeIds");
        String chamberJoin = request.getParameter("chamberJoin");
        chamberJoin = StringUtils.isNotEmptyTrim(chamberJoin) ? chamberJoin : (String) parameters.get("chamberJoin");
        String[] lotIdShow = request.getParameterValues("lotIdShow");
        lotIdShow = ArrayUtils.isNotEmpty(lotIdShow) ? lotIdShow : (String[]) parameters.get("lotIdShow");
        String eventId = (String) parameters.get("eventId");
        Map recipeIdMap = new HashMap();
        if (lotIdShow != null) {
            for (int i = 0; i < lotIdShow.length; i++) {

                StringBuffer chamberType = new StringBuffer();
                StringBuffer chamberEqptsId = new StringBuffer();
                if (StringUtils.isNotEmpty(chamberJoin)) {
                    String chambers[] = chamberJoin.split(",");
                    for (String chamberkey : chambers) {
                       /* List<String> values     = sysService.getRefFileKey("$CHAMBER_TYPE", chambervalue);
                        String       chamberkey = (String) values.iterator().next();*/
                        Entity entity = emsService.getChildChamberEquip(job.getEqptRrn(), chamberkey);
                        chamberType.append(chamberkey);
                        chamberEqptsId.append(entity.getInstanceId() + Job.CHAMBEREQPTSSEPARATOR);
                        Long eventRrn = getInstanceRrn(eventId, getNamedSpace(ObjectList.EVENT_KEY,
                                                                              LocalContext.getFacilityRrn()),
                                                       ObjectList.EVENT_KEY);
                        job.setChamberEqptsId(chamberEqptsId.toString());
                        wipService.insertChamberEqptsId(job.getJobRrn(), chamberEqptsId.toString());
                    }
                }

                recipeIdMap.put(lotIdShow[i], getLotRecipeInfo(lots, lotIdShow[i], recipeIds[i], chamberJoin,
                                                               chamberEqptsId.toString()));
            }

            transInfo.put("recipeIdMap", recipeIdMap);
        }

        User createUser = new User();
        createUser.setInstanceId(LocalContext.getUserId());
        createUser.setInstanceRrn(LocalContext.getUserRrn());
        transInfo.put("user", createUser);

        String[] chamberEqptsId = StringUtils.split(job.getChamberEqptsId(), Job.CHAMBEREQPTSSEPARATOR);
        String logEventCheckResult = wipCheckService
                .checkEqptEnableLogEventAtMoveIn(job.getJobRrn(), eventId, job.getEqptRrn(), chamberEqptsId);
        Assert.isFalse(StringUtils.isNotBlank(logEventCheckResult),
                       Errors.create().content(logEventCheckResult).build());
        long userRrn = LocalContext.getUserRrn();
        String userId = LocalContext.getUserId();

        String avaliableEqtRrn = request.getParameter("avaliableEqtRrn");
        avaliableEqtRrn = StringUtils.isNotEmptyTrim(avaliableEqtRrn) ? avaliableEqtRrn : (String) parameters.get("avaliableEqtRrn");
        if (StringUtils.isEmpty(avaliableEqtRrn)) {
            avaliableEqtRrn = "";
            // 派工界面直接进站request里面没有avaliableEqtRrn的值;需要再从数据库查找
            ArrayList availableEquipmentInfos = (ArrayList) buildAvailableEquipInfosForLot(item,
                                                                                           LocalContext.getUserRrn());
            for (Iterator it = availableEquipmentInfos.iterator(); it.hasNext(); ) {
                Map availableEquipmentInfo = (HashMap) it.next();
                String equipmentRrn = MapUtils.getString(availableEquipmentInfo, "equipmentRrn");
                if (!StringUtils.isEmpty(equipmentRrn)) {
                    avaliableEqtRrn += equipmentRrn + StringUtils.COMMA_SIGN;
                }
            }
        }

        // checkAndCreateLotsTransLock(userRrn, TransactionNames.LOCK_MOVEIN, lockLots,
        //                             "movein in MoveInAction by: " + userId);
        // try {
            //上面代码已经根据 job 去查询 lots 了 能保证非空问题
            //代码循环内部 判断太多 这里直接拿到查询后的 lots 取出 rrn
            //这里抓去 lots 上锁
        List<String> lotRrns =lots4job.stream().map(e->e.getLotRrn()).map(StringUtils::toString).collect(Collectors.toList());
        wipService.moveIn(job, loadPosition, reticleRrns, recipeIdMap, comments,lotRrns,transInfo);
            // removeLotLockWhenTransError(userRrn, lockLots, TransactionNames.LOCK_MOVEIN,
            //                             "movein fail, in MoveInAction by: " + userId);
        // } catch (Exception e) {
        //     // removeLotLockWhenTransError(userRrn, lockLots, TransactionNames.LOCK_MOVEIN,
        //     //                             "movein fail, in MoveInAction by: " + userId);
        //     throw new SystemIllegalArgumentException(Errors.create().content("movein fail!").build());
        // }
        buildBondingRelation(lots);
        request.setAttribute("wfldetail", "movein");

        // update the cache after move in
        String[] equipmentRrns = StringUtils.split(avaliableEqtRrn, ",");
        if (equipmentRrns != null) {
            updateCacheHelper(equipmentRrns, eqptRrn);
        }

        parameters.put("jobRrn", job.getJobRrn() + "");
        parameters.put(SessionNames.RUNSTEP_FLAG, "0");
        String automovein = WebUtils.getParameter("automovein", request);
        automovein = StringUtils.isNotEmptyTrim(automovein) ? automovein : (String) parameters.get("automovein");
        if (StringUtils.isNotBlank(automovein)) {
            request.setAttribute("automovein", automovein);
        }
        request.getRequestDispatcher(mapping.findForward("workflow").getPath()).forward(request, response);
        return null;
    }

    /**
     * 根据选择recipeId 带出可用腔
     *
     * @param request
     * @param lotInfo
     * @throws Exception
     */
    public void selectRecipeId(HttpServletRequest request, Map lotInfo) {
        String recipeId = WebUtils.getParameter("recipeId", request);
        if (StringUtils.isEmpty(recipeId)) {
            recipeId = MapUtils.getString(lotInfo, "selectedRecipeId");
            setEnableChamberList(request, lotInfo, recipeId);
        }
        if (StringUtils.isNotEmpty(recipeId)) {
            if (StringUtils.equals(WebUtils.getParameter("lotId", request), MapUtils.getString(lotInfo, "lotId"))) {

                setEnableChamberList(request, lotInfo, WebUtils.getParameter("recipeId", request));
            }
            List<Map> childRecipeList = (List) MapUtils.getObject(lotInfo, "childRecipes");
            for (Map map : childRecipeList) {
                String matchRecipeId = recipeService
                        .buildRecipePhysicalId(MapUtils.getString(map, "recipeId"), lotInfo);
                if (recipeId.equals(matchRecipeId)) {
                    map.put("selectRecipeId", matchRecipeId);
                }

            }

        }
    }

    public void checkRectileStatus(Entity transEntity) {
        Long facilityRrn = LocalContext.getFacilityRrn();
        Long userRrn = LocalContext.getUserRrn();

        String entityId = transEntity.getInstanceId();
        Entity entity = new Entity(entityId, getNamedSpace(ObjectList.ENTITY_KEY, facilityRrn), ObjectList.ENTITY_KEY);
        entity = emsService.getEntity(entity);
        wipCheckService.doValidateReticlePermissions(userRrn, entity.getInstanceRrn());
    }

    @Override
    public void setChildRecipe(HttpServletRequest request, Map lotInfo, Long totalWaferQty) {
        Long facilityRrn = LocalContext.getFacilityRrn();
        String recipeId = MapUtils.getString(lotInfo, "recipeId");
        Collection lots = (Collection) request.getAttribute(SessionNames.COLLECTION_KEY);


        Collection childRecipes = recipeService
                .getRelation4RecipeByWaferQty(getInstanceRrn(recipeId, facilityRrn, ObjectList.RECIPE_KEY),
                                              LinkTypeList.RECIPEFAMILY_TO_RECIPE, totalWaferQty);
        Collection recipeConditions = recipeService
                .getRecipeCondition(getInstanceRrn(recipeId, facilityRrn, ObjectList.RECIPE_KEY));
        if (childRecipes != null && childRecipes.size() > 0) {
            lotInfo.put("childRecipes", childRecipes);
            if (recipeConditions != null && recipeConditions.size() > 0) {
                RecipeCondition recipeCondition = (RecipeCondition) recipeConditions.iterator().next();
                Long lotRrn = MapUtils.getLong(lotInfo, "lotRrn");
                double parameterVal = wipQueryService.getParamValByCondition(lotRrn, recipeCondition.getOperationRrn(),
                                                                             recipeCondition.getProductRrn(),
                                                                             recipeCondition.getProcessRrn(),
                                                                             recipeCondition.getParameterRrn(),
                                                                             recipeCondition.getPuType());
                // check has child recipe
                if (!LotStatus.RUNNING.equals(MapUtils.getString(lotInfo, "lotStatus"))) {
                    for (Iterator it = childRecipes.iterator(); it.hasNext(); ) {
                        Map recipe = (Map) it.next();
                        if (parameterVal >= Double.parseDouble(MapUtils.getString(recipe, "paraMinVal")) &&
                                parameterVal < Double.parseDouble(MapUtils.getString(recipe, "paraMaxVal"))) {
                            lotInfo.put("CalculateRecipe", recipe.get("recipeId"));
                        }
                    }

                }
            }
        } else {
            // 没有子recipe则设置当前recipe可用chamber
            setEnableChamberList(request, lotInfo, recipeId);
        }
    }

    private void updateCacheHelper(String[] equipmentRrns, String eqptRrn) {

        for (int i = 0; i < equipmentRrns.length; i++) {
            String equipmentRrn = equipmentRrns[i];
            List cacheLotStatus = (List<String>) CacheUtils.get(equipmentRrn);

            if (cacheLotStatus != null) {
                for (int h = 0; h < cacheLotStatus.size(); h++) {
                    if (LotStatus.WAITING.equals(cacheLotStatus.get(h))) {
                        if (StringUtils.equalsIgnoreCase(equipmentRrn, eqptRrn)) {
                            // 将使用中的设备的批次的一个waiting状态改为running,宁外一个可用状态的waiting状态移除
                            cacheLotStatus.set(h, LotStatus.RUNNING);
                        } else {
                            cacheLotStatus.remove(h);
                        }
                        break;
                    }
                }

                CacheUtils.put(equipmentRrn + "", cacheLotStatus);
            }
        }
    }

    private Map getLotRecipeInfo(List<Map> lots, String lotId, String logicalRecipeId, String chamberType,
                                 String chamberEqptsId) {
        for (Object obj : lots) {
            Map lotInfo = (Map) obj;
            if (StringUtils.equals(lotId, MapUtils.getString(lotInfo, "lotId"))) {
                Long recipeGroupRrn = MapUtils.getLong(lotInfo, "recipeRrn");
                RecipeVersion recipeGroupVersion = recipeService.getNowActiveRecipeVersion(recipeGroupRrn);

                Long recipeLogicalRrn = null;
                RecipeVersion recipeLogicalVersion = null;

                String recipePhysicalId = "";
                if (StringUtils.equalsIgnoreCase(logicalRecipeId, MapUtils.getString(lotInfo, "recipeId"))) {
                    recipeLogicalRrn = recipeGroupRrn;
                    recipeLogicalVersion = recipeGroupVersion;
                } else {
                    recipeLogicalRrn = getInstanceRrn(logicalRecipeId, LocalContext.getFacilityRrn(),
                                                      ObjectList.RECIPE_KEY);
                    recipeLogicalVersion = recipeService.getNowActiveRecipeVersion(recipeLogicalRrn);
                }

                recipePhysicalId = recipeService.buildRecipePhysicalId(logicalRecipeId, lotInfo);
                Map lotRecipeInfo = new HashMap();
                lotRecipeInfo.put("recipeGroupRrn", recipeGroupRrn);
                lotRecipeInfo.put("recipeGroupVersion", recipeGroupVersion.getInstanceVersion());
                lotRecipeInfo.put("recipeLogicalRrn", recipeLogicalRrn);
                lotRecipeInfo.put("recipeLogicalVersion", recipeLogicalVersion.getInstanceVersion());
                lotRecipeInfo.put("recipePhysicalId", recipePhysicalId);
                lotRecipeInfo.put("chamberType", chamberType);
                lotRecipeInfo.put("chamberEqptsId", chamberEqptsId);
                lotRecipeInfo.put("recipeParam", MapUtils.getString(lotInfo, "recipeParam"));
                return lotRecipeInfo;
            }
        }
        return null;
    }

    private void buildBondingRelation(Collection lots) {
        for (Object obj : lots) {
            Map map = (Map) obj;
            boolean isSapphireLot = MapUtils.getBooleanValue(map, "isSapphire");
            if (isSapphireLot) {
                Long lotRrn = MapUtils.getLong(map, "lotRrn");
                lotService.updateLotIsSapphire(lotRrn, "1");
            }
        }
    }

}