# EquipmentChartManagerImpl.java

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

    import com.fa.sesa.exception.Assert;
    import com.fa.sesa.exception.Errors;
    import com.fa.sesa.i18n.I18nUtils;
    import com.fa.sesa.threadlocal.LocalContext;
    import com.mycim.framework.jdbc.Page;
    import com.mycim.framework.utils.lang.StringUtils;
    import com.mycim.framework.utils.lang.collections.CollectionUtils;
    import com.mycim.framework.utils.lang.time.DateUtils;
    import com.mycim.server.base.manager.NamedObjectManager;
    import com.mycim.server.base.manager.TransactionLogManager;
    import com.mycim.server.edcchart.dao.EquipmentChartDAO;
    import com.mycim.server.edcchart.manager.EquipmentChartManager;
    import com.mycim.valueobject.MessageIdList;
    import com.mycim.valueobject.ObjectList;
    import com.mycim.valueobject.bas.TransactionLog;
    import com.mycim.valueobject.consts.TransactionNames;
    import com.mycim.valueobject.edcspc.EquipmentChartInfo;
    import com.mycim.valueobject.edcspc.dto.UploadChartInfoDto;
    import com.mycim.valueobject.spc.UploadChartInfo;
    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.regex.Pattern;

    /**
     * @author yanbing.chen
     * @version 6.0.0
     * @date 2019/12/13
     **/
    @Service
    @Transactional
    public class EquipmentChartManagerImpl implements EquipmentChartManager {

        @Autowired
        EquipmentChartDAO equipmentChartDAO;

        @Autowired
        TransactionLogManager transactionLogManager;

        @Autowired
        NamedObjectManager namedObjectManager;

        @Override
        public Page getEquipmentChartInfoPage(int pageSize, int pageNo, Map<String, Object> condition) {
            Page page = new Page(pageNo, pageSize);
            page = equipmentChartDAO.getEquipmentChartInfoPage(page, condition);
            return page;
        }

        @Override
        public List<EquipmentChartInfo> getEquipmentChartInfoList(Map condition) {
            return equipmentChartDAO.getEquipmentChartInfoList(condition);
        }

        @Override
        public void updateEquipmentChartMailSendTime(List<EquipmentChartInfo> EquipmentChartInfos) {
            TransactionLog transactionLog = transactionLogManager
                    .startTransactionLog("System", TransactionNames.EMAS_MAIL_SEND);
            equipmentChartDAO.updateEquipmentChartInfoByBatch(EquipmentChartInfos);
            equipmentChartDAO.insertEquipmentChartInfoHistoryByBatch(transactionLog.getTransRrn(), EquipmentChartInfos);
            transactionLogManager.markTransactionLog(transactionLog);
        }

        @Override
        public Page getEquipmentChartInfoHistoryPage(int pageSize, int pageNo, Map<String, Object> condition) {
            Page page = new Page(pageNo, pageSize);
            page = equipmentChartDAO.getEquipmentChartInfoHistoryPage(page, condition);
            return page;
        }

        @Override
        public List<Map<String, Object>> getEquipmentChartInfoHistoryList(Map<String, Object> condition) {
            List<Map<String, Object>> results = equipmentChartDAO.getEquipmentChartInfoHistoryList(condition);
            if (CollectionUtils.isEmpty(results)) {
                results = new ArrayList<>();
            }
            return results;
        }

        @Override
        public void skipExpiredTimestamp(Long equipmentRrn, String chartId) {
            String userId = LocalContext.getUserId();
            EquipmentChartInfo equipmentChartInfo = getEquipmentChartInfo(equipmentRrn, chartId);
            Assert.isFalse(equipmentChartInfo == null || equipmentChartInfo.getExpiredTimestamp() == null,
                           Errors.create().content("No expiration time, can't skip").build());
            Timestamp expiredTimestamp = equipmentChartInfo.getExpiredTimestamp();
            equipmentChartInfo.setExpiredTimestamp(new Timestamp(
                    expiredTimestamp.getTime() + (long) (equipmentChartInfo.getTimeInterval() * 60 * 60 * 1000)));
            TransactionLog transactionLog = transactionLogManager.startTransactionLog(userId, TransactionNames.SKIP_KEY);

            updateEquipmentChartInfo(transactionLog.getTransRrn(), equipmentChartInfo);

            transactionLogManager.markTransactionLog(transactionLog);

        }

        @Override
        public void modifyExpiredTimestamp(Long equipmentRrn, String chartId, String expiredTimestamp) {
            String userId = LocalContext.getUserId();
            EquipmentChartInfo equipmentChartInfo = this.getEquipmentChartInfo(equipmentRrn, chartId);
            Assert.isFalse(equipmentChartInfo == null,
                           Errors.create().content("Can not find any Equipment Chart Info!").build());
            equipmentChartInfo.setExpiredTimestamp(DateUtils.stringToTimestamp(expiredTimestamp));

            Assert.isFalse(new Timestamp(System.currentTimeMillis()).after(equipmentChartInfo.getExpiredTimestamp()),
                           Errors.create().content("Expiration date must be greater than current date!").build());

            TransactionLog transactionLog = transactionLogManager.startTransactionLog(userId, TransactionNames.MODIFY_KEY);

            updateEquipmentChartInfo(transactionLog.getTransRrn(), equipmentChartInfo);

            transactionLogManager.markTransactionLog(transactionLog);
        }

        @Override
        public void uploadChartInfos(UploadChartInfoDto uploadChartInfoDto) {
            long facilityRrn = LocalContext.getFacilityRrn();
            Map<String, List<EquipmentChartInfo>> map = new HashMap<>();

            List<EquipmentChartInfo> addNewEquipmentChartInfos = new ArrayList<>();
            List<EquipmentChartInfo> updateEquipmentChartInfos = new ArrayList<>();
            map.put("insert", addNewEquipmentChartInfos);
            map.put("update", updateEquipmentChartInfos);

            Map<Long, Set<String>> addMap = new HashMap<>();
            Set<String> addChartIds;
            EquipmentChartInfo equipmentChartInfo;
            for (UploadChartInfo uploadChartInfo : uploadChartInfoDto.getUploadChartInfos()) {
                String equipmentId = StringUtils.trimToUpperCase(uploadChartInfo.getEquipmentId());
                long equipmentRrn = namedObjectManager.getNamedObjectRrn(equipmentId, facilityRrn, ObjectList.ENTITY_KEY);
                if (StringUtils.isEmpty(uploadChartInfo.getJobId()) || equipmentRrn <= 0) {
                    continue;
                }

                boolean isExisted = true;
                equipmentChartInfo = getEquipmentChartInfo(equipmentRrn, uploadChartInfo.getJobId());
                if (equipmentChartInfo == null) {
                    isExisted = false;
                    equipmentChartInfo = new EquipmentChartInfo(equipmentRrn, uploadChartInfo.getJobId());
                }

                equipmentChartInfo.setFacilityRrn(facilityRrn);
                equipmentChartInfo.setEquipmentId(equipmentId);
                equipmentChartInfo.setChartName(uploadChartInfo.getJobName());
                equipmentChartInfo.setAreaId(uploadChartInfo.getAreaId());

                equipmentChartInfo.setDeriveChartName(uploadChartInfo.getDeriveChartName());
                equipmentChartInfo.setUserName(uploadChartInfo.getUserName());
                equipmentChartInfo.setRecipeList(uploadChartInfo.getRecipeList());
                equipmentChartInfo.setProdList(uploadChartInfo.getProdList());
                equipmentChartInfo.setTimeInterval(uploadChartInfo.getTimeInterval());
                equipmentChartInfo.setWarningTime(uploadChartInfo.getWarningTime());
                equipmentChartInfo.setFormula(uploadChartInfo.getFormula());

                addChartIds = addMap.get(equipmentChartInfo.getEquipmentRrn());
                if (addChartIds == null) {
                    addChartIds = new HashSet<>();
                    addMap.put(equipmentChartInfo.getEquipmentRrn(), addChartIds);
                }

                if (isExisted || addChartIds.contains(equipmentChartInfo.getChartId())) {
                    if (equipmentChartInfo.getTimeInterval() == null || equipmentChartInfo.getTimeInterval() == 0) {
                        equipmentChartInfo.setExpiredTimestamp(null);
                    } else {
                        if (equipmentChartInfo.getLastUploadTimestamp() != null) {
                            equipmentChartInfo.setExpiredTimestamp(
                                    this.timestampPlusHours(equipmentChartInfo.getLastUploadTimestamp(),
                                                            equipmentChartInfo.getTimeInterval()));
                        }
                    }
                    updateEquipmentChartInfos.add(equipmentChartInfo);
                } else {
                    addChartIds.add(equipmentChartInfo.getChartId());
                    addNewEquipmentChartInfos.add(equipmentChartInfo);
                }
            }

            int totalSize = addNewEquipmentChartInfos.size() + updateEquipmentChartInfos.size();
            uploadChartInfos(totalSize, map);
        }

        @Override
        public void uploadEquipmentChartInfoByBatch(Map<String, List<EquipmentChartInfo>> map) {
            TransactionLog transactionLog = transactionLogManager
                    .startTransactionLog(LocalContext.getUserId(), TransactionNames.IMPORT_KEY);

            List<EquipmentChartInfo> equipmentChartInfos = new ArrayList<>();
            List<EquipmentChartInfo> addNewEquipmentChartInfos = map.get("insert");
            List<EquipmentChartInfo> updateEquipmentChartInfos = map.get("update");

            equipmentChartInfos.addAll(addNewEquipmentChartInfos);
            equipmentChartInfos.addAll(updateEquipmentChartInfos);

            if (CollectionUtils.isNotEmpty(addNewEquipmentChartInfos)) {
                equipmentChartDAO.insertEquipmentChartInfoByBatch(addNewEquipmentChartInfos);
            }

            if (CollectionUtils.isNotEmpty(updateEquipmentChartInfos)) {
                equipmentChartDAO.updateEquipmentChartInfoByBatch(updateEquipmentChartInfos);
            }

            equipmentChartDAO.insertEquipmentChartInfoHistoryByBatch(transactionLog.getTransRrn(), equipmentChartInfos);

            transactionLogManager.markTransactionLog(transactionLog);
        }

        @Override
        public void deleteChartInfo(UploadChartInfoDto uploadChartInfoDto) {
            Set<String> repeatSet = new HashSet<String>();
            EquipmentChartInfo equipmentChartInfo;
            List<EquipmentChartInfo> equipmentChartInfos = new ArrayList<>();

            for (UploadChartInfo uploadChartInfo : uploadChartInfoDto.getUploadChartInfos()) {
                String equipmentId = StringUtils.trimToUpperCase(uploadChartInfo.getEquipmentId());

                String repeats = uploadChartInfo.getJobId() + equipmentId;
                if (repeatSet.contains(repeats)) {
                    continue; // has been in chartIdSet
                }
                repeatSet.add(repeats);

                long equipmentRrn = namedObjectManager
                        .getNamedObjectRrn(equipmentId, LocalContext.getFacilityRrn(), ObjectList.ENTITY_KEY);
                if (StringUtils.isEmpty(uploadChartInfo.getJobId()) || equipmentRrn <= 0) {
                    continue; // equipment not exist in database or chart ID is empty
                }

                equipmentChartInfo = getEquipmentChartInfo(equipmentRrn, uploadChartInfo.getJobId());
                if (equipmentChartInfo == null) {
                    continue; // chart not exist in database
                }

                equipmentChartInfos.add(equipmentChartInfo);
            }

            if (CollectionUtils.isNotEmpty(equipmentChartInfos)) {
                deleteChartInfos(equipmentChartInfos);
            }
        }

        @Override
        public void deleteEquipmentChartInfoByBatch(List<EquipmentChartInfo> equipmentChartInfos) {
            TransactionLog transactionLog = transactionLogManager
                    .startTransactionLog(LocalContext.getUserId(), TransactionNames.DELETE_KEY);

            int[] result = equipmentChartDAO.deleteEquipmentChartInfoByBatch(equipmentChartInfos);
            for (int i = 0; i < result.length; i++) {
                if (result[i] != -2) { // -2 means success
                    EquipmentChartInfo error = equipmentChartInfos.get(i);
                }
            }
            equipmentChartDAO.insertEquipmentChartInfoHistoryByBatch(transactionLog.getTransRrn(), equipmentChartInfos);

            transactionLogManager.markTransactionLog(transactionLog);

        }

        @Override
        public List<EquipmentChartInfo> getEquipAndChamberChart(long instanceRrn) {
            return equipmentChartDAO.getEquipAndChamberChart(instanceRrn);
        }

        @Override
        public List<EquipmentChartInfo> getEquipChart(long instanceRrn) {
            return equipmentChartDAO.getEquipChart(instanceRrn);
        }

        @Override
        public String checkChartExpire(long instanceRrn, String instanceId, String physicalId, String productId) {
            StringBuffer retBf = new StringBuffer();
            List<EquipmentChartInfo> charList = getEquipChart(instanceRrn);
            for (EquipmentChartInfo equipmentChartInfo : charList) {
                Timestamp expiredTimestamp = equipmentChartInfo.getExpiredTimestamp();
                String equipmentId = equipmentChartInfo.getEquipmentId();
                String recipeList = equipmentChartInfo.getRecipeList();
                String prodList = equipmentChartInfo.getProdList();
                String charName = equipmentChartInfo.getChartName();
                if (StringUtils.isEmpty(recipeList) || StringUtils.isEmpty(prodList)) {
                    continue;
                }
                if (expiredTimestamp == null) {
                    continue;
                }
                if (expiredTimestamp != null && (expiredTimestamp.getTime() > (new Date()).getTime())) {
                    continue;
                }
                if (StringUtils.equals(equipmentId, instanceId)) {
                    if (patternMatch(recipeList, physicalId) && patternMatch(prodList, productId)) {
                        // if (retBf.length() == 0) {
                        //     retBf.append("EMAS Char Expired,<br>");
                        // }
                        // retBf.append(charName + "<br>");
                        retBf.append(I18nUtils.getMessage(MessageIdList.EMAS_CHECK_CHAR_EXPIRE, new Object[]{charName}));
                    }
                }
            }
            return retBf.toString();
        }

        @Override
        public void updateLastUploadTimestampWhenUpload(String userId, Long equipmentRrn, String chartId) {
            EquipmentChartInfo equipmentChartInfo = equipmentChartDAO.getEquipmentChartInfo(equipmentRrn, chartId);
            if (equipmentChartInfo != null) {
                TransactionLog transactionLog = transactionLogManager
                        .startTransactionLog(userId, TransactionNames.UPLOAD_KEY);
                equipmentChartInfo.setLastUploadTimestamp(transactionLog.getTransStartTimestamp());
                Timestamp expiredTimestamp = equipmentChartInfo.getTimeInterval() == null ||
                        equipmentChartInfo.getTimeInterval() <= 0 ? null : timestampPlusHours(
                        equipmentChartInfo.getLastUploadTimestamp(), equipmentChartInfo.getTimeInterval());
                equipmentChartInfo.setExpiredTimestamp(expiredTimestamp);

                equipmentChartDAO.updateEquipmentChartInfo(equipmentChartInfo);
                List<EquipmentChartInfo> equipmentChartInfos = new ArrayList<>();
                equipmentChartInfos.add(equipmentChartInfo);
                equipmentChartDAO.insertEquipmentChartInfoHistoryByBatch(transactionLog.getTransRrn(), equipmentChartInfos);
                transactionLogManager.markTransactionLog(transactionLog);
            }
        }

        @Override
        public String getEquipmentChartUploadTime(Long equipmentRrn, String chartName) {
            EquipmentChartInfo equipmentChartInfo = getEquipmentChartInfo(equipmentRrn, chartName);
            String lastUpLoadTime = null;
            if (equipmentChartInfo != null && equipmentChartInfo.getLastUploadTimestamp() != null) {
                Date tempLastUpLoadTime = equipmentChartInfo.getLastUploadTimestamp();
                lastUpLoadTime = DateUtils.formatDate(tempLastUpLoadTime, DateUtils.DATE_FORMAT4DATE);
            }
            return lastUpLoadTime;
        }

        private void deleteChartInfos(List<EquipmentChartInfo> equipmentChartInfos) {
            if (equipmentChartInfos != null && equipmentChartInfos.size() > 0) {
                this.deleteEquipmentChartInfoByBatch(equipmentChartInfos);
            }
        }

        private void uploadChartInfos(Integer totalSize, Map<String, List<EquipmentChartInfo>> map) {
            if (totalSize != null && totalSize > 0) {
                this.uploadEquipmentChartInfoByBatch(map);
            }
        }

        private Timestamp timestampPlusHours(Timestamp timestamp, Float hours) {
            if (timestamp == null) {
                return null;
            }
            if (hours == null) {
                return timestamp;
            }
            return new Timestamp(timestamp.getTime() + hourToMillisecond(hours));
        }

        private long hourToMillisecond(Float hours) {
            return (long) (hours * 60 * 60 * 1000);
        }

        private EquipmentChartInfo getEquipmentChartInfo(Long equipmentRrn, String chartId) {
            return equipmentChartDAO.getEquipmentChartInfo(equipmentRrn, chartId);
        }

        private void updateEquipmentChartInfo(Long transRrn, EquipmentChartInfo equipmentChartInfo) {
            equipmentChartDAO.updateEquipmentChartInfo(equipmentChartInfo);
            List<EquipmentChartInfo> equipmentChartInfos = new ArrayList<>();
            equipmentChartInfos.add(equipmentChartInfo);
            equipmentChartDAO.insertEquipmentChartInfoHistoryByBatch(transRrn, equipmentChartInfos);
        }

        private boolean patternMatch(String regStr, String sourceStr) {
            if (StringUtils.contains(regStr, ",")) {
                for (String r : regStr.split(",")) {
                    String pattern = r.replaceAll("\\*", "\\.*");
                    if (Pattern.matches(pattern, sourceStr)) {
                        return true;
                    }
                }
            } else {
                String pattern = regStr.replaceAll("\\*", "\\.*");
                if (Pattern.matches(pattern, sourceStr)) {
                    return true;
                }
            }
            return false;
        }

    }