# 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;
        }
    }