# EdcSpcManagerImpl.java

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

    import com.fa.sesa.exception.Assert;
    import com.fa.sesa.exception.Errors;
    import com.fa.sesa.exception.SystemIllegalArgumentException;
    import com.fa.sesa.threadlocal.LocalContext;
    import com.mycim.framework.jdbc.Page;
    import com.mycim.framework.logging.Logger;
    import com.mycim.framework.logging.LoggerFactory;
    import com.mycim.framework.utils.beans.BeanUtils;
    import com.mycim.framework.utils.lang.StringUtils;
    import com.mycim.framework.utils.lang.collections.CollectionUtils;
    import com.mycim.framework.utils.lang.collections.MapUtils;
    import com.mycim.framework.utils.lang.math.NumberUtils;
    import com.mycim.framework.utils.lang.time.DateUtils;
    import com.mycim.framework.utils.msg.JsonUtils;
    import com.mycim.server.base.manager.NamedObjectManager;
    import com.mycim.server.base.manager.ObjectVersionManager;
    import com.mycim.server.base.manager.TransactionLogManager;
    import com.mycim.server.edc.manager.DataCollectionRuleManager;
    import com.mycim.server.edc.manager.EcnManager;
    import com.mycim.server.edc.manager.ParameterManager;
    import com.mycim.server.edc.manager.ParameterSetManager;
    import com.mycim.server.edcchart.dao.EdcSpcDAO;
    import com.mycim.server.edcchart.manager.EdcSpcManager;
    import com.mycim.server.edcchart.manager.EquipmentChartManager;
    import com.mycim.server.emas.manager.EmasEventManager;
    import com.mycim.server.emas.manager.EmasManager;
    import com.mycim.server.ems.manager.EntityManager;
    import com.mycim.server.ems.manager.EquipmentManager;
    import com.mycim.server.ocap.manager.OcapManager;
    import com.mycim.server.spc.Edc2SpcContainer;
    import com.mycim.server.spc.manager.SpcManager;
    import com.mycim.server.system.manager.ReferenceFileManager;
    import com.mycim.server.wip.manager.LotQueryManager;
    import com.mycim.server.wip.manager.OcapQueryManager;
    import com.mycim.server.wip.manager.UnitQueryManager;
    import com.mycim.utils.NonRTMathUtil;
    import com.mycim.valueobject.MessageIdList;
    import com.mycim.valueobject.ObjectList;
    import com.mycim.valueobject.automonitor.util.AutoMonitorUtils;
    import com.mycim.valueobject.bas.ObjectVersion;
    import com.mycim.valueobject.bas.TransactionLog;
    import com.mycim.valueobject.consts.ObjectStatus;
    import com.mycim.valueobject.consts.SpecifiedActionEnum;
    import com.mycim.valueobject.consts.TransactionNames;
    import com.mycim.valueobject.consts.VersionStatus;
    import com.mycim.valueobject.edcspc.*;
    import com.mycim.valueobject.edcspc.dto.nonrt.*;
    import com.mycim.valueobject.ems.Entity;
    import com.mycim.valueobject.ocap.dto.OcapChartInfoDTO;
    import com.mycim.valueobject.ocap.dto.OcapProcessingResultDTO;
    import com.mycim.valueobject.prp.Ecn;
    import com.mycim.valueobject.security.User;
    import com.mycim.valueobject.spc.RunCardRawDataInfo;
    import com.mycim.valueobject.sys.Facility;
    import com.mycim.valueobject.sys.ReferenceFileDetail;
    import com.mycim.valueobject.wip.Lot;
    import com.mycim.valueobject.wip.Unit;
    import com.mycim.webservice.nonrtservice.client.stub.NonRTUploadData;
    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.*;

    /**
     * @author zhi.cai
     * @version 6.0.0
     * @date 2019/12/14
     **/
    @Service
    @Transactional
    public class EdcSpcManagerImpl implements EdcSpcManager {

        private final Logger logger = LoggerFactory.getLogger(EdcSpcManagerImpl.class);

        @Autowired
        EdcSpcDAO edcSpcDAO;

        @Autowired
        EquipmentChartManager equipmentChartManager;

        @Autowired
        TransactionLogManager transactionLogManager;

        @Autowired
        ObjectVersionManager objectVersionManager;

        @Autowired
        NamedObjectManager namedObjectManager;

        @Autowired
        ParameterSetManager parameterSetManager;

        @Autowired
        EcnManager ecnManager;

        @Autowired
        SpcManager spcManager;

        @Autowired
        ParameterManager parameterManager;

        @Autowired
        LotQueryManager lotQueryManager;

        @Autowired
        DataCollectionRuleManager dataCollectionRuleManager;

        @Autowired
        UnitQueryManager unitQueryManager;

        @Autowired
        ReferenceFileManager referenceFileManager;

        @Autowired
        Edc2SpcContainer edc2SpcContainer;

        @Autowired
        EntityManager entityManager;

        @Autowired
        OcapManager ocapManager;

        @Autowired
        OcapQueryManager ocapQueryManager;

        @Autowired
        EdcSpcManager edcSpcManager;

        @Autowired
        EmasEventManager emasEventManager;

        @Autowired
        EmasManager emasManager;

        @Autowired
        EquipmentManager equipmentManager;

        @Override
        public Long insertNonRTUploadHistory(List<NonRTUploadDataInfo> list, String user) {
            TransactionLog transactionLog = transactionLogManager.startTransactionLog(user, TransactionNames.NON_RT_UPLOAD);
            edcSpcDAO.insertNonRTUploadHistory(list, transactionLog.getTransRrn());
            transactionLogManager.markTransactionLog(transactionLog);
            return transactionLog.getTransRrn();
        }

        @Override
        public List getActiveParameterSetVersion(long instanceRrn) {
            int activeVersion = 0;
            activeVersion = objectVersionManager.getActiveVersion(instanceRrn);
            edcSpcDAO.getActiveParameterSetVersion(instanceRrn, activeVersion);
            return null;
        }

        @Override
        public String getParameterSetUseForumla(long parameterSetRrn) {
            return edcSpcDAO.getParameterSetUseForumla(parameterSetRrn);
        }

        @Override
        public String getParameterSetMultiEqptMonitor(long parameterSetRrn) {
            return edcSpcDAO.getParameterSetMultiEqptMonitor(parameterSetRrn);
        }

        @Override
        public List<NonRTUploadDataInfo> getNonRTDataValues(String spcJobName, Long lotRrn, List<String> unitList) {
            return edcSpcDAO.getNonRTDataValues(spcJobName, lotRrn, unitList);
        }

        @Override
        public Page getNonRTUploadHistory(Page page) {
            return edcSpcDAO.getNonRTUploadHistory(page);
        }

        @Override
        public Page getEdcPlanImportHistory(Page page) {
            return edcSpcDAO.getEdcPlanImportHistory(page);
        }

        @Override
        public void insertEdcPlanImportHistory(List<EDCPlanExcelData> list, String impType) {
            TransactionLog transactionLog = transactionLogManager.startTransactionLog(LocalContext.getUserId(), impType);
            edcSpcDAO.insertEdcPlanImportHistory(list, transactionLog.getTransRrn());
            transactionLogManager.markTransactionLog(transactionLog);
        }

        @Override
        public void addEDCPlanByExcel(Map<String, List<ParameterSetVersion>> parameterSetList) {
            long facilityRrn = LocalContext.getFacilityRrn();
            String user = LocalContext.getUserId();

            long parameterSetRrn;
            long parameterRrn;
            String parameterId;
            ParameterSetVersion parameterSetVersion = new ParameterSetVersion();
            ObjectVersion ob;
            ParameterSet parameterSet;
            Parameter parameter;
            List<ParameterSetVersion> psvList;
            for (String parameterSetId : parameterSetList.keySet()) {// 获取所有导入的参数集Id

                psvList = parameterSetList.get(parameterSetId);
                // 参数集
                ParameterSet tempParamSet = new ParameterSet(parameterSetId, namedObjectManager.getNamedSpace(facilityRrn,
                                                                                                              ObjectList.PARAMETERSET_KEY),
                                                             ObjectList.PARAMETERSET_KEY);
                parameterSet = parameterSetManager.getParameterSet(tempParamSet);
                if (parameterSet == null || parameterSet.getInstanceRrn() <= 0) {// 新建parameterSet
                    parameterSet = buildParameterSetForInsert(parameterSetId);
                    parameterSet.setObjectType(psvList.iterator().next().getObjectType());
                    parameterSetManager.insertParameterSet(parameterSet);
                    parameterSet = parameterSetManager.getParameterSet(parameterSet);
                }
                parameterSetRrn = parameterSet.getInstanceRrn();
                ob = getNewestParameterSetVersion(parameterSet);
                parameterSetVersion.setInstanceRrn(parameterSetRrn);
                parameterSetVersion.setInstanceVersion(ob.getInstanceVersion());
                if (StringUtils.equalsIgnoreCase(ob.getVersionStatus(), ObjectStatus.UNFROZEN_KEY)) {
                    // 删除 样点 参数采集规则信息
                    this.deleteParameterSetVersion(parameterSetVersion.getInstanceRrn(),
                                                   parameterSetVersion.getInstanceVersion());
                }

                if (StringUtils.equalsIgnoreCase(ob.getVersionStatus(), ObjectStatus.ACTIVE_KEY)) {
                    // 直接升级版本
                    buildParameterSetVersion(parameterSet, ob.getInstanceVersion() + 1);
                    ob = getNewestParameterSetVersion(parameterSet);
                }

                parameterSetManager.activeParameterSetVersion(ob, user);

                parameterSetVersion.setInstanceVersion(ob.getInstanceVersion());
                parameterSetVersion.setVersionId(String.valueOf(ob.getInstanceVersion()));

                // 开始添加参数信息
                for (ParameterSetVersion tmp : psvList) {
                    parameterId = tmp.getParameterId();
                    Parameter tempParam = new Parameter();
                    tempParam.setInstanceRrn(namedObjectManager.getNamedObjectRrn(parameterId,
                                                                                  namedObjectManager.getNamedSpace(
                                                                                          facilityRrn,
                                                                                          ObjectList.PARAMETER_KEY),
                                                                                  ObjectList.PARAMETER_KEY));
                    parameter = parameterManager.getParameter(tempParam);

                    if (parameter == null || parameter.getInstanceRrn() <= 0) {// 新建parameter
                        parameter = buildParameterForInsert(parameterId);
                        parameter.setInstanceDesc(tmp.getParameterDesc());
                        parameter.setObjectType(tmp.getParameterType());
                        parameterManager.insertParameter(parameter);
                        parameter = parameterManager.getParameter(parameter);
                    }
                    parameterRrn = parameter.getInstanceRrn();

                    tmp.setInstanceRrn(parameterSetRrn);
                    tmp.setParameterRrn(parameterRrn);
                    tmp.setInstanceVersion(ob.getInstanceVersion());
                    parameterSetVersion.setParameterRrn(parameterRrn);
                    parameterSetVersion.setCollectionLevel(tmp.getCollectionLevel());
                    parameterSetVersion.setRuleType(tmp.getRuleType());
                    parameterSetVersion.setTransPerformedby(user);
                    parameterSetVersion.setEffectiveDateFrom(DateUtils.stringToTimestamp(DateUtils.formatDate(new Date())));
                    parameterSetVersion.setEffectiveDateTo(DateUtils.stringToTimestamp(getEffectiveDateTo()));
                    Double lowerLimit = tmp.getLowerSpecificationLimit();
                    Double upperLimit = tmp.getUpperSpecificationLimit();
                    if (StringUtils.isNotBlank(tmp.getLowerSpecificationLimitStr())) {
                        parameterSetVersion.setLowerSpecificationLimit(lowerLimit);
                    }
                    if (StringUtils.isNotBlank(tmp.getUpperSpecificationLimitStr())) {
                        parameterSetVersion.setUpperSpecificationLimit(upperLimit);
                    }
                    parameterSetVersion.setCheckLowerLimitFlag(lowerLimit == 0 || lowerLimit == null ? "0" : "1");
                    parameterSetVersion.setCheckUpperLimitFlag(upperLimit == 0 || upperLimit == null ? "0" : "1");
                    parameterSetVersion.setOptionalFlag(tmp.getOptionalFlag());

                    // 绑定到参数集
                    // 绑定参数集、参数、规则关系到DATA_COLLECTION_RULE表中
                    //parameterSetManager.addParameterToSet(parameterSetVersion);
                    handleEdcPlanRelation(parameterSetVersion, parameterRrn);
                }
            }
        }

        @Override
        public void addEDCPlanByExcel(String parameterSetId, List<ParameterSetVersion> versionList) {
            long facilityRrn = LocalContext.getFacilityRrn();
            String user = LocalContext.getUserId();

            long parameterRrn;
            ParameterSetVersion parameterSetVersion = new ParameterSetVersion();
            String parameterId;
            Parameter parameter;
            boolean newParameterFlag = false;

            ParameterSet tempParamSet = new ParameterSet(parameterSetId, namedObjectManager.getNamedSpace(facilityRrn,
                                                                                                          ObjectList.PARAMETERSET_KEY),
                                                         ObjectList.PARAMETERSET_KEY);
            ParameterSet parameterSet = parameterSetManager.getParameterSet(tempParamSet);
            if (parameterSet == null || parameterSet.getInstanceRrn() <= 0) {// 新建parameterSet
                parameterSet = buildParameterSetForInsert(parameterSetId);
                parameterSet.setObjectType(versionList.iterator().next().getObjectType());
                parameterSetManager.insertParameterSet(parameterSet);
                parameterSet = parameterSetManager.getParameterSet(parameterSet);
            }
            long parameterSetRrn = parameterSet.getInstanceRrn();
            ObjectVersion ob = getNewestParameterSetVersion(parameterSet);
            parameterSetVersion.setInstanceRrn(parameterSetRrn);
            parameterSetVersion.setInstanceVersion(ob.getInstanceVersion());
            if (StringUtils.equalsIgnoreCase(ob.getVersionStatus(), ObjectStatus.UNFROZEN_KEY)) {
                // 删除 样点 参数采集规则信息
                this.deleteParameterSetVersion(parameterSetVersion.getInstanceRrn(),
                                               parameterSetVersion.getInstanceVersion());
            }

            if (StringUtils.equalsIgnoreCase(ob.getVersionStatus(), ObjectStatus.ACTIVE_KEY)) {
                // 直接升级版本
                buildParameterSetVersion(parameterSet, ob.getInstanceVersion() + 1);
                ob = getNewestParameterSetVersion(parameterSet);
            }

            parameterSetManager.activeParameterSetVersion(ob, user);

            parameterSetVersion.setInstanceVersion(ob.getInstanceVersion());
            parameterSetVersion.setVersionId(String.valueOf(ob.getInstanceVersion()));

            // 开始添加参数信息
            for (ParameterSetVersion tmp : versionList) {
                parameterId = tmp.getParameterId();
                Parameter tempParam = new Parameter();
                tempParam.setInstanceRrn(namedObjectManager.getNamedObjectRrn(parameterId,
                                                                              namedObjectManager.getNamedSpace(facilityRrn,
                                                                                                               ObjectList.PARAMETER_KEY),
                                                                              ObjectList.PARAMETER_KEY));
                parameter = parameterManager.getParameter(tempParam);

                if (parameter == null || parameter.getInstanceRrn() <= 0) {// 新建parameter
                    parameter = buildParameterForInsert(parameterId);
                    parameter.setInstanceDesc(tmp.getParameterDesc());
                    parameter.setObjectType(tmp.getParameterType());
                    parameterManager.insertParameter(parameter);
                    parameter = parameterManager.getParameter(parameter);
                    newParameterFlag = true;
                }
                parameterRrn = parameter.getInstanceRrn();

                tmp.setInstanceRrn(parameterSetRrn);
                tmp.setParameterRrn(parameterRrn);
                tmp.setInstanceVersion(ob.getInstanceVersion());
                parameterSetVersion.setParameterRrn(parameterRrn);
                parameterSetVersion.setCollectionLevel(tmp.getCollectionLevel());
                parameterSetVersion.setRuleType(tmp.getRuleType());
                parameterSetVersion.setTransPerformedby(user);
                parameterSetVersion.setEffectiveDateFrom(DateUtils.stringToTimestamp(DateUtils.formatDate(new Date())));
                parameterSetVersion.setEffectiveDateTo(DateUtils.stringToTimestamp(getEffectiveDateTo()));
                Double lowerLimit = tmp.getLowerSpecificationLimit();
                Double upperLimit = tmp.getUpperSpecificationLimit();
                if (StringUtils.isNotBlank(tmp.getLowerSpecificationLimitStr())) {
                    parameterSetVersion.setLowerSpecificationLimit(lowerLimit);
                }
                if (StringUtils.isNotBlank(tmp.getUpperSpecificationLimitStr())) {
                    parameterSetVersion.setUpperSpecificationLimit(upperLimit);
                }
                parameterSetVersion.setCheckLowerLimitFlag(lowerLimit == 0 || lowerLimit == null ? "0" : "1");
                parameterSetVersion.setCheckUpperLimitFlag(upperLimit == 0 || upperLimit == null ? "0" : "1");
                parameterSetVersion.setOptionalFlag(tmp.getOptionalFlag());

                // 绑定到参数集
                // 绑定参数集、参数、规则关系到DATA_COLLECTION_RULE表中
                //parameterSetManager.addParameterToSet(parameterSetVersion);
                handleEdcPlanRelation(parameterSetVersion, parameterRrn);
            }

        }

        @Override
        public void addParameterByExcel(List<Parameter> parameterList) {
            String user = LocalContext.getUserId();

            for (Parameter parameter : parameterList) {
                if (parameter.getInstanceRrn() <= 0) {// 新建parameter
                    String dataType = "VARIABLE";
                    parameter.setTransPerformedby(user);
                    parameter.setDataType(dataType);
                    parameterManager.insertParameter(parameter);
                    parameter = parameterManager.getParameter(parameter);
                } else {
                    // 修改 parameter参数
                    String cpPara = parameter.getCpPara();
                    String keyChartFlag = parameter.getKeyChartFlag();
                    Integer sampleNum = parameter.getSampleNum();
                    String parameterUnit = parameter.getParameterUnit();
                    String actionPoint = parameter.getActionPoint();
                    parameter = parameterManager.getParameter(parameter);
                    //if (!StringUtils.equals(parameter.getCpPara(), cpPara) || !StringUtils.equals(
                    //        parameter.getKeyChartFlag(), keyChartFlag)) {
                    parameter.setCpPara(cpPara);
                    parameter.setKeyChartFlag(keyChartFlag);
                    parameter.setSampleNum(sampleNum);
                    parameter.setParameterUnit(parameterUnit);
                    parameter.setActionPoint(actionPoint);
                    parameterManager.updateParameter(parameter);
                    //}
                    dataCollectionRuleManager.deleteDataCollectionRuleForAll(0L, 0, parameter.getInstanceRrn());
                    parameterSetManager.deleteReadingPromptsForParameterAll(0L, 0, parameter.getInstanceRrn());
                }

                Collection<DataCollectionRule> rules = parameter.getCollectionRules();
                int i = 0;

                for (DataCollectionRule rule : rules) {
                    rule.setParameterSetRrn(0L);
                    rule.setParameterSetVersion(0);
                    rule.setParameterRrn(parameter.getInstanceRrn());
                    rule.setCollectionRuleSequence(++i);
                    dataCollectionRuleManager.insertDataCollectionRule(rule);
                }

                Collection readings = parameter.getReadingPrompts();
                i = 0;
                for (Object obj : readings) {
                    ReadingPrompts reading = (ReadingPrompts) obj;
                    reading.setParameterSetRrn(0L);
                    reading.setParameterSetVersion(0L);
                    reading.setParameterRrn(parameter.getInstanceRrn());
                    reading.setReadingSequence(++i);
                    parameterManager.insertReadingPrompt(reading);
                }
            }
        }

        @Override
        public List<RunCardRawDataInfo> getRunCardRawDataInfoList(Long lotRrn, Long stepSequence) {
            return edcSpcDAO.getRunCardRawDataInfoList(lotRrn, stepSequence);
        }

        @Override
        public void insertSrcSampleRawdata(List<RunCardRawDataInfo> rawDataInfoList) {
            edcSpcDAO.insertSrcSampleRawdata(rawDataInfoList);
        }

        @Override
        public void handleEdcPlanRelation(ParameterSetVersion parameterSetVersion, long parameterRrn) {
            parameterSetManager.addParameterToSet(parameterSetVersion);
            List<DataCollectionRule> dataCollectionRules = dataCollectionRuleManager.getDataCollectionRules(parameterRrn);
            int i = 0;
            for (DataCollectionRule rule : dataCollectionRules) {
                rule.setParameterSetRrn(parameterSetVersion.getInstanceRrn());
                rule.setParameterSetVersion(parameterSetVersion.getInstanceVersion());
                rule.setParameterRrn(parameterSetVersion.getParameterRrn());
                rule.setCollectionRuleSequence(++i);
                dataCollectionRuleManager.insertDataCollectionRule(rule);
            }

        }

        @Override
        public NonRTReturnInfoDTO importUploadData(List<NonRTUploadDTO> uploadDataInfos, Facility facility, User user,
                                                   String importType, Map dataInfo) {
            boolean isOcapSend = StringUtils.isNotBlank(MapUtils.getStringCheckNull(dataInfo, "ocapId"));
            NonRTReturnInfoDTO returnInfo = importUploadData(uploadDataInfos, facility, user, importType, isOcapSend);

            boolean needHold = NonRTMathUtil.isNeedHoldEqptImportType(importType) ||
                    checkAutoMoitorTypeNeedCreateOcap(importType, dataInfo, returnInfo);

            if (needHold && !isOcapSend) {
                if (returnInfo.getUploadSpc() && returnInfo.getHadViolation()) {
                    for (Long eqptRrn : returnInfo.getVioEqptRrnList()) {
                        entityManager.logEventToWaitEng(facility.getInstanceRrn(), user.getInstanceId(), eqptRrn,
                                                        "NonRT value out of range");
                    }
                }
                if (!checkOcapIsAlreadyExists(returnInfo)) {
                    // ocap 处理
                    if (MapUtils.isNotEmpty(returnInfo.getVioInfos())) {
                        Long measuringEqptRrn = MapUtils.getLong(dataInfo, "edcEqptRrn", 0L);
                        String measuringEqptId = MapUtils.getString(dataInfo, "edcEqptId", "");
                        List<OcapProcessingResultDTO> ocaplist = ocapManager.createOcapByOffLine(facility.getInstanceRrn(),
                                                                                                 user.getInstanceRrn(),
                                                                                                 user.getInstanceId(),
                                                                                                 returnInfo.getTransRrn(),
                                                                                                 returnInfo.getVioInfos(),
                                                                                                 measuringEqptId,
                                                                                                 measuringEqptRrn);
                        if (CollectionUtils.isNotEmpty(ocaplist)) {
                            insertOcapChartInfo(facility.getInstanceRrn(), user.getInstanceId(), returnInfo, ocaplist);
                        }
                    }
                }
            } else if (isOcapSend) {
                String offlineFlag = MapUtils.getString(dataInfo, "offlineFlag");
                String remark = StringUtils.EMPTY;
                if (StringUtils.equals(offlineFlag, SpecifiedActionEnum.RE_KEYIN_DATA.toString())) {
                    remark = "offline Re-key-in upload data";
                } else if (StringUtils.equals(offlineFlag, SpecifiedActionEnum.REMEASURE.toString())) {
                    remark = "offline Re-measure upload data";
                }
                Long ocapRrn = MapUtils.getLongValue(dataInfo, "ocapRrn");
                String ocapId = MapUtils.getStringCheckNull(dataInfo, "ocapId");
                if (returnInfo.getUploadDetails().size() > 0) {
                    if (!returnInfo.getHadViolation()) { // 上传成功
                        insertNonRTUploadHistory(returnInfo.getUploadDetails(), user, StringUtils.EMPTY);
                    } else {// 返回 OOS或OOC
                        insertNonRTUploadHistory(returnInfo.getUploadDetails(), user, ocapId);
                    }
                }
                ocapManager.handleOcapSend(facility, user, ocapRrn, returnInfo.getHadViolation(), remark);
            }
            return returnInfo;
        }

        @Override
        public void handleEdcPlanByChart(List<Parameter> parameterList, List<EDCPlanExcelData> list, String impType) {
            edcSpcManager.addParameterByExcel(parameterList);

            edcSpcManager.insertEdcPlanImportHistory(list, impType);
        }

        @Override
        public void handleEdcPlanByExcel(Map<String, List<ParameterSetVersion>> parameterSetList,
                                         List<EDCPlanExcelData> list, String impType) {
            edcSpcManager.addEDCPlanByExcel(parameterSetList);

            edcSpcManager.insertEdcPlanImportHistory(list, impType);
        }

        @Override
        public void handleEdcPlanByExcel(String parameterSetId, List<ParameterSetVersion> versionList,
                                         EDCPlanExcelData data, String impType) {
            edcSpcManager.addEDCPlanByExcel(parameterSetId, versionList);
            edcSpcManager.insertEdcPlanImportHistory(Collections.singletonList(data), impType);
        }

        @Override
        public String queryOfflineUnitList(String jobId, String lotId, String ocapId) {
            return edcSpcDAO.queryOfflineUnitList(jobId, lotId, ocapId);
        }

        @Override
        public NonRTUploadCheckResult impNonRTUploadData(NonRTUploadDataInfo reqData, String userId) {
            NonRTUploadData data = new NonRTUploadData();
            BeanUtils.copyProperties(reqData, data);
            NonRTUploadCheckResult result = edc2SpcContainer.impNonRTUploadData(data, userId);
            equipmentChartManager.updateLastUploadTimestampWhenUpload(userId, reqData.getEqptRrn(), reqData.getJobId());
            emasManager.updateEmasChartLastUpLoadTime(reqData.getEqptRrn(), reqData.getJobName());
            return result;
        }

        @Override
        public List<Map> getMainEqpNonRTJobList(Long eqptRrn) {
            List<String> jobIds = new ArrayList<>();
            List<Map> jobList = new ArrayList<>();

            String eqptId = namedObjectManager.getInstanceId(eqptRrn);
            String spcResult = edc2SpcContainer.getNonRTJob(eqptId);
            List<Map> nonRTJobList = JsonUtils.toList(spcResult, Map.class);
            jobList.addAll(buildJobList(jobIds, nonRTJobList, eqptId, eqptRrn));

            List<Entity> childEqptList = equipmentManager.getChildChamberEquip(eqptRrn);
            for (Entity entity : childEqptList) {
                String childSpcResult = edc2SpcContainer.getNonRTJob(entity.getInstanceId());
                if (StringUtils.isBlank(childSpcResult)) {
                    continue;
                }
                List<Map> childNonRTJobList = JsonUtils.toList(childSpcResult, Map.class);
                jobList.addAll(buildJobList(jobIds, childNonRTJobList, entity.getInstanceId(), entity.getInstanceRrn()));
            }
            return jobList;
        }

        public Timestamp timestampPlusHours(Timestamp timestamp, Float hours) {
            if (timestamp == null) {
                return null;
            }
            if (hours == null) {
                return timestamp;
            }
            return new Timestamp(timestamp.getTime() + (long) (hours * 60 * 60 * 1000));
        }

        private boolean checkOcapIsAlreadyExists(NonRTReturnInfoDTO returnInfo) {
            List<Map<String, Object>> ocapChartInfos = returnInfo.getOcapChartInfos();

            if (Objects.isNull(ocapChartInfos)) {
                return true;
            }

            for (Map<String, Object> ocapChartInfo : ocapChartInfos) {
                String jobName = MapUtils.getString(ocapChartInfo, "jobName");
                Long eqptRrn = MapUtils.getLong(ocapChartInfo, "eqptRrn");
                String ocapId = ocapQueryManager.getActiveOfflineOcapId(eqptRrn, jobName);

                if (StringUtils.isNotBlank(ocapId)) {
                    return true;
                }
            }
            return false;
        }

        private boolean checkAutoMoitorTypeNeedCreateOcap(String importType, Map ocapinfo, NonRTReturnInfoDTO returnInfo) {
            if (StringUtils.equals(NonRTMathUtil.NONRT_IMPORT_TYPE_AUTO_MONITOR, importType)) {
                String eqptType = MapUtils.getString(ocapinfo, "eqptType");
                if (AutoMonitorUtils.checkStepIsPreEdcStep(eqptType)) {
                    return false;
                }

                if (checkOcapIsAlreadyExists(returnInfo)) {
                    return false;
                }
            }
            return true;
        }

        private List<Map> buildJobList(List<String> jobIds, List<Map> nonRTJobList, String eqptId, Long eqptRrn) {
            List<Map> jobList = new ArrayList<>();
            for (Map nonRTJob : nonRTJobList) {
                String jobId = MapUtils.getString(nonRTJob, "JobID");
                String formula = MapUtils.getString(nonRTJob, "Formula");

                if (!jobIds.contains(jobId)) {
                    jobIds.add(jobId);
                    if (NonRTMathUtil.isBasicFormula(formula)) {
                        nonRTJob.put("eqptId", eqptId);
                        nonRTJob.put("eqptRrn", eqptRrn);
                        jobList.add(nonRTJob);
                    }
                }
            }
            return jobList;
        }

        private long insertNonRTUploadHistory(List<NonRTUploadDetailDTO> uploadDetails, User user, String ocapId) {
            TransactionLog transactionLog = transactionLogManager.startTransactionLog(user.getInstanceId(),
                                                                                      TransactionNames.NON_RT_UPLOAD_WITH_OCAP);
            edcSpcDAO.insertNonRTUploadHistory(uploadDetails, transactionLog.getTransRrn(), ocapId);
            transactionLogManager.markTransactionLog(transactionLog);
            return transactionLog.getTransRrn();
        }

        private NonRTReturnInfoDTO importUploadData(List<NonRTUploadDTO> uploadDataInfos, Facility facility, User user,
                                                    String importType, boolean isOcapSend) {
            List<NonRTUploadDataInfo> saveList = new ArrayList<NonRTUploadDataInfo>();
            List<NonRTUploadDataInfo> postList = new ArrayList<NonRTUploadDataInfo>();
            for (NonRTUploadDTO uploadDataInfoDTO : uploadDataInfos) {
                NonRTUploadDataInfo baseInfo = buildUploadDataBaseInfo(facility, user, importType, uploadDataInfoDTO);

                String lotId = uploadDataInfoDTO.getJobBaseInfo().getLotId();
                Lot lot = lotQueryManager.getLot(lotId, facility.getInstanceRrn());
                Assert.isFalse(StringUtils.isNotBlank(lotId) && lot.getLotRrn() <= 0,
                               Errors.create().content("Incorrect lot information!").build());

                for (NonRTUnitInfoDTO unitInfo : uploadDataInfoDTO.getUnitList()) {
                    Assert.isFalse(unitInfo.getValueList() == null || unitInfo.getValueList().length !=
                                           uploadDataInfoDTO.getJobBaseInfo().getSubgroupSize(),
                                   Errors.create().content("Value list size unequal the subgroup size!").build());

                    NonRTUploadDataInfo dataValueInfo = buildUploadDataValueInfo(lot, baseInfo, unitInfo);
                    saveList.add(dataValueInfo);

                    if (StringUtils.equalsIgnoreCase(NonRTMathUtil.NONRT_FORMULA_POST_KEY, baseInfo.getValueType())) {
                        postList.add(dataValueInfo);
                    }
                }
            }

            List<NonRTUploadDataInfo> uploadDataList = new ArrayList<NonRTUploadDataInfo>();
            if (postList.size() > 0) {
                preAndDeriveChartDataHandle(facility, importType, saveList, postList, uploadDataList);
            }

            // vio flag
            boolean hadViolation = false;
            List<String> violitionIds = new ArrayList<String>();
            List<Long> vioEqptRrns = new ArrayList<>();

            // ocap info
            Map<NonRTUploadDataInfo, NonRTUploadCheckResult> nonRTDataInfos = new HashMap<>();
            List<NonRTUploadDetailDTO> detailDTOList = new ArrayList<>();
            List<Map<String, Object>> ocapChartInfoList = new ArrayList<>();

            // upload data
            for (NonRTUploadDataInfo uploadDataInfo : uploadDataList) {
                String lotId = uploadDataInfo.getLotId();
                Lot tempLot = lotQueryManager.getLot(lotId, LocalContext.getFacilityRrn());
                if (tempLot != null && tempLot.getLotRrn() > 0) {
                    uploadDataInfo.setProcessId(tempLot.getProcessId());
                }
                NonRTUploadCheckResult result = impNonRTUploadData(uploadDataInfo, user.getInstanceId());

                if (validateSpcResultsHadViolate(result, uploadDataInfo, saveList, nonRTDataInfos)) {
                    hadViolation = true;
                }

                Map<String, Object> jobInfoMap = new HashMap<String, Object>();
                jobInfoMap.put("jobId", uploadDataInfo.getJobId());
                jobInfoMap.put("jobName", uploadDataInfo.getJobName());
                jobInfoMap.put("url", result.getUrl());
                jobInfoMap.put("eqptRrn", uploadDataInfo.getEqptRrn());

                ocapChartInfoList.add(jobInfoMap);
                detailDTOList.add(new NonRTUploadDetailDTO(uploadDataInfo, result));

                if (hadViolation && (!violitionIds.contains(uploadDataInfo.getLotId()))) {
                    violitionIds.add(uploadDataInfo.getLotId());
                }
                if (hadViolation && (!vioEqptRrns.contains(uploadDataInfo.getEqptRrn()))) {
                    vioEqptRrns.add(uploadDataInfo.getEqptRrn());
                }

            }

            // build return info
            NonRTReturnInfoDTO returnInfo = new NonRTReturnInfoDTO();

            if (saveList.size() > 0 && !isOcapSend) {
                returnInfo.setTransRrn(insertNonRTUploadHistory(saveList, user.getInstanceId()));
            }

            if (uploadDataList.size() > 0) {
                returnInfo.setUploadSpc(true);
                returnInfo.setHadViolation(hadViolation);

                returnInfo.setVioLotIds(violitionIds);
                returnInfo.setVioEqptRrnList(vioEqptRrns);
                returnInfo.setVioInfos(nonRTDataInfos);

                returnInfo.setUploadDetails(detailDTOList);
                returnInfo.setOcapChartInfos(ocapChartInfoList);

                // 对 list 根据 eqpId 以及 jobName 进行去重,保证相同 eqpId、jobName、checkType只close一条
                Set<NonRTUploadDetailDTO> set = new TreeSet<>(new Comparator<NonRTUploadDetailDTO>() {
                    @Override
                    public int compare(NonRTUploadDetailDTO n1, NonRTUploadDetailDTO n2) {
                        int compareToResult = 1;//==0表示重复
                        if(StringUtils.equals(n1.getUploadData().getEqptId(), n2.getUploadData().getEqptId()) &&
                                StringUtils.equals(n1.getUploadData().getJobName(), n2.getUploadData().getJobName())) {
                            compareToResult = 0;
                        }
                        return compareToResult;
                    }
                });
                set.addAll(detailDTOList);
                List<NonRTUploadDetailDTO> nonRTUploadDetailDTOS = new ArrayList<>(set);
                // new Emas 处理 去重后的数据
                for (NonRTUploadDetailDTO detailDTO : nonRTUploadDetailDTOS) {
                    String eqpId = detailDTO.getUploadData().getEqptId();
                    String chartId = detailDTO.getUploadData().getJobName();
                    emasEventManager.closeEmasEvent(eqpId, chartId);
                }
            }
            return returnInfo;
        }

        private void preAndDeriveChartDataHandle(Facility facility, String importType, List<NonRTUploadDataInfo> saveList,
                                                 List<NonRTUploadDataInfo> postList,
                                                 List<NonRTUploadDataInfo> uploadDataList) {
            for (NonRTUploadDataInfo postInfo : postList) {
                NonRTUploadDataInfo uploadDataInfo = new NonRTUploadDataInfo();
                BeanUtils.copyProperties(postInfo, uploadDataInfo);

                if (NonRTMathUtil.isNeedPreValue(uploadDataInfo.getFormulaType())) {

                    NonRTUploadDataInfo preInfo = getPreDataInfoByPostInfo(importType, saveList, uploadDataInfo);

                    Assert.isFalse(preInfo == null, Errors.create().content(
                                                                  "The NonRT chart:{} wafer:{} need pre value," + "please"
                                                                          + " check the transData or history")
                                                          .args(uploadDataInfo.getJobName(), uploadDataInfo.getUnitId())
                                                          .build());

                    double[] values = new double[uploadDataInfo.getValueList().length];
                    for (int i = 0; i < values.length; i++) {
                        double pre = preInfo.getValueList()[i];
                        double post = postInfo.getValueList()[i];
                        String time = uploadDataInfo.getFormulaPara();
                        String formulaType = uploadDataInfo.getFormulaType();
                        double value = formatDataValue(NonRTMathUtil.mathDataValue(formulaType, pre, post, time),
                                                       facility.getInstanceRrn());
                        if (StringUtils.contains(formulaType, "C") && value < 0) {
                            value = 0;
                        }
                        values[i] = value;
                    }

                    uploadDataInfo.setValueList(values);
                } else {
                    for (int i = 0; i < uploadDataInfo.getValueList().length; i++) {
                        uploadDataInfo.getValueList()[i] = formatDataValue(uploadDataInfo.getValueList()[i],
                                                                           facility.getInstanceRrn());
                    }
                }

                uploadDataList.add(uploadDataInfo);

                if (NonRTMathUtil.isNeedDeriveChart(uploadDataInfo.getFormulaType())) {
                    String deriveFormulaType = StringUtils.split(uploadDataInfo.getFormulaType(), ",")[1];
                    if (NonRTMathUtil.isAvaliableFormula(deriveFormulaType)) {
                        NonRTUploadDataInfo deriveDataInfo = buildDeriveChartUploadInfo(facility, uploadDataInfo,
                                                                                        deriveFormulaType);
                        saveList.add(deriveDataInfo);
                        uploadDataList.add(deriveDataInfo);
                    }
                }
            }
        }

        private void insertOcapChartInfo(Long facilityRrn, String userId, NonRTReturnInfoDTO returnDTO,
                                         List<OcapProcessingResultDTO> ocaplist) {
            for (OcapProcessingResultDTO ocapDTO : ocaplist) {
                String jobId = "";
                String jobName = "";
                String url = "";

                for (NonRTUploadDetailDTO detail : returnDTO.getUploadDetails()) {
                    if (StringUtils.isEmpty(detail.getUploadData().getViolationInfo())) {
                        continue;
                    }
                    if (StringUtils.equals(ocapDTO.getChartName(), detail.getUploadData().getJobName())) {
                        jobId = detail.getUploadData().getJobId();
                        jobName = detail.getUploadData().getJobName();
                        url = detail.getResultInfo().getUrl();
                        if (ocapDTO.getCreationFlag()) {
                            StringBuilder msg = new StringBuilder(detail.getUploadData().getViolationInfo());
                            msg.append(":" + ocapDTO.getOcapId());
                            detail.getUploadData().setViolationInfo(msg.toString());
                        }
                        break;
                    }
                }

                String newOcapId = ocapDTO.getOcapId();
                // 在NON_RT_DATA_HISTORY的数据上标识ocap_Id
                updateNonRTUploadHistoryWithOcapId(newOcapId, userId, returnDTO.getTransRrn());

                // 记录chart info
                Long planRrn = ocapQueryManager.getOcapCardRrnByUniqueKey(facilityRrn, newOcapId, null);
                OcapChartInfoDTO dto = new OcapChartInfoDTO(planRrn, jobId, jobName, url);

                ocapManager.insertOcapChartInfo(dto);
            }
        }

        private void updateNonRTUploadHistoryWithOcapId(String newOcapId, String userId, Long transRrn) {
            TransactionLog transactionLog = transactionLogManager.startTransactionLog(userId,
                                                                                      TransactionNames.NON_RT_UPLOAD_UPDATE);
            edcSpcDAO.updateNonRTUploadHistoryWithOcapId(newOcapId, transRrn);
            transactionLogManager.markTransactionLog(transactionLog);
        }

        private boolean validateSpcResultsHadViolate(NonRTUploadCheckResult result, NonRTUploadDataInfo valueInfo,
                                                     List<NonRTUploadDataInfo> saveList,
                                                     Map<NonRTUploadDataInfo, NonRTUploadCheckResult> nonRTDataInfos) {
            boolean hadViolation = false;
            if (result != null) {
                Assert.isFalse(StringUtils.equalsIgnoreCase("1", result.getReturnCode()),
                               Errors.create().content(result.getReturnMessage()).build());

                String rm = result.getReturnMessage();
                if (StringUtils.contains(result.getReturnMessage(), "Violate Rule")) {
                    String violate = rm.substring(StringUtils.indexOf(rm, "Violate Rule") + "Violate Rule".length() + 1,
                                                  StringUtils.indexOf(rm, "||", StringUtils.indexOf(rm, "Violate Rule")));

                    hadViolation = true;
                    for (NonRTUploadDataInfo saveInfo : saveList) {
                        if (StringUtils.equalsIgnoreCase(saveInfo.getJobId(), valueInfo.getJobId()) &&
                                StringUtils.equalsIgnoreCase(saveInfo.getLotId(), valueInfo.getLotId()) &&
                                StringUtils.equalsIgnoreCase(saveInfo.getUnitId(), valueInfo.getUnitId())) {
                            saveInfo.setViolationInfo(violate);
                            valueInfo.setViolationInfo(violate);
                            result.setHoldFlag(true);
                            nonRTDataInfos.put(saveInfo, result);
                        }
                    }
                }
            }
            return hadViolation;
        }

        private double formatDataValue(double value, long facilityRrn) {

            // 查询上下限值
            List<ReferenceFileDetail> refFileValues = referenceFileManager.getRefFileValues("$$EDC_DATAVALUE_LIMIT",
                                                                                            namedObjectManager.getNamedSpace(
                                                                                                    facilityRrn,
                                                                                                    ObjectList.REFERENCE_FILE_KEY));

            double upperLimit = 0.0;
            double lowerLimit = 0.0;
            boolean checkUpperFLag = false;
            boolean checkLowerFLag = false;
            if (CollectionUtils.isNotEmpty(refFileValues)) {
                for (Iterator<ReferenceFileDetail> it = refFileValues.iterator(); it.hasNext(); ) {
                    ReferenceFileDetail ref = it.next();
                    if (StringUtils.isNotBlank(ref.getData1Value()) && NumberUtils.isNumber(ref.getData1Value()) &&
                            StringUtils.equals(ref.getKey1Value(), "LOWER LIMIT VALUE")) {
                        lowerLimit = NumberUtils.toDouble(ref.getData1Value(), lowerLimit);
                        checkLowerFLag = true;
                        continue;
                    } else if (StringUtils.isNotBlank(ref.getData1Value()) && NumberUtils.isNumber(ref.getData1Value()) &&
                            StringUtils.equals(ref.getKey1Value(), "UPPER LIMIT VALUE")) {
                        upperLimit = NumberUtils.toDouble(ref.getData1Value(), upperLimit);
                        checkUpperFLag = true;
                    }
                }

                /**
                 * 判断dataValue是否大于上限upperLimit或者小于下限lowerLimit
                 */
                if (checkUpperFLag && value >= upperLimit) {
                    value = upperLimit;
                } else if (checkLowerFLag && value <= lowerLimit) {
                    value = lowerLimit;
                }
            }

            if (new Double(value).toString().length() > 15) {
                value = NumberUtils.toDouble(StringUtils.substring(new Double(value).toString(), 0, 15));
            }

            return value;
        }

        private NonRTUploadDataInfo buildDeriveChartUploadInfo(Facility facility, NonRTUploadDataInfo uploadDataInfo,
                                                               String deriveFormulaType) {
            NonRTUploadDataInfo deriveInfo = new NonRTUploadDataInfo();
            BeanUtils.copyProperties(uploadDataInfo, deriveInfo);

            deriveInfo.setJobId(deriveInfo.getDeriveJobId());
            deriveInfo.setJobName(deriveInfo.getDeriveJobName());
            deriveInfo.setNonRTKey(deriveInfo.getDeriveNonRTKey());
            deriveInfo.setValueType("DERIVE");

            double value = formatDataValue(NonRTMathUtil.mathDataValue(deriveFormulaType, uploadDataInfo.getValueList()),
                                           facility.getInstanceRrn());
            deriveInfo.setValueList(new double[]{value});
            deriveInfo.setFormula(NonRTMathUtil.getNonRTFormula(deriveFormulaType));
            deriveInfo.setFormulaType(deriveFormulaType);

            return deriveInfo;
        }

        private NonRTUploadDataInfo getPreDataInfoByPostInfo(String importType, List<NonRTUploadDataInfo> saveList,
                                                             NonRTUploadDataInfo postInfo) {
            NonRTUploadDataInfo preInfo = null;
            for (NonRTUploadDataInfo saveInfo : saveList) {
                if (StringUtils.equalsIgnoreCase(saveInfo.getJobId(), postInfo.getJobId()) &&
                        StringUtils.equalsIgnoreCase(saveInfo.getLotId(), postInfo.getLotId()) &&
                        StringUtils.equalsIgnoreCase(saveInfo.getUnitId(), postInfo.getUnitId()) &&
                        StringUtils.equalsIgnoreCase(NonRTMathUtil.NONRT_FORMULA_PRE_KEY, saveInfo.getValueType())) {
                    preInfo = saveInfo;
                    break;
                }
            }

            if (preInfo == null) {
                List<String> unitList = new ArrayList<String>();
                unitList.add(postInfo.getUnitId());
                List<NonRTUploadDataInfo> list = getNonRTDataValues(postInfo.getJobName(), postInfo.getLotRrn(), unitList);
                for (NonRTUploadDataInfo dataInfo : list) {
                    if (StringUtils.equalsIgnoreCase(NonRTMathUtil.NONRT_FORMULA_PRE_KEY, dataInfo.getValueType())) {
                        preInfo = dataInfo;
                        preInfo.setImportType(importType);
                        saveList.add(preInfo);
                        break;
                    }
                }
            }
            return preInfo;
        }

        private NonRTUploadDataInfo buildUploadDataValueInfo(Lot lot, NonRTUploadDataInfo baseInfo,
                                                             NonRTUnitInfoDTO unitInfo) {
            NonRTUploadDataInfo valueInfo = new NonRTUploadDataInfo();
            BeanUtils.copyProperties(baseInfo, valueInfo);

            if (lot != null && lot.getLotRrn() > 0) {
                Assert.isTrue(StringUtils.equalsIgnoreCase("C", lot.getCreateCategory()),
                              Errors.create().content("Error Lot Type").build());

                valueInfo.setLotId(lot.getLotId());
                valueInfo.setLotRrn(lot.getLotRrn());

                Unit unit = unitQueryManager.getUnit(lot.getFacilityRrn(), unitInfo.getUnitId());
                Assert.isFalse(unit == null || unit.getUnitRrn() <= 0,
                               Errors.create().content("Incorrect unit information!").build());
                valueInfo.setUnitId(unitInfo.getUnitId());
                valueInfo.setUnitRrn(unit.getUnitRrn());

                valueInfo.setPro1(lot.getLotId());
                valueInfo.setPro2(unitInfo.getUnitId());
            }
            valueInfo.setValueList(unitInfo.getValueList());

            return valueInfo;
        }

        private NonRTUploadDataInfo buildUploadDataBaseInfo(Facility facility, User user, String importType,
                                                            NonRTUploadDTO dataInfo) {
            NonRTUploadDataInfo info = new NonRTUploadDataInfo();
            info.setImportType(importType);
            info.setFabId(facility.getInstanceId());
            info.setFacilityRrn(facility.getInstanceRrn());

            info.setEqptId(dataInfo.getJobBaseInfo().getEqptId());
            info.setEqptRrn(dataInfo.getJobBaseInfo().getEqptRrn());
            info.setArea(dataInfo.getJobBaseInfo().getArea());
            info.setJobId(dataInfo.getJobBaseInfo().getJobId());
            info.setJobName(dataInfo.getJobBaseInfo().getJobName());
            info.setNonRTKey(dataInfo.getJobBaseInfo().getNonRTKey());
            info.setFormulaType(dataInfo.getJobBaseInfo().getFormulaType());
            info.setFormulaPara(dataInfo.getJobBaseInfo().getFormulaPara());
            info.setTime(dataInfo.getJobBaseInfo().getFormulaPara());
            info.setCreateUser(user.getInstanceId());
            info.setValueType(dataInfo.getJobBaseInfo().getValueType());
            info.setDeriveJobId(dataInfo.getJobBaseInfo().getDeriveChartID());
            info.setDeriveJobName(dataInfo.getJobBaseInfo().getDeriveChartName());
            info.setDeriveNonRTKey(dataInfo.getJobBaseInfo().getDeriveNonRTKey());
            info.setSubgroupSizeFlag(StringUtils.toString(dataInfo.getJobBaseInfo().getSubgroupSize()));

            info.setFormula(NonRTMathUtil.getNonRTFormula(info.getFormulaType()));
            return info;
        }

        private ParameterSet buildParameterSetForInsert(String parameterSetId) {
            long facilityRrn = LocalContext.getFacilityRrn();
            String user = LocalContext.getUserId();
            ParameterSet parameterSet = new ParameterSet(parameterSetId, namedObjectManager.getNamedSpace(facilityRrn,
                                                                                                          ObjectList.PARAMETERSET_KEY),
                                                         ObjectList.PARAMETERSET_KEY);
            parameterSet.setTransPerformedby(user);
            return parameterSet;
        }

        private ObjectVersion getNewestParameterSetVersion(ParameterSet parameterSet) {
            List<ObjectVersion> versions = parameterSetManager.getBaseVersions(parameterSet);
            if (versions == null || versions.isEmpty()) {
                buildParameterSetVersion(parameterSet, 1);
                versions = parameterSetManager.getBaseVersions(parameterSet);
            }

            return versions.iterator().next();
        }

        private void buildParameterSetVersion(ParameterSet parameterSet, Integer version) {

            String user = LocalContext.getUserId();

            ParameterSetVersion parameterSetVersion = new ParameterSetVersion();
            parameterSetVersion.setInstanceRrn(parameterSet.getInstanceRrn());
            parameterSetVersion.setInstanceVersion(version);
            parameterSetVersion.setVersionId(version.toString());

            parameterSetVersion.setVersionDesc("Automatic schema generation");
            parameterSetVersion.setTransId("create");
            parameterSetVersion.setTransPerformedby(user);

            Ecn ecn;
            try {
                ecn = generateUnFrozenECNForParameterSetVersion();
            } catch (SystemIllegalArgumentException e) {
                throw new SystemIllegalArgumentException(Errors.create().key(MessageIdList.SYSTEM_UPDATE_VERSION_ERROR)
                                                               .content("导入至 {}，系统今日导入的版本已达最大值，请明日再试! ")
                                                               .args(parameterSet.getInstanceId()).build());
            }

            parameterSetVersion.setEffectiveDateFrom(DateUtils.stringToTimestamp(ecn.getEffectiveDateFrom()));
            parameterSetVersion.setEffectiveDateTo(DateUtils.stringToTimestamp(ecn.getEffectiveDateTo()));
            parameterSetVersion.setEcnRrn(ecn.getInstanceRrn());

            parameterSetManager.insertParameterSetVersion(parameterSetVersion);
        }

        private Ecn generateUnFrozenECNForParameterSetVersion() {

            long facilityRrn = LocalContext.getFacilityRrn();
            String user = LocalContext.getUserId();

            Long userRrn = LocalContext.getUserRrn();
            String defaultType = "PROCESSPLAN";

            String ecnId = ecnManager.generateECNID();

            Ecn ecn = new Ecn(ecnId, namedObjectManager.getNamedSpace(facilityRrn, ObjectList.ECN_KEY), ObjectList.ECN_KEY);

            ecn.setInstanceDesc("Automatic schema generation");

            ecn.setEffectiveDateFrom(DateUtils.formatDate(new Date()));
            ecn.setEffectiveDateTo(getEffectiveDateTo());

            ecn.setEcnStatus(VersionStatus.UNFROZEN_KEY);

            ecn.setObject(ObjectList.ECN_KEY);

            ecn.setTransId(TransactionNames.CREATE_KEY);

            ecn.setObjectType(defaultType);
            ecn.setObjectSubtype(defaultType);
            ecn.setRequestBy(userRrn);
            ecn.setTransPerformedby(user);

            ecn.setInstanceRrn(ecnManager.insertEcn(ecn));

            return ecn;
        }

        private String getEffectiveDateTo() {
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 100);
            return DateUtils.formatDate(cal.getTime());
        }

        private void deleteParameterSetVersion(Long parameterSetRrn, Integer parameterSetVersion) {
            edcSpcDAO.deleteParameterSetVersion(parameterSetRrn, parameterSetVersion);
            edcSpcDAO.deleteSamplePromptsForAll(parameterSetRrn, parameterSetVersion);
            edcSpcDAO.deleteReadingPromptsForAll(parameterSetRrn, parameterSetVersion);
            edcSpcDAO.deleteDataCollectionRuleForAll(parameterSetRrn, parameterSetVersion);
            parameterSetManager.adjustParameterSetVersion(parameterSetRrn, null);
        }

        private Parameter buildParameterForInsert(String parameterId) {
            String dataType = "VARIABLE";
            long facilityRrn = LocalContext.getFacilityRrn();
            String user = LocalContext.getUserId();
            Parameter parameter = new Parameter(parameterId,
                                                namedObjectManager.getNamedSpace(facilityRrn, ObjectList.PARAMETER_KEY),
                                                ObjectList.PARAMETER_KEY);
            parameter.setTransPerformedby(user);
            parameter.setDataType(dataType);

            return parameter;
        }

    }