# ProductSpecInfoManagerImpl.java

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

    import com.mycim.framework.utils.lang.BooleanUtils;
    import com.mycim.framework.utils.lang.collections.CollectionUtils;
    import com.mycim.server.prp.manager.ProcessManager;
    import com.mycim.server.spec.dao.ProductSpecInfoDao;
    import com.mycim.server.spec.manager.ProductSpecInfoManager;
    import com.mycim.valueobject.bas.TransactionLog;
    import com.mycim.valueobject.consts.VersionStatus;
    import com.mycim.valueobject.prp.ProcessSpecInfo;
    import com.mycim.valueobject.prp.ProductAttributeInfo;
    import com.mycim.valueobject.prp.ProductSpecInfo;
    import com.mycim.valueobject.prp.ProductVersion;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;

    /**
     * @author Qiansheng.Wang
     * @since 2020-10-26
     */
    @Service
    @Transactional
    public class ProductSpecInfoManagerImpl implements ProductSpecInfoManager {

        @Autowired
        ProductSpecInfoDao productSpecInfoDao;

        @Autowired
        ProcessManager processManager;

        private void insertProductSpecInfos(TransactionLog transactionLog, List<ProductSpecInfo> productSpecInfos) {
            for (ProductSpecInfo productSpecInfo : productSpecInfos) {
                productSpecInfo.setActiveFlag(true);
                productSpecInfo.setActiveTime(transactionLog.getTransStartTimestamp());
                productSpecInfo.setActiveUser(transactionLog.getTransPerformedBy());

                productSpecInfo.setCurrentStatus(VersionStatus.ACTIVE_KEY);

                productSpecInfo.setLastUpdatedUser(transactionLog.getTransPerformedBy());
                productSpecInfo.setLastUpdatedTime(transactionLog.getTransStartTimestamp());

                productSpecInfo.setCreateUserId(transactionLog.getTransPerformedBy());
                productSpecInfo.setCreateTime(transactionLog.getTransStartTimestamp());
            }

            productSpecInfoDao.insertProductSpecInfos(productSpecInfos);
        }

        private void updateProductSpecInfos(TransactionLog transactionLog, List<ProductSpecInfo> productSpecInfos) {
            for (ProductSpecInfo productSpecInfo : productSpecInfos) {
                productSpecInfo.setCurrentStatus(VersionStatus.ACTIVE_KEY);

                productSpecInfo.setLastUpdatedUser(transactionLog.getTransPerformedBy());
                productSpecInfo.setLastUpdatedTime(transactionLog.getTransStartTimestamp());
            }

            productSpecInfoDao.updateProductSpecInfos(productSpecInfos);
        }

        @Override
        public void activateProductSpecInfos(TransactionLog transactionLog, ProcessSpecInfo processSpecInfo,
                                             List<ProductVersion> allProductVersions) {
            List<ProductSpecInfo> willSaveProductSpecInfo = new ArrayList<>();
            for (ProductVersion productVersion : allProductVersions) {
                ProductSpecInfo productSpecInfo = new ProductSpecInfo();

                productSpecInfo.setProductRrn(productVersion.getProductRrn());
                productSpecInfo.setProductId(productVersion.getProductId());
                productSpecInfo.setProductVersion(productVersion.getProductVer());

                productSpecInfo.setProcessRrn(processSpecInfo.getProcessRrn());
                productSpecInfo.setProcessId(processSpecInfo.getProcessId());
                productSpecInfo.setProcessVersion(processSpecInfo.getProcessVersion());

                willSaveProductSpecInfo.add(productSpecInfo);
            }

            activateProductSpecInfos(transactionLog, willSaveProductSpecInfo, processSpecInfo.getProcessRrn(),
                                     processSpecInfo.getProcessVersion());
        }

        @Override
        public void activateProductSpecInfos(TransactionLog transactionLog,
                                             List<ProductAttributeInfo> productAttributeInfos) {
            List<ProductSpecInfo> willSaveProductSpecInfo = new ArrayList<>();
            for (ProductAttributeInfo productVersion : productAttributeInfos) {
                ProductSpecInfo productSpecInfo = new ProductSpecInfo();

                productSpecInfo.setProductRrn(productVersion.getProductRrn());
                productSpecInfo.setProductId(productVersion.getProductId());
                productSpecInfo.setProductVersion(productVersion.getProductVersion());

                productSpecInfo.setProcessRrn(productVersion.getProcessRrn());
                productSpecInfo.setProcessId(productVersion.getProcessId());
                productSpecInfo.setProcessVersion(productVersion.getProcessVersion());

                willSaveProductSpecInfo.add(productSpecInfo);
            }

            ProductSpecInfo temp = willSaveProductSpecInfo.iterator().next();

            activateProductSpecInfos(transactionLog, willSaveProductSpecInfo, temp.getProcessRrn(),
                                     temp.getProcessVersion());
        }

        private void activateProductSpecInfos(TransactionLog transactionLog, List<ProductSpecInfo> willSaveProductSpecInfo,
                                              Long processRrn, Integer processVersion) {
            List<ProductSpecInfo> productSpecInfosInDb = getProductSpecInfos(processRrn, processVersion);

            List<ProductSpecInfo> insertSpecItemInfos = new ArrayList<>();
            List<ProductSpecInfo> updateSpecItemInfos = new ArrayList<>();

            for (ProductSpecInfo productSpecInfoTemp : willSaveProductSpecInfo) {
                if (productSpecInfosInDb.contains(productSpecInfoTemp)) {
                    // If the spec item already exists, it will be updated
                    updateSpecItemInfos.add(productSpecInfoTemp);
                } else {
                    // If the spec item does not exists, it will be inserted
                    insertSpecItemInfos.add(productSpecInfoTemp);
                }
            }

            insertProductSpecInfos(transactionLog, insertSpecItemInfos);
            updateProductSpecInfos(transactionLog, updateSpecItemInfos);
        }

        @Override
        public List<ProductSpecInfo> getProductSpecInfos(Long processRrn, Integer processVersion) {
            List<ProductSpecInfo> result = productSpecInfoDao.getProductSpecInfosByProcess(processRrn, processVersion);
            if (CollectionUtils.isEmpty(result)) {
                result = Collections.emptyList();
            }
            return result;
        }

        @Override
        public ProductSpecInfo getLatestActivatedProductSpecInfo(Long productRrn, Long processRrn) {
            return productSpecInfoDao.getLatestActivatedProductSpecInfo(productRrn, processRrn);
        }

        @Override
        public List<ProductSpecInfo> getAllActivatedProductSpecItemInfo(Long productRrn, Long processRrn) {
            List<ProductSpecInfo> result = productSpecInfoDao.getAllActivatedProductSpecInfo(productRrn, processRrn);
            if (CollectionUtils.isEmpty(result)) {
                result = Collections.emptyList();
            }
            return result;
        }

        @Override
        public List<Integer> getAllActivatedProcessVersions(Long productRrn, Long processRrn) {
            List<Integer> result = productSpecInfoDao.getAllActivatedProcessVersions(productRrn, processRrn);
            if (CollectionUtils.isEmpty(result)) {
                result = Collections.emptyList();
            }
            return result;
        }

        @Override
        public ProductSpecInfo getLatestActivatedProductSpecItemInfo(Long productRrn, Long processRrn) {
            return productSpecInfoDao.getLatestActivatedProductSpecInfo(productRrn, processRrn);
        }

        @Override
        public boolean isAvailableVersion(Long productRrn, Integer productVersion, Long processRrn,
                                          Integer processVersion) {
            ProductSpecInfo productSpecInfo = productSpecInfoDao
                    .getProductSpecInfoByPrimaryKey(productRrn, productVersion, processRrn, processVersion);

            return productSpecInfo != null && BooleanUtils.toBoolean(productSpecInfo.getActiveFlag());
        }

    }