StatusManagerImpl.java

package com.mycim.server.status.manager.impl;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
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.server.base.manager.EventManager;
import com.mycim.server.base.manager.NamedObjectManager;
import com.mycim.server.base.manager.TransactionLogManager;
import com.mycim.server.carrier.manager.CarrierManager;
import com.mycim.server.carrier.manager.DoorManager;
import com.mycim.server.carrier.manager.PcdManager;
import com.mycim.server.carrier.manager.PodManager;
import com.mycim.server.emas.manager.EmasEventManager;
import com.mycim.server.ems.manager.EntityManager;
import com.mycim.server.ems.manager.EquipmentManager;
import com.mycim.server.pilot.manager.PiLotCheckManager;
import com.mycim.server.reticle.manager.ReticleManager;
import com.mycim.server.status.dao.StatusDAO;
import com.mycim.server.status.manager.StatusManager;
import com.mycim.server.system.manager.ReferenceFileManager;
import com.mycim.server.wip.manager.LotManager;
import com.mycim.valueobject.MessageIdList;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.TransactionLog;
import com.mycim.valueobject.consts.EventName;
import com.mycim.valueobject.consts.ObjectStatus;
import com.mycim.valueobject.consts.PcdStatus;
import com.mycim.valueobject.consts.TransactionNames;
import com.mycim.valueobject.ems.*;
import com.mycim.valueobject.table.SubEntityTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;

@Service
@Transactional
public class StatusManagerImpl implements StatusManager {

    private static final String NUMBER_2 = "2";

    @Autowired
    private TransactionLogManager transactionLogManager;

    @Autowired
    private EntityManager entityManager;

    @Autowired
    private EventManager eventManager;

    @Autowired
    private EquipmentManager equipmentManager;

    @Autowired
    private NamedObjectManager namedObjectManager;

    @Autowired
    private CarrierManager carrierManager;

    @Autowired
    private DoorManager doorManager;

    @Autowired
    private PcdManager pcdManager;

    @Autowired
    private PodManager podManager;

    @Autowired
    private StatusDAO statusDAO;

    @Autowired
    private ReticleManager reticleManager;

    @Autowired
    private LotManager lotManager;

    @Autowired
    private EmasEventManager emasEventManager;

    @Autowired
    private ReferenceFileManager referenceFileManager;

    @Autowired
    private PiLotCheckManager piLotCheckManager;

    @Override
    public long updateEntityStatus(List<EntityStatus> entityStatuss, HashMap map) {
        Long entityRrn = (Long) map.get("entityrrn");
        // STEP 1
        long transRrn = updateEntityStatusOnly(entityStatuss, map);
        // STEP 2
        Event event = (Event) map.get("event");
        String comment = (String) map.get("comments");
        String comment1 = (String) map.get("comments1");
        String comment2 = (String) map.get("comments2");

        String user = (String) map.get("user");

        List<Map<String, Object>> cascadingEvents = eventManager.getCascadingEvent(entityRrn, event.getInstanceRrn());

        if (cascadingEvents != null) {
            Long cascadingEntityRrn;
            for (Map cascading : cascadingEvents) {
                cascadingEntityRrn = (Long) cascading.get("entityRrn");

                if (cascadingEntityRrn != null) {
                    logEventImpl(cascadingEntityRrn, null, event.getInstanceRrn(), user, comment, comment1, comment2);
                }
            }
        }

        List<PrincipalSupportingEvent> principalEvents = eventManager
                .getPrincipalSupportingEvents(entityRrn, event.getInstanceRrn());

        if (principalEvents != null) {

            Long _entityRrn = null;
            Long _eventRrn = null;
            for (PrincipalSupportingEvent item : principalEvents) {
                _entityRrn = item.getSupportEntityRrn();

                _eventRrn = item.getSupportEventRrn();
                if (_entityRrn != null && _eventRrn != null) {
                    logEventImpl(_entityRrn, null, _eventRrn, user, comment, comment1, comment2);
                }
            }
        }
        return transRrn;
    }




    @Override
    public long updateEntityStatusOnly(Collection entityStatuss, HashMap map) {
        Event event = (Event) map.get("event");

        Long entityRrn = (Long) map.get("entityrrn");

        if (entityRrn == null) {
            entityRrn = 0L;
        }
        String user = (String) map.get("user");

        TransactionLog transactionLog = transactionLogManager.startTransactionLog(user, TransactionNames.LOGEVENT_KEY);
        // delete the named object.
        long transRrn = transactionLog.getTransRrn();
        updateAllEntityStatus(entityStatuss, event, entityRrn, transRrn);
        map.put("transrrn", transRrn);
        map.put("lastUpdateTime", transactionLog.getTransStartTimestamp());
        map.put("eventrrn", event.getInstanceRrn());
        map.put("entityavailablebefore", event.getValidAvailability());
        map.put("entityavailableafter", event.getTargetAvailability());
        entityManager.insertEntityEventHistoty(map);
        Entity entity = entityManager.getEntity(entityRrn);
        if ("RETICLE".equalsIgnoreCase(entity.getObjectType())) {
            entity.setAvailability(event.getTargetAvailability());
            entity.setLastUpdateTimestamp(transactionLog.getTransStartTimestamp());
            reticleManager.updateReticleStatus(entity);
        }

        //insert new table
        updateAllEntityStatus((List<EntityStatus>) entityStatuss, event, entity, transactionLog);

        // insert into Transaction Log
        transactionLogManager.markTransactionLog(transactionLog);
        // update status end time
        if (StringUtils.isNotBlank(MapUtils.getString(map, "statusEndTime"))) {
            statusDAO.updateStatusEndTime(transRrn, MapUtils.getString(map, "statusEndTime"));
        }

        return transRrn;

    }

    @Override
    public void updateAllEntityStatus(Collection entityStatuss, Event event, long entityRrn, long transRrn) {
        statusDAO.updateAllEntityStatus(entityStatuss, event, entityRrn, transRrn);
    }

    @Override
    public void updateParentOrChildEntityStatus(HashMap map, Entity entity, Event event,
                                                List<EntityStatus> entityStatuss) {
        // 更改父设备
        // 是否更改子设备状态的时候不联动更改父设备状态
        boolean _flag = true;
        if (_flag) {
            if (entity.getParentEntityRrn() != null && entity.getParentEntityRrn().intValue() > 0) {
                List list = new ArrayList();
                for (EntityStatus entityStatus : entityStatuss) {
                    entityStatus.setEntityRrn(entity.getParentEntityRrn().longValue());
                    list.add(entityStatus);
                }
                map.put("entityrrn", new Long(entity.getParentEntityRrn().longValue()));
                Boolean flag = entityManager.logical4ParentEntityEvent(list, map);
                if (flag) {
                    updateEntityStatus(list, map);
                }
            }
        }

        // 更改子设备
        if (StringUtils.equals("Y", event.getIsChangeChild())) {
            List childEntityRrns = entityManager.getChildEntityRrns(new Long(entity.getInstanceRrn()));

            if (childEntityRrns != null) {
                for (int j = 0; j < childEntityRrns.size(); j++) {
                    List list = new ArrayList();
                    for (EntityStatus entityStatus : entityStatuss) {
                        entityStatus.setEntityRrn(Long.parseLong(childEntityRrns.get(j).toString()));
                        list.add(entityStatus);
                    }
                    map.put("entityrrn", Long.valueOf(childEntityRrns.get(j).toString()));
                    updateEntityStatus(list, map);
                }
            }

        }
    }

    @Override
    public void logEventImpl(long entityRrn, String eventId, long eventRrn, String userId, String comments,
                             String comments1, String comments2) {
        HashMap map = new HashMap();

        Entity entity = new Entity();

        entity.setInstanceRrn(entityRrn);

        entity = entityManager.getEntity(entity);

        Event event = new Event();

        if (eventId != null && eventId.trim().length() > 0) {
            event = new Event(eventId, entity.getNamedSpace(), ObjectList.EVENT_KEY);
        } else {
            event.setInstanceRrn(eventRrn);
        }

        //
        // set event_type
        event.setEntityType(entity.getObjectType());

        event = eventManager.getEvent(event);

        if (event != null) {
            if (event.getTargetAvailability() != null) {
                if (event.getTargetAvailability().equalsIgnoreCase("2")) {

                    event.setTargetAvailability(entity.getAvailability());
                }
            } else {
                event.setTargetAvailability("0");
            }

            List<EventModel> eventModels = eventManager.getEventModelofEvent(event, new Long(entityRrn));

            List<EntityStatus> entityStatuss = new ArrayList();
            for (EventModel eventModel : eventModels) {
                EntityStatus entityStatus = new EntityStatus();
                entityStatus.setStatusGroupId(eventModel.getStatusGroupId());
                entityStatus.setCurrentStatus(eventModel.getTargetStatus());
                entityStatus.setStatusBefore(eventModel.getCurrentStatus());
                entityStatus.setEntityRrn(entity.getInstanceRrn());
                entityStatuss.add(entityStatus);
            }

            map.put("event", event);
            map.put("entityrrn", new Long(entity.getInstanceRrn()));
            map.put("user", userId);
            map.put("comments", comments);
            map.put("comments1", comments1);
            map.put("comments2", comments2);
            updateEntityStatusOnly(entityStatuss, map);
        }
    }

    @Override
    public void changePcdStatusByLogEvent(Long facilityRrn, String user, String pcdId, String pcdType, String eventId,
                                          String comments, String targetStatus, String currentStatus,
                                          String cleanEqptId) {
        String entityNamedSpace = namedObjectManager.getNamedSpace(facilityRrn, ObjectList.ENTITY_KEY);
        long entityRrn = 0;
        PcdAssembly pcdAll = null;
        String objectType = StringUtils.EMPTY;

        if (StringUtils.equalsIgnoreCase(pcdType, ObjectList.CARRIER_KEY)) {
            Carrier c = carrierManager.getCarrier(facilityRrn, pcdId);
            Assert.isTrue(c != null && c.getInstanceRrn() > 0,
                          Errors.create().key(MessageIdList.CARRIER_CASSETTE_MISSING).content("Cassette 不存在").build());
            entityRrn = c.getInstanceRrn();
            objectType = c.getObjectType();
            pcdAll = pcdManager.getPcdAssembly(c.getInstanceRrn(), null, null);
            // 既是组合 又是wait_clean
            Assert.isFalse(pcdAll!=null&&StringUtils.equalsIgnoreCase(c.getCarrierStatus(),PcdStatus.WAIT_CLEAN_KEY),
                           Errors.create().key(MessageIdList.PCD_DEASSEMBLY_PCD_FIRST).content("请先解绑PCD").build());
        } else if (StringUtils.equalsIgnoreCase(pcdType, ObjectList.POD_KEY)) {
            long podRrn = namedObjectManager
                    .getNamedObjectRrn(pcdId, entityNamedSpace, ObjectList.ENTITY_KEY, ObjectList.POD_KEY);
            POD p = podManager.getPod(podRrn);
            Assert.isTrue(p != null && p.getInstanceRrn() > 0,
                          Errors.create().key(MessageIdList.POD_POD_MISSING).content("Pod 不存在").build());
            entityRrn = p.getInstanceRrn();
            objectType = p.getObjectType();
            pcdAll = pcdManager.getPcdAssembly(null, p.getInstanceRrn(), null);
            // 既是组合 又是wait_clean
            Assert.isFalse(pcdAll!=null&&StringUtils.equalsIgnoreCase(p.getPodStatus(),PcdStatus.WAIT_CLEAN_KEY),
                          Errors.create().key(MessageIdList.PCD_DEASSEMBLY_PCD_FIRST).content("请先解绑PCD").build());
        } else if (StringUtils.equalsIgnoreCase(pcdType, ObjectList.DOOR_KEY)) {
            long doorRrn = namedObjectManager
                    .getNamedObjectRrn(pcdId, entityNamedSpace, ObjectList.ENTITY_KEY, ObjectList.DOOR_KEY);
            Door d = doorManager.getDoor(doorRrn);
            Assert.isTrue(d != null && d.getInstanceRrn() > 0,
                          Errors.create().key(MessageIdList.DOOR_DOOR_MISSING).content("Door 不存在").build());
            entityRrn = d.getInstanceRrn();
            objectType = d.getObjectType();
            pcdAll = pcdManager.getPcdAssembly(null, null, d.getInstanceRrn());
            // 既是组合 又是wait_clean
            Assert.isFalse(pcdAll!=null&&StringUtils.equalsIgnoreCase(d.getDoorStatus(),PcdStatus.WAIT_CLEAN_KEY),
                          Errors.create().key(MessageIdList.PCD_DEASSEMBLY_PCD_FIRST).content("请先解绑PCD").build());
        }
        // 手动change,P/C/D 上有批次都不能change
        String hasLotCarrierId = pcdId;
        if (pcdAll != null && StringUtils.isNotBlank(pcdAll.getCarrierId())) {
            hasLotCarrierId = pcdAll.getCarrierId();
        }

        Carrier hasLotCarrier = null;
        hasLotCarrier = carrierManager.getCarrier(
                new Carrier(hasLotCarrierId, namedObjectManager.getNamedSpace(facilityRrn, ObjectList.ENTITY_KEY),
                            ObjectList.ENTITY_KEY));
        // 晶舟上有批次
        Assert.isFalse(hasLotCarrier != null && hasLotCarrier.getSlotCount() > hasLotCarrier.getAvailableSlotCount(),
                       Errors.create().key(MessageIdList.CARRIER_EXCHANGE_CASSETTE_FIRST).content("请先交换晶舟").build());

        // PCD组装模式下,只能做FREE操作
        // IN_CLEAN 操作必须是单个组件
        Assert.isFalse(pcdAll != null && StringUtils.isNotBlank(pcdAll.getCarrierId()) &&
                               !StringUtils.equalsIgnoreCase(targetStatus, PcdStatus.FREE_KEY),
                       Errors.create().key(MessageIdList.PCD_DEASSEMBLY_PCD_FIRST).content("请先解绑PCD").build());

        if (entityRrn > 0) {
            // check是否是组装状态
            if (pcdAll != null && StringUtils.isNotBlank(pcdAll.getCarrierId())) {
                // 分别获取P/C/D的事件ID
                Carrier pcdCst = carrierManager.getCarrier(facilityRrn, pcdAll.getCarrierId());
                String cstEventId = eventManager
                        .getEventIdBy2Status(facilityRrn, pcdAll.getCarrierRrn(), pcdCst.getCarrierStatus(),
                                             targetStatus);

                POD pcdPod =pcdAll.getPodRrn()==null||pcdAll.getPodRrn()==0?null: podManager.getPod(pcdAll.getPodRrn());
                String podEventId =pcdPod==null?null: eventManager
                        .getEventIdBy2Status(facilityRrn, pcdAll.getPodRrn(), pcdPod.getPodStatus(), targetStatus);

                Door pcdDoor =pcdAll.getDoorRrn()==null||pcdAll.getDoorRrn()==0?null: doorManager.getDoor(pcdAll.getDoorRrn());
                String doorEventId = pcdDoor==null?null:eventManager
                        .getEventIdBy2Status(facilityRrn, pcdAll.getDoorRrn(), pcdDoor.getDoorStatus(), targetStatus);


                // 组装模式下,当前状态是 WAIT_CLEAN,前一个状态是ASSEMBLY, P/C/D本身状态不改变(做两段倒转操作)
                // 将P/C/D先由WAIT_CLEAN变为FREE,再有FREE变为WAIT_CLEAN
                comments += "  [Carrier: " + pcdCst.getInstanceId() + (pcdPod==null?"": ", Pod: " + pcdPod.getInstanceId()) +
                        (pcdDoor==null?"":", Door: " + pcdDoor.getInstanceId())+ "]";

                changeCstState(pcdCst,pcdAll,comments,targetStatus,cstEventId);
                changePodState(pcdPod,pcdAll,comments,targetStatus,podEventId);
                changeDoorState(pcdDoor,pcdAll,comments,targetStatus,doorEventId);
                pcdManager.deAssemblyPcd(pcdAll.getCarrierRrn(), user, null);
            } else {
                long transRrn = changePCDStatusByEvent(facilityRrn, user, entityRrn, objectType, eventId, comments);
                if (StringUtils.equalsIgnoreCase(pcdType, ObjectList.CARRIER_KEY)) {
                    this.updateCarrierStatus(entityRrn, targetStatus, user, null, transRrn, comments);
                } else if (StringUtils.equalsIgnoreCase(pcdType, ObjectList.POD_KEY)) {
                    this.updatePodStatus(entityRrn, targetStatus, user, null, transRrn, comments);
                } else if (StringUtils.equalsIgnoreCase(pcdType, ObjectList.DOOR_KEY)) {
                    this.updateDoorStatus(entityRrn, targetStatus, user, null, transRrn, comments);
                }

                if (StringUtils.equalsIgnoreCase(targetStatus, PcdStatus.IN_CLEAN_KEY)) {
                    // 开始清洗
                    pcdManager.inCleanPcd(cleanEqptId, entityRrn, user, facilityRrn);
                }
                if (StringUtils.equalsIgnoreCase(currentStatus, PcdStatus.IN_CLEAN_KEY)) {
                    // 结束清洗
                    pcdManager.outCleanPcd(entityRrn, user, facilityRrn);
                }
            }
        }
    }

    @Override
    public long changePCDStatusByEvent(Long facilityRrn, String user, Long objectRrn, String objectType, String eventId,
                                       String comments) {
        Event event = new Event();
        long eventRrn = namedObjectManager
                .getNamedObjectRrn(eventId, namedObjectManager.getNamedSpace(facilityRrn, ObjectList.EVENT_KEY),
                                   ObjectList.EVENT_KEY);
        event.setInstanceRrn(eventRrn);
        event.setEntityType(objectType);
        event = eventManager.getEvent(event);
        Assert.isFalse(event == null || event.getInstanceRrn() <= 0,
                       Errors.create().content("Event ID not found!").build());
        event.setEventModels(eventManager.getEventModels(eventRrn, objectRrn));

        Collection entityStatuss = new ArrayList();
        Collection eventModels = event.getEventModels();
        Iterator it = eventModels.iterator();
        while (it.hasNext()) {
            EventModel instance = (EventModel) it.next();
            EntityStatus entityStatus = new EntityStatus();
            entityStatus.setStatusGroupId(instance.getStatusGroupId());
            entityStatus.setCurrentStatus(parseInputStatus(instance.getTargetStatus()));
            entityStatus.setStatusBefore(parseInputStatus(instance.getCurrentStatus()));
            entityStatus.setEntityRrn(objectRrn);

            entityStatuss.add(entityStatus);
        }

        if (checkEnableLogEvent(event.getInstanceRrn(), objectRrn)) {
            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put("event", event);
            map.put("user", user);
            map.put("comments", comments);
            map.put("entityrrn", objectRrn);
            long transRrn = this.updateEntityStatusOnly(entityStatuss, map);
            return transRrn;
        }
        return 0;
    }

    @Override
    public void updateCarrierStatus(Long carrierRrn, Long transRrn, String status, String comments) {
        statusDAO.updateCarrierStatus(carrierRrn, transRrn, status, comments);
    }

    @Override
    public void updateCarrierStatus(Long carrierRrn, String status, String user, String transId, Long transRrn,
                                    String comments) {
        TransactionLog transactionLog = null;
        if (transRrn == null || transRrn == 0) {
            transactionLog = transactionLogManager.startTransactionLog(user, transId);
            transRrn = transactionLog.getTransRrn();
        }

        statusDAO.updateCarrierStatus(carrierRrn, transRrn, status, comments);

        carrierManager.insertCarrierH(carrierRrn, comments, transRrn);

        PcdClean cstCleanInfo = pcdManager.getPcdCleanInfo(carrierRrn);
        if (cstCleanInfo != null && StringUtils.isNotBlank(cstCleanInfo.getInstanceId())) {
            pcdManager.insertPcdCleanH(transRrn, cstCleanInfo);
        }

        if (transactionLog != null) {
            transactionLogManager.markTransactionLog(transactionLog);
        }
    }

    @Override
    public void updatePodStatus(Long podRrn, String status, String user, String transId, Long transRrn,
                                String comments) {
        TransactionLog transactionLog = null;
        if (transRrn == null || transRrn == 0) {
            transactionLog = transactionLogManager.startTransactionLog(user, transId);
            transRrn = transactionLog.getTransRrn();
        }

        statusDAO.updatePodStatus(podRrn, transRrn, status, comments);

        podManager.insertPodH(podRrn, comments, transRrn);

        PcdClean cstCleanInfo = pcdManager.getPcdCleanInfo(podRrn);
        if (cstCleanInfo != null && StringUtils.isNotBlank(cstCleanInfo.getInstanceId())) {
            pcdManager.insertPcdCleanH(transRrn, cstCleanInfo);
        }

        if (transactionLog != null) {
            transactionLogManager.markTransactionLog(transactionLog);
        }
    }

    @Override
    public void updateDoorStatus(Long doorRrn, String status, String user, String transId, Long transRrn,
                                 String comments) {
        TransactionLog transactionLog = null;
        if (transRrn == null || transRrn == 0) {
            transactionLog = transactionLogManager.startTransactionLog(user, transId);
            transRrn = transactionLog.getTransRrn();
        }

        statusDAO.updateDoorStatus(doorRrn, transRrn, status, comments);

        doorManager.insertDoorH(doorRrn, comments, transRrn);

        PcdClean cstCleanInfo = pcdManager.getPcdCleanInfo(doorRrn);
        if (cstCleanInfo != null && StringUtils.isNotBlank(cstCleanInfo.getInstanceId())) {
            pcdManager.insertPcdCleanH(transRrn, cstCleanInfo);
        }

        if (transactionLog != null) {
            transactionLogManager.markTransactionLog(transactionLog);
        }
    }

    @Override
    public boolean checkEnableLogEvent(long eventRrn, long entityRrn) {
        Entity entity = new Entity();
        Event myevent = new Event();

        entity.setInstanceRrn(entityRrn);
        myevent.setInstanceRrn(eventRrn);

        entity = entityManager.getEntity(entity);

        Assert.isFalse(entity == null, Errors.create().key(MessageIdList.ENTITY_MISSING).content("找不到entity").build());

        myevent.setEntityType(entity.getObjectType());

        myevent = eventManager.getEvent(myevent);

        Assert.isFalse(myevent == null, Errors.create().key(MessageIdList.EVENT_MISSING).content("找不到事件").build());

        String entityId = namedObjectManager.getNamedObjectId(entity.getInstanceRrn());
        if (entityId == null) {
            entityId = "";
        }
        // step 1:
        if (entity.getInstanceStatus() == null) {
            entity.setInstanceStatus("ACTIVE");
        }

        Assert.isFalse(entity.getInstanceStatus().equalsIgnoreCase(ObjectStatus.HOLD_KEY),
                       Errors.create().key(MessageIdList.ENTITY_STATUS_HOLD).content("实体{}状态是hold").args(entityId)
                             .build());

        // step 2:
        if ((entity.getExecutionRrn() == null) || (entity.getExecutionRrn().longValue() < 1)) {
            Assert.isFalse(entity.getLastEventRrn() != null &&
                                   entity.getLastEventRrn().longValue() != myevent.getInstanceRrn(),
                           Errors.create().key(MessageIdList.ENTITY_EVENT_NOT_END).content("当前实体{}事件未结束").args(entityId)
                                 .build());
        }

        if (myevent.getValidAvailability() != null) {
            if (!myevent.getValidAvailability().equalsIgnoreCase(NUMBER_2)) {
                // if (entity.getAvailability() == null
                // || !entity.getAvailability().equalsIgnoreCase(event.getValidAvailability())) {
                // // throw new
                // //
                // ValidateException("Current entity "+entityId+"'s status not same as event
                // defined,event->"+event.getValidAvailability()+" ,entity->"+entity
                // .getAvailability(),3);
                // throw new ValidateException("The status of " + entityId
                // + " is not valid, please check it and try again.", 3);
                // }
            }
        }
        // step4
        Assert.isFalse(eventManager.getEventAndEntityStatus(new Long(myevent.getInstanceRrn()),
                                                            new Long(entity.getInstanceRrn())) == null,
                       Errors.create().key(MessageIdList.EQUIPMENT_STATUS_INVALID).content("设备{}当前状态无效").args(entityId)
                             .build());
        return true;
    }

    @Override
    public boolean checkEnableLogEventNoException(long eventRrn, long entityRrn) {
        Entity entity = new Entity();
        Event myevent = new Event();

        entity.setInstanceRrn(entityRrn);
        myevent.setInstanceRrn(eventRrn);

        entity = entityManager.getEntity(entity);

        if (entity == null) {
            return false;
        }

        myevent.setEntityType(entity.getObjectType());

        myevent = eventManager.getEvent(myevent);

        if (myevent == null) {
            return false;
        }

        String entityId = namedObjectManager.getNamedObjectId(entity.getInstanceRrn());
        if (entityId == null) {
            entityId = "";
        }
        // step 1:
        if (entity.getInstanceStatus() == null) {
            entity.setInstanceStatus("ACTIVE");
        }

        if (entity.getInstanceStatus().equalsIgnoreCase(ObjectStatus.HOLD_KEY)) {
            return false;
        }

        // step 2:
        if ((entity.getExecutionRrn() == null) || (entity.getExecutionRrn().longValue() < 1)) {
            if ((entity.getLastEventRrn() != null) &&
                    (entity.getLastEventRrn().longValue() != myevent.getInstanceRrn())) {
                return false;
            }
        }

        if (myevent.getValidAvailability() != null) {
            if (!myevent.getValidAvailability().equalsIgnoreCase(NUMBER_2)) {
                // if (entity.getAvailability() == null
                // || !entity.getAvailability().equalsIgnoreCase(event.getValidAvailability())) {
                // // throw new
                // //
                // ValidateException("Current entity "+entityId+"'s status not same as event
                // defined,event->"+event.getValidAvailability()+" ,entity->"+entity
                // .getAvailability(),3);
                // throw new ValidateException("The status of " + entityId
                // + " is not valid, please check it and try again.", 3);
                // }
            }
        }
        // step4
        if (eventManager
                .getEventAndEntityStatus(new Long(myevent.getInstanceRrn()), new Long(entity.getInstanceRrn())) ==
                null) {
            return false;
        }
        return true;
    }

    @Override
    public void updatePcdStatus(Long carrierRrn, Long podRrn, Long doorRrn, String status, Long transRrn,
                                String comments) {

        String cstId = namedObjectManager.getNamedObjectId(carrierRrn);
        String podId = namedObjectManager.getNamedObjectId(podRrn);
        String dorId = null;
        comments += "  [Carrier: " + cstId + " Pod: " + podId ;
        if (doorRrn != null && doorRrn > 0) {/** by #40125 */
            dorId = namedObjectManager.getNamedObjectId(doorRrn);
            comments+=" Door:"+ dorId + "]";
            statusDAO.updateDoorStatus(doorRrn, transRrn, status, comments);
        }
        statusDAO.updateCarrierStatus(carrierRrn, transRrn, status, comments);
        //        dao.updateCarrierAvailableSlotCount(carrierRrn);
        statusDAO.updatePodStatus(podRrn, transRrn, status, comments);

    }

    @Override
    public void changePCDStatusAndEvent(String user, Long objectRrn, String objectType, Long eventRrn, String comments,
                                        String targetStatus) {
        Event event = new Event();
        event.setInstanceRrn(eventRrn);
        event.setEntityType(objectType);
        event = eventManager.getEvent(event);
        event.setEventModels(eventManager.getEventModels(eventRrn, objectRrn));

        List<EntityStatus> entityStatuss = new ArrayList();
        Collection eventModels = event.getEventModels();
        Iterator it = eventModels.iterator();
        while (it.hasNext()) {
            EventModel instance = (EventModel) it.next();
            EntityStatus entityStatus = new EntityStatus();
            entityStatus.setStatusGroupId(instance.getStatusGroupId());
            entityStatus.setCurrentStatus(parseInputStatus(instance.getTargetStatus()));
            entityStatus.setStatusBefore(parseInputStatus(instance.getCurrentStatus()));
            entityStatus.setEntityRrn(objectRrn);

            entityStatuss.add(entityStatus);
        }

        if (this.checkEnableLogEvent(event.getInstanceRrn(), objectRrn)) {
            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put("event", event);
            map.put("user", user);
            map.put("comments", comments);
            map.put("entityrrn", objectRrn);
            map.put("entityType", objectType);
            map.put("targetStatus", targetStatus);
            this.updateEntityStatusAndEvent(entityStatuss, map, comments);

            String transId=" to "+targetStatus;
            if(CollectionUtils.isNotEmpty(entityStatuss)){
                EntityStatus entityStatus =entityStatuss.get(0);
                transId= entityStatus.getStatusBefore()+"_to_"+entityStatus.getCurrentStatus();
            }
            if(transId.length()>24){ //数据库字段超长
                transId =transId.substring(0,20);
                transId+=transId+"...";
            }
            TransactionLog transactionLog = transactionLogManager
                    .startTransactionLog(user,transId);
            //这里需要判断是否直接插入carrier_h中
            if (StringUtils.equalsIgnoreCase(objectType, ObjectList.CARRIER_KEY)) {
                carrierManager.insertCarrierH(objectRrn,comments,transactionLog.getTransRrn());
            } else if (StringUtils.equalsIgnoreCase(objectType, ObjectList.POD_KEY)) {
                podManager.insertPodH(objectRrn,comments,transactionLog.getTransRrn());
            } else if (StringUtils.equalsIgnoreCase(objectType, ObjectList.DOOR_KEY)) {
                doorManager.insertDoorH(objectRrn,comments,transactionLog.getTransRrn());
            }
            transactionLogManager.markTransactionLog(transactionLog);
            // carrierDAO.insertCarrierH(instanceRrn, StringUtils.EMPTY, carrier.getInstanceId(), transactionLog);
        }
    }

    @Override
    public void updateEntityStatusAndEvent(List<EntityStatus> entityStatuss, HashMap map, String comments) {
        Event event = (Event) map.get("event");
        String user = MapUtils.getString(map, "user");
        Long entityRrn = MapUtils.getLongValue(map, "entityrrn");
        String entityType = MapUtils.getString(map, "entityType");
        String targetStatus = MapUtils.getString(map, "targetStatus");
        TransactionLog transactionLog = transactionLogManager
                .startTransactionLog(user, TransactionNames.CHANGE_STATUS_KEY);
        long transRrn = transactionLog.getTransRrn();
        //修改原表中的数据
        updateAllEntityStatus(entityStatuss, event, entityRrn, transRrn);
        //修改新表中的数据,并记录历史
        updateAllEntityStatus(entityStatuss, event, new Entity(entityRrn), transactionLog);

        map.put("transrrn", transRrn);
        map.put("eventrrn", event.getInstanceRrn());
        map.put("entityavailablebefore", event.getValidAvailability());
        map.put("entityavailableafter", event.getTargetAvailability());

        entityManager.insertEntityEventHistoty(map);

        if (StringUtils.equalsIgnoreCase(entityType, ObjectList.CARRIER_KEY)) {
            statusDAO.updateCarrierStatus(entityRrn, transRrn, targetStatus, comments);
        } else if (StringUtils.equalsIgnoreCase(entityType, ObjectList.POD_KEY)) {
            statusDAO.updatePodStatus(entityRrn, transRrn, targetStatus, comments);
        } else if (StringUtils.equalsIgnoreCase(entityType, ObjectList.DOOR_KEY)) {
            statusDAO.updateDoorStatus(entityRrn, transRrn, targetStatus, comments);
        }
        transactionLogManager.markTransactionLog(transactionLog);
    }

    @Override
    public Long updateEntityStatusForReticle(List<EntityStatus> entityStatuss, HashMap map, Reticle reticle) {
        Long transRrn = this.updateEntityStatus(entityStatuss, map);
        reticle.setTransRrn(transRrn);
        reticle.setTransSequence(1L);
        reticle.setLastUpdateTimestamp(
                (Timestamp) MapUtils.getObject(map, "lastUpdateTime", new Timestamp(System.currentTimeMillis())));
        this.addReticleHAndEntityH(reticle);
        return transRrn;
    }

    @Override
    public long updateEntityStatusByEntityId(List entityStatuss, String user, Long userRrn, Event event,
                                             String comments, String comments1, String comments2, String statusEndTime,
                                             long entityRrn) {
        long transRrn = 0;
        if (checkEnableLogEvent(event.getInstanceRrn(), entityRrn)) {
            HashMap<String, Object> map = new HashMap<String, Object>(10);
            map.put("event", event);
            map.put("user", user);
            map.put("comments", comments);
            map.put("comments1", comments1);
            map.put("comments2", comments2);
            map.put("statusEndTime", statusEndTime);
            map.put("entityrrn", entityRrn);
            Entity entity = entityManager.getEntity(entityRrn);
            if (StringUtils.equalsIgnoreCase(entity.getObjectType(), ObjectList.RETICLE_KEY)) {
                Reticle reticle = new Reticle();
                BeanUtils.copyProperties(entity, reticle);
                EntityStatus entityStatus = (EntityStatus) entityStatuss.get(0);
                reticle.setPrevEntityStatus(entityStatus.getStatusBefore());
                reticle.setCurrentEntityStatus(entityStatus.getCurrentStatus());
                //当触发清洗记录动作,更新实际清洗数
                Reticle reticleInfo = new Reticle();
                reticleInfo = reticleManager.getReticleInfo(entity.getInstanceId(),entity.getReticleFamilyRrn());
                if (StringUtils.equals(event.getInstanceId(), EventName.RTL_IN_PD_TO_IDLE) &&
                        StringUtils.equals(entityStatus.getStatusBefore(), EventName.RTL_STATUS_IN_PD)) {
                    reticleInfo.setCleanCount(reticleInfo.getCleanCount() + 1);
                    reticleManager.updateReticleCleanCount(reticleInfo);
                } else if (StringUtils.equals(event.getInstanceId(), EventName.RTL_IN_PD_TO_HOLD) &&
                        StringUtils.equals(entityStatus.getStatusBefore(), EventName.RTL_STATUS_IN_PD)) {
                    reticleInfo.setCleanCount(reticleInfo.getCleanCount() + 1);
                    reticleManager.updateReticleCleanCount(reticleInfo);
                }

                transRrn = this.updateEntityStatusForReticle(entityStatuss, map, reticle);
            } else {
                transRrn = this.updateEntityStatus(entityStatuss, map);
            }
            // insert EMAS info
            if (CollectionUtils.isNotEmpty(entityStatuss)) {
                EntityStatus entityStatus = (EntityStatus) entityStatuss.iterator().next();
                String preStatus = entityStatus.getStatusBefore();
                String toStatus = entityStatus.getCurrentStatus();
                if (StringUtils.equalsIgnoreCase(preStatus, "PM")) {
                    String eventId = "MANUAL." + preStatus + "_TO_" + toStatus;
                    String eqpId = namedObjectManager.getInstanceId(entityRrn);
                    emasEventManager.generateEmasEventRecord(eqpId, eventId);
                    //增加Pi Lot
                    piLotCheckManager.checkEquipmentPiLotByPM(eqpId);
                }
            }

            for (int i = 0; i < entityStatuss.size(); i++) {
                Object obj = entityStatuss.get(i);
                if (obj instanceof EntityStatus) {
                    EntityStatus es = (EntityStatus) obj;
                    if (StringUtils.equals(EventName.WAIT_ENG, es.getCurrentStatus())) {
                        Map holdInfo = new HashMap(10);
                        holdInfo.put("holdCode", "WAIT_ENG");
                        holdInfo.put("holdReasons", "Wait ENG");
                        holdInfo.put("userId", "SYSTEM");
                        lotManager.holdRunningLotByEqpWaitENG(entityRrn, holdInfo);
                    }
                }
            }
        }
        //每个机台都记录Change Status Comment
        entityStatuss.forEach(o -> {
            EntityStatus entityStatus = (EntityStatus) o;
            equipmentManager.addEqptComment(entityStatus.getEntityRrn(), comments, user);

        });
        return transRrn;
    }

    @Override
    public void logEventImpl(long entityRrn, String eventId, long eventRrn, String userId, Map maph) {
        HashMap map = new HashMap();
        Entity entity = new Entity();
        entity.setInstanceRrn(entityRrn);
        entity = entityManager.getEntity(entity);
        Event event = new Event();
        if (eventId != null && eventId.trim().length() > 0) {
            event = new Event(eventId, entity.getNamedSpace(), ObjectList.EVENT_KEY);
        } else {
            event.setInstanceRrn(eventRrn);
        }
        // set event_type
        event.setEntityType(entity.getObjectType());
        entity = entityManager.getEntity(entity);
        if (event != null) {
            if (event.getTargetAvailability() != null) {
                if (event.getTargetAvailability().equalsIgnoreCase("2")) {
                    event.setTargetAvailability(entity.getAvailability());
                }
            } else {
                event.setTargetAvailability("0");
            }
            Collection eventModels = eventManager.getEventModelofEvent(event, new Long(entityRrn));

            Iterator it = eventModels.iterator();
            int i = 0;
            List<EntityStatus> entityStatuss = new ArrayList();
            while (it.hasNext()) {
                EventModel instance = (EventModel) it.next();
                EntityStatus entityStatus = new EntityStatus();
                entityStatus.setStatusGroupId(instance.getStatusGroupId());
                entityStatus.setCurrentStatus(instance.getTargetStatus());
                entityStatus.setStatusBefore(instance.getCurrentStatus());
                entityStatus.setEntityRrn(entity.getInstanceRrn());
                entityStatuss.add(entityStatus);
            }
            map.put("event", event);
            map.put("entityrrn", new Long(entity.getInstanceRrn()));
            map.put("user", userId);
            map.put("comments", "Background");
            map.putAll(maph);
            updateEntityStatus(entityStatuss, map);
        }
    }

    @Override
    public void updateParentEntityByChamberAllInSameState(List<EntityStatus> entityStatuss,
                                                          HashMap<String, Object> comment, List<String> status) {
        if (CollectionUtils.isEmpty(entityStatuss) || MapUtils.isEmpty(comment) || CollectionUtils.isEmpty(status)) {
            return;
        }
        BiConsumer<Set<EntityStatus>, String> cascadUpdate = (parentEntityStatusResult, changeToState) -> {
            if (CollectionUtils.isNotEmpty(parentEntityStatusResult)) {
                for (EntityStatus parentStatus : parentEntityStatusResult) {
                    //根据状态去查询 xxx.getCurrentStatus() 巨坑。。。。。直接是null 有时候有 有时候没有
                    String currentStatus = entityManager.getEntityCurrentStatus(parentStatus.getEntityRrn());
                    String changeEvent = "EQP." + currentStatus + String.format("_TO_%s", changeToState);
                    Event parentEvent = eventManager.getEvent(changeEvent);
                    if (parentEvent == null) {//当前设备没有对应的事件不能更改
                        continue;
                    }
                    parentStatus.setStatusBefore(currentStatus);
                    parentStatus.setCurrentStatus(changeToState);
                    comment.put("event", parentEvent);
                    comment.put("entityrrn", parentStatus.getEntityRrn());
                    //如果发生down 或者 wait_eng 操作下面的函数会自动 hold 已经挂载设备上运行的lot
                    updateEntityStatus(Arrays.asList(parentStatus), comment);
                }
            }
        };
        for (String state : status) {//这里要保证 子设备状态的一致性
            Set<EntityStatus> downResult = getParentEntityStatusByChamberAllInTheSeamState(entityStatuss, state);
            cascadUpdate.accept(downResult, state);
        }
    }

    /**
     * 修改新状态表中的数据 的集合
     *
     * @param entityStatusList 实体集合
     * @param event            事件
     * @param entity           实体设备对象
     * @param transactionLog   事务Log对象
     */
    public void updateAllEntityStatus(List<EntityStatus> entityStatusList, Event event, Entity entity,
                                      TransactionLog transactionLog) {
        if (StringUtils.isBlank(entity.getObjectType()) && entity.getInstanceRrn() > 0) {
            entity = entityManager.getEntity(entity.getInstanceRrn());
        }
        //循环执行
        SubEntityTable st = new SubEntityTable(entity.getObjectType(), entity.getInstanceRrn(), event.getInstanceRrn());
        for (EntityStatus es : entityStatusList) {
            updateEntityStatus(es, st, transactionLog);
        }
    }

    public void updateEntityStatus(EntityStatus est, SubEntityTable set, TransactionLog tl) {
        if (set == null || StringUtils.isBlank(set.getSubEntityTableName()) ||
                StringUtils.isBlank(set.getSubEntityHistoryTableName())) {
            return;
        }
        //修改新表的状态
        statusDAO.updateEntityStatus(est, set, tl);
        //记录修改新表的历史
        statusDAO.insertEntityStatusHistory(est, set, tl);
    }

    private void changeDoorState(Door pcdDoor, PcdAssembly pcdAll, String comments, String targetStatus,
                                 String doorEventId) {
        if (pcdDoor == null) {
            return;
        }
        Long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();
        String doorPreStatus = entityManager.getPreStatusByEntityRrn(pcdDoor.getInstanceRrn());
        long transRrn = 0;
        if (StringUtils.isNotBlank(doorPreStatus)) {
            if (StringUtils.equals(doorPreStatus, PcdStatus.ASSEMBLY_KEY) &&
                    StringUtils.equals(pcdDoor.getDoorStatus(), PcdStatus.WAIT_CLEAN_KEY)) {
                // 变更两次
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getDoorRrn(), ObjectList.DOOR_KEY,
                                       EventName.DOOR_WAIT_CLEAN_TO_FREE, comments);
                this.updateDoorStatus(pcdAll.getDoorRrn(), PcdStatus.FREE_KEY, user, TransactionNames.LOGEVENT_KEY,
                                      null, comments);

                changePCDStatusByEvent(facilityRrn, user, pcdAll.getDoorRrn(), ObjectList.DOOR_KEY,
                                       EventName.DOOR_FREE_TO_WAIT_CLEAN, comments);
                this.updateDoorStatus(pcdAll.getDoorRrn(), PcdStatus.WAIT_CLEAN_KEY, user,
                                      TransactionNames.LOGEVENT_KEY, null, comments);
            } else {
                // 同时做LOGEVET操作和历史记录操作
                transRrn = changePCDStatusByEvent(facilityRrn, user, pcdAll.getDoorRrn(), ObjectList.DOOR_KEY,
                                                  doorEventId, comments);
                this.updateDoorStatus(pcdAll.getDoorRrn(), targetStatus, user, null, transRrn, comments);
            }
        } else {
            if (StringUtils.equals(pcdDoor.getDoorStatus(), PcdStatus.WAIT_CLEAN_KEY)) {
                // 变更两次
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getDoorRrn(), ObjectList.DOOR_KEY,
                                       EventName.DOOR_WAIT_CLEAN_TO_FREE, comments);
                this.updateDoorStatus(pcdAll.getDoorRrn(), PcdStatus.FREE_KEY, user, TransactionNames.LOGEVENT_KEY,
                                      null, comments);

                changePCDStatusByEvent(facilityRrn, user, pcdAll.getDoorRrn(), ObjectList.DOOR_KEY,
                                       EventName.DOOR_FREE_TO_WAIT_CLEAN, comments);
                this.updateDoorStatus(pcdAll.getDoorRrn(), PcdStatus.WAIT_CLEAN_KEY, user,
                                      TransactionNames.LOGEVENT_KEY, null, comments);
            } else {
                // 同时做LOGEVET操作和历史记录操作
                transRrn = changePCDStatusByEvent(facilityRrn, user, pcdAll.getDoorRrn(), ObjectList.DOOR_KEY,
                                                  doorEventId, comments);
                this.updateDoorStatus(pcdAll.getDoorRrn(), targetStatus, user, null, transRrn, comments);
            }
        }
    }

    private void changePodState(POD pcdPod, PcdAssembly pcdAll, String comments, String targetStatus,
                                String podEventId) {
        Long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();
        String podPreStatus = entityManager.getPreStatusByEntityRrn(pcdPod.getInstanceRrn());
        long transRrn = 0;
        if (StringUtils.isNotBlank(podPreStatus)) {
            if (StringUtils.equals(podPreStatus, PcdStatus.ASSEMBLY_KEY) &&
                    StringUtils.equals(pcdPod.getPodStatus(), PcdStatus.WAIT_CLEAN_KEY)) {
                // 变更两次
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getPodRrn(), ObjectList.POD_KEY,
                                       EventName.POD_WAIT_CLEAN_TO_FREE, comments);
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getPodRrn(), ObjectList.POD_KEY,
                                       EventName.POD_FREE_TO_WAIT_CLEAN, comments);

                this.updatePodStatus(pcdAll.getPodRrn(), PcdStatus.FREE_KEY, user, TransactionNames.LOGEVENT_KEY, null,
                                     comments);
                this.updatePodStatus(pcdAll.getPodRrn(), PcdStatus.WAIT_CLEAN_KEY, user, TransactionNames.LOGEVENT_KEY,
                                     null, comments);
            } else {
                // 同时做LOGEVET操作和历史记录操作
                transRrn = changePCDStatusByEvent(facilityRrn, user, pcdAll.getPodRrn(), ObjectList.POD_KEY, podEventId,
                                                  comments);
                this.updatePodStatus(pcdAll.getPodRrn(), targetStatus, user, null, transRrn, comments);
            }
        } else {
            if (StringUtils.equals(pcdPod.getPodStatus(), PcdStatus.WAIT_CLEAN_KEY)) {
                // 变更两次
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getPodRrn(), ObjectList.POD_KEY,
                                       EventName.POD_WAIT_CLEAN_TO_FREE, comments);
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getPodRrn(), ObjectList.POD_KEY,
                                       EventName.POD_FREE_TO_WAIT_CLEAN, comments);

                this.updatePodStatus(pcdAll.getPodRrn(), PcdStatus.FREE_KEY, user, TransactionNames.LOGEVENT_KEY, null,
                                     comments);
                this.updatePodStatus(pcdAll.getPodRrn(), PcdStatus.WAIT_CLEAN_KEY, user, TransactionNames.LOGEVENT_KEY,
                                     null, comments);
            } else {
                // 同时做LOGEVET操作和历史记录操作
                transRrn = changePCDStatusByEvent(facilityRrn, user, pcdAll.getPodRrn(), ObjectList.POD_KEY, podEventId,
                                                  comments);
                this.updatePodStatus(pcdAll.getPodRrn(), targetStatus, user, null, transRrn, comments);
            }
        }
    }

    private void changeCstState(Carrier pcdCst, PcdAssembly pcdAll, String comments, String targetStatus,
                                String cstEventId) {
        Long facilityRrn = LocalContext.getFacilityRrn();
        String user = LocalContext.getUserId();
        String cstPreStatus = entityManager.getPreStatusByEntityRrn(pcdCst.getInstanceRrn());
        long transRrn = 0;
        if (StringUtils.isNotBlank(cstPreStatus)) {
            if (StringUtils.equals(cstPreStatus, PcdStatus.ASSEMBLY_KEY) &&
                    StringUtils.equals(pcdCst.getCarrierStatus(), PcdStatus.WAIT_CLEAN_KEY)) {
                // 变更两次
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getCarrierRrn(), ObjectList.CARRIER_KEY,
                                       EventName.CST_WAIT_CLEAN_TO_FREE, comments);
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getCarrierRrn(), ObjectList.CARRIER_KEY,
                                       EventName.CST_FREE_TO_WAIT_CLEAN, comments);

                this.updateCarrierStatus(pcdAll.getCarrierRrn(), PcdStatus.FREE_KEY, user,
                                         TransactionNames.LOGEVENT_KEY, null, comments);
                this.updateCarrierStatus(pcdAll.getCarrierRrn(), PcdStatus.WAIT_CLEAN_KEY, user,
                                         TransactionNames.LOGEVENT_KEY, null, comments);
            } else {
                transRrn = changePCDStatusByEvent(facilityRrn, user, pcdAll.getCarrierRrn(), ObjectList.CARRIER_KEY,
                                                  cstEventId, comments);
                this.updateCarrierStatus(pcdAll.getCarrierRrn(), targetStatus, user, null, transRrn, comments);
            }
        } else {
            if (StringUtils.equals(pcdCst.getCarrierStatus(), PcdStatus.WAIT_CLEAN_KEY)) {
                // 变更两次
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getCarrierRrn(), ObjectList.CARRIER_KEY,
                                       EventName.CST_WAIT_CLEAN_TO_FREE, comments);
                changePCDStatusByEvent(facilityRrn, user, pcdAll.getCarrierRrn(), ObjectList.CARRIER_KEY,
                                       EventName.CST_FREE_TO_WAIT_CLEAN, comments);

                this.updateCarrierStatus(pcdAll.getCarrierRrn(), PcdStatus.FREE_KEY, user,
                                         TransactionNames.LOGEVENT_KEY, null, comments);
                this.updateCarrierStatus(pcdAll.getCarrierRrn(), PcdStatus.WAIT_CLEAN_KEY, user,
                                         TransactionNames.LOGEVENT_KEY, null, comments);
            } else {
                transRrn = changePCDStatusByEvent(facilityRrn, user, pcdAll.getCarrierRrn(), ObjectList.CARRIER_KEY,
                                                  cstEventId, comments);
                this.updateCarrierStatus(pcdAll.getCarrierRrn(), targetStatus, user, null, transRrn, comments);
            }
        }
    }

    private boolean checkChamberAllInTheSameState(long parentRrn, List<Long> excludeChamberRrn, String state) {
        return statusDAO.checkChamberAllInTheSameState(parentRrn, excludeChamberRrn, state);
    }

    private String parseInputStatus(String inputStatus) {
        if (inputStatus.indexOf(">") != -1) {
            String[] inputStatusArray = StringUtils.split(inputStatus, ">");
            if (inputStatusArray != null && inputStatusArray.length > 1) {
                return inputStatusArray[inputStatusArray.length - 1];
            }
        } else {
            return inputStatus;
        }
        return StringUtils.EMPTY;
    }

    private void addReticleHAndEntityH(Reticle reticle) {
        entityManager.addEntityH(reticle.getTransRrn(), reticle.getInstanceRrn());
        reticleManager.addReticleH(reticle);
    }

    private Set<EntityStatus> getParentEntityStatusByChamberAllInTheSeamState(List<EntityStatus> entityStatuss,String state) {
        //这里要做及联更新的数据
        Set<EntityStatus> cascadeUpdateParentStatus = new HashSet<>();//set 去重复
        //判断集合中的多个属性
        for (EntityStatus entityStatus : entityStatuss) {
            //先判断当前状态是否要变更为 传入状态
            if (!StringUtils.equalsIgnoreCase(entityStatus.getCurrentStatus(),state)) {
                continue;
            }
            //判断当前entity 是否为chamber
            Entity currentEntity = entityManager.getEntity(entityStatus.getEntityRrn());
            //如果有pid 则表明是 chamber设备
            if (currentEntity == null) {//脏数据拦截
                continue;
            }
            if (currentEntity.getParentEntityRrn() == null || currentEntity.getParentEntityRrn() <= 0 ||
                    StringUtils.isEmpty(currentEntity.getChamberType())) {//非chamber设备
                continue;
            }
            Function<Entity, EntityStatus> createParentStatus = (entity) -> {
                List<EntityStatus> parentStatus = entityManager.getEntityStatuss(entity.getParentEntityRrn());
                if (CollectionUtils.isEmpty(parentStatus)) {//脏数据拦截
                    return null;
                }
                //详情参照LogEventSaveAction 128行
                EntityStatus status = parentStatus.get(parentStatus.size() - 1);
                //查出来居然没有rrn 需要手动回填
                status.setEntityRrn(entity.getParentEntityRrn());
                return status;
            };
            //兼容先后调用,例如:改子设备状态之前调用
            //根据主设备 查询 chamber 是否都为传入状态 ,并且排除当前chamber设备(备注:接下来要变更为传入状态的chamber)
            boolean isAllSeamState = this.checkChamberAllInTheSameState(currentEntity.getParentEntityRrn(),
                                                                        Arrays.asList(currentEntity.getInstanceRrn()),state);
            if (isAllSeamState) {
                EntityStatus parentStatus = createParentStatus.apply(currentEntity);
                if (parentStatus != null) {
                    cascadeUpdateParentStatus.add(parentStatus);
                }
            }
        }
        //将获取到 要更新的父设备已经加入本次更新的集合中
        return cascadeUpdateParentStatus;
    }
}