com.castis.xylophone.adsmadapter.convert.axistree.ConvertContentAxisTreeDTO.java Source code

Java tutorial

Introduction

Here is the source code for com.castis.xylophone.adsmadapter.convert.axistree.ConvertContentAxisTreeDTO.java

Source

package com.castis.xylophone.adsmadapter.convert.axistree;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.annotation.Transactional;

import com.castis.tambourine.bizobject.common.Period;
import com.castis.tambourine.bizobject.ktadsm.ADSMJobNameType;
import com.castis.tambourine.bizobject.ktadsm.ADSMSchedulerStatus;
import com.castis.tambourine.bizobject.ktadsm.TargetMap;
import com.castis.tambourine.define.Constants;
import com.castis.tambourine.dto.inventory.AxisTreeDTO;
import com.castis.tambourine.dto.inventory.NodeDTO;
import com.castis.tambourine.dto.ktadsm.ADSMSchedulerLogDTO;
import com.castis.tambourine.dto.ktadsm.ContentDataDTO;
import com.castis.tambourine.dto.ktadsm.NodeInfoLicenseDTO;
import com.castis.tambourine.dto.ktadsm.NodeInfoWithLinkNodeDTO;
import com.castis.tambourine.dto.ktadsm.InventoryData.TargetedContentInfo;
import com.castis.tambourine.dto.ktadsm.axistree.AxisTreeNodeDTO;
import com.castis.tambourine.dto.ktadsm.axistree.TreeNodeLinkDTO;
import com.castis.tambourine.dto.ktadsm.axistree.TreeNodeLinkPeriodDTO;
import com.castis.tambourine.dto.ktadsm.campaign.Ads;
import com.castis.tambourine.dto.ktadsm.campaign.Ads_disable_detail;
import com.castis.tambourine.dto.ktadsm.campaign.Content;
import com.castis.tambourine.dto.ktadsm.campaign.Exclusive_content_disable;
import com.castis.tambourine.dto.ktadsm.campaign.PlayInfo;
import com.castis.tambourine.dto.ktadsm.campaign.Target;
import com.castis.tambourine.enumeration.InventoryType;
import com.castis.tambourine.enumeration.PlacementOpportunityTypeEnum;
import com.castis.tambourine.enumeration.Platform;
import com.castis.tambourine.enumeration.TreeType;
import com.castis.tambourine.logger.TheLogger;
import com.castis.tambourine.util.DateUtil;
import com.castis.xylophone.adsmadapter.setting.ADDSAdapterSetting;

public class ConvertContentAxisTreeDTO extends ConvertTreeDTO {

    static final Log log = LogFactory.getLog(ConvertContentAxisTreeDTO.class);
    static final String name = "ConvertContentAxisTreeDTO";
    static final String ROOT_NODE_NAME = "root_content";
    private static final String ROOT_LINK_NODE_NAME = "root_link_content";

    private static final String ROOT_CONTENT_PARENT = "*.content";
    private static final String ROOT_CONTENT_LINK_PARENT = "*";

    private static final String ALL_CATEOGRY = "ALL_CATEGORY";
    private static final String ALL_CONTENT = "ALL_CONTENT";

    boolean bContentTreeUpdatedByContentData;

    public ConvertContentAxisTreeDTO() {
        log.info(" ### " + name + " was started.");
    }

    public void close() {
        log.info(" # " + name + " is shutting down.");
    }

    public void setbContentTreeUpdatedByContentData(boolean bContentTreeUpdatedByContentData) {
        this.bContentTreeUpdatedByContentData = bContentTreeUpdatedByContentData;
    }

    public void init() {

        int treeID = tambourineConnector.getAxisTreeId(TreeType.VOD_CONTENTS_AXIS, Constants.tree.CONTENT_TREE_NAME,
                ADDSAdapterSetting.defaultSiteName, null, false);
        //?
        if (treeID <= 0) {
            log.info(" ### Generate Content Tree");
            treeID = tambourineConnector.generateContentTree(Constants.tree.CONTENT_TREE_NAME, ROOT_NODE_NAME,
                    ROOT_CONTENT_PARENT, ADDSAdapterSetting.defaultSiteName, null);
        }
    }

    public boolean insertData(List<ContentDataDTO> contentDataList, ADSMSchedulerLogDTO schedulerLog,
            String dataFileName) {
        return tambourineConnector.insertContentData(contentDataList, schedulerLog, resultDirectory, dataFileName);
    }

    public void makeMapperFile(AxisTreeDTO axisTreeDTO) {
        if (axisTreeDTO == null)
            return;

        try {
            File file = new File("c:/dataTest/content.txt"); //  ? ?
            PrintWriter writer = new PrintWriter(new FileWriter(file, false));

            writer.println("Type\tTreeID\tNodeID\tPath_Name\tMappingID(to be filled in)");
            writer.println("----\t------\t------\t---------\t---------");
            writeMapperFile(writer, axisTreeDTO.getRootNode(), axisTreeDTO.getTreeID());
            writer.flush();
            writer.close();
        } catch (Exception e) {
            log.error("Fail to write MapperFile. Exception Type : Exception |", e);
        }
    }

    public void writeMapperFile(PrintWriter writer, NodeDTO nodeDTO, int treeID) {
        if (nodeDTO == null)
            return;

        List<NodeDTO> childNodeDTO = nodeDTO.getChildren();

        if (childNodeDTO != null) {
            for (int i = 0; i < childNodeDTO.size(); i++)
                writeMapperFile(writer, childNodeDTO.get(i), treeID);
        }

        writer.println("Category" + "\t" + treeID + "\t" + nodeDTO.getNodeID() + "\t" + nodeDTO.getName() + "\t"
                + nodeDTO.getAggregationId());
    }

    @Transactional(rollbackFor = Exception.class)
    public int convertContentTree(Date date, ADSMSchedulerLogDTO schedulerLog, String publisher,
            Platform platformType) throws Exception {

        long start = System.currentTimeMillis();
        int dataLogId = Integer.parseInt((String) schedulerLog.getParamValue("dataLogId"));

        log.info("convertContentTree start(ContentData)");

        int treeID = mergeContentTreenode(schedulerLog, date, null, dataLogId, false, null, publisher,
                platformType);

        long end = System.currentTimeMillis();
        log.info("convertContentTree end - T(" + (end - start) + ")");
        return treeID;
    }

    @Transactional(rollbackFor = Exception.class)
    public int convertContentTree(PlayInfo playInfo, Date date, ADSMSchedulerLogDTO schedulerLog,
            PlacementOpportunityTypeEnum oppType, String publisher, Platform platformType) throws Exception {
        if (playInfo == null)
            return 0;

        long start = System.currentTimeMillis();
        log.info("convertContentTree start(adsInfo) " + oppType.name());

        int dataLogId = Integer.parseInt((String) schedulerLog.getParamValue("dataLogId"));

        int treeID = mergeContentTreenode(schedulerLog, date, playInfo, dataLogId, false, oppType, publisher,
                platformType);

        long end = System.currentTimeMillis();
        log.info("convertContentTree end - T(" + (end - start) + ") " + oppType.name());
        return treeID;
    }

    @Transactional(rollbackFor = Exception.class)
    public int updateContentTree(PlayInfo playInfo, Date date, ADSMSchedulerLogDTO schedulerLog,
            PlacementOpportunityTypeEnum oppType, String publisher, Platform platformType) throws Exception {
        if (playInfo == null)
            return 0;

        int dataLogId = Integer.parseInt((String) schedulerLog.getParamValue("dataLogId"));
        long start = System.currentTimeMillis();
        log.info("update ContentTree start(adsInfo) " + oppType.name());

        int treeID = mergeContentTreenode(schedulerLog, date, playInfo, dataLogId, true, oppType, publisher,
                platformType);

        long end = System.currentTimeMillis();
        log.info("convertContentTree end - T(" + (end - start) + ") " + oppType.name());
        return treeID;
    }

    public String getNewSchedulerLogParam(boolean checkContentTreeLog) {

        ADSMSchedulerLogDTO contentDataLog = tambourineConnector
                .getLatestADSMSchedulerLog(ADSMJobNameType.CONTENT_DATA.name());
        ADSMSchedulerLogDTO contentTreeLog = null;
        if (checkContentTreeLog)
            contentTreeLog = tambourineConnector.getLatestADSMSchedulerLog(TreeType.VOD_CONTENTS_AXIS.name());

        if (contentDataLog == null) {
            return null; //? ? DAT ? ?
        }
        int dataLogId = contentDataLog.getId();
        String schedulerLogParam = "dataLogId:" + dataLogId;

        if (checkContentTreeLog) {
            if (contentTreeLog == null) { //? DAT  ?
                log.warn("Cannot Find Updated ContentTree");
                return null;
            } else {
                if (dataLogId == Integer.parseInt((String) contentTreeLog.getParamValue("dataLogId"))) {
                    //log.info(" ?  ? - " + schedulerLogParam);
                    return null;
                }
            }
        }

        return schedulerLogParam;
    }

    public int mergeContentTreenode(ADSMSchedulerLogDTO schedulerLog, Date date, PlayInfo playInfo, int dataLogId,
            boolean updateTreeNode, PlacementOpportunityTypeEnum oppType, String publisher, Platform platformType)
            throws Exception {
        int treeID = 0;
        try {
            //         NodeDTO rootNodeDTO = getRootNode(ROOT_NODE_NAME);
            NodeDTO rootNodeDTO = getContentRootNode(ROOT_NODE_NAME);
            treeID = tambourineConnector.getAxisTreeId(TreeType.VOD_CONTENTS_AXIS, Constants.tree.CONTENT_TREE_NAME,
                    publisher, platformType, false);
            //?
            if (treeID <= 0)
                treeID = tambourineConnector.registerContentAxisTree(getAxisTreeDTO(
                        Constants.tree.CONTENT_TREE_NAME, rootNodeDTO, false, null, publisher, platformType), date);

            if (playInfo != null)
                addContentToTargetMap(playInfo, oppType, TreeType.VOD_CONTENTS_AXIS, publisher, platformType);

            TargetedContentInfo targetedContentInfo = getAllTargettedContentIdList(TreeType.VOD_CONTENTS_AXIS,
                    dataLogId, InventoryType.VOD);

            int linkTreeId = -1;
            linkTreeId = makeTreeNode(treeID, date, rootNodeDTO.getExternalNodeId(), targetedContentInfo,
                    !updateTreeNode, dataLogId, publisher, platformType);

            tambourineConnector.insertTreeLogNSyncNoticeboard(linkTreeId, TreeType.VOD_CONTENTS_AXIS,
                    Constants.tree.CONTENT_LINK_TREE_NAME, null, publisher, platformType);
            tambourineConnector.insertTreeLogNSyncNoticeboard(treeID, TreeType.VOD_CONTENTS_AXIS,
                    Constants.tree.CONTENT_TREE_NAME, null, publisher, platformType);

            schedulerLog.setSchedulerStatus(ADSMSchedulerStatus.SUCCESS);
            TheLogger.getWriter().info("Update Content Tree Success");
        } catch (Exception e) {
            //log.error("",e);
            TheLogger.getWriter().error("Fail to Update Content Tree");
            log.error("Fail to Update Content Tree");
            schedulerLog.setMessage(e.getMessage());
            schedulerLog.setSchedulerStatus(ADSMSchedulerStatus.FAIL);
            StackTraceElement[] stackTraces = e.getStackTrace();
            if (stackTraces.length > 0) {
                schedulerLog.setFailProcess(stackTraces[0].getClassName() + " - " + stackTraces[0].getMethodName()
                        + "(" + stackTraces[0].getLineNumber() + ")");
            }
            throw e;
        }
        return treeID;
    }

    private List<String> splitIds(String notSplitedText) {
        String[] splited = notSplitedText.split("/");
        List<String> splitedList = Arrays.asList(splited);
        return splitedList;
    }

    private void addContentToTargetMap(PlayInfo playInfo, PlacementOpportunityTypeEnum oppType, TreeType treeType,
            String publisher, Platform platformType) {

        //category / content
        Map<String, List<String>> targetMap = new HashMap<String, List<String>>();

        if (!(playInfo == null || playInfo.getContent_promoRate() == null)) {
            //content_promoRate            
            for (Content content : playInfo.getContent_promoRate().getContentList()) {
                List<String> contentIds = new ArrayList<String>();
                contentIds.addAll(content.getContent_id());
                addContent2TargetMap(targetMap, contentIds);
            }
        }

        if (!(playInfo == null || playInfo.getContent_monopolyRate() == null)) {
            for (Content content : playInfo.getContent_monopolyRate().getContentList()) {
                List<String> contentIds = new ArrayList<String>();
                contentIds.addAll(content.getContent_id());
                addContent2TargetMap(targetMap, contentIds);
            }
        }

        /*
         <ads_disable>               
           <content> //?             
        <content_id>M89E3JKYSGL080005200</content_id>         
           </content>            
           <category>//?_?            
        <category_id>0532</category_id>         
           </category>            
           <category_content>//?_?            
        <category_id>10000000000000031567</category_id>         
        <content_id>M44E2Y5LSGL080000100</content_id>         
           </category_content>            
           <content>// ? ?  ?    
        <category_id>10000000000000061912</category_id>         
        <category_id>10000000000000059628</category_id>         
           </content>            
        </ads_disable>   
        */
        List<Ads_disable_detail> content_disable = new ArrayList<Ads_disable_detail>();
        if (playInfo != null && playInfo.getAds_disable() != null) {
            content_disable.addAll(playInfo.getAds_disable().getContent_disable());
        }

        int categoryTreeID = tambourineConnector.getAxisTreeId(TreeType.CATEGORY_AXIS_TREE,
                Constants.tree.CATEGORY_TREE_NAME, publisher, platformType, false);
        //  ?    
        Set<String> uniqueCategoryid = new HashSet<String>();

        for (Ads_disable_detail ads_disable_detail : content_disable) {

            if (ads_disable_detail.getContent_id().size() > 0) {
                //? 
                addContent2TargetMap(targetMap, ads_disable_detail.getContent_id());
            } else {
                // ? ?  ? 
                //2014.12
                //leaf  ?  ??? ?    . ???  id  .            
                for (String parentCategory : ads_disable_detail.getCateogry_id()) {

                    if (categoryTreeID <= 0)
                        log.warn("Cannot find categoryTree info in generating CategoryTree");
                    else {
                        List<String> familyCategoryExternalIdList = tambourineConnector
                                .getFamilyExternalIdList(parentCategory, categoryTreeID);
                        if (familyCategoryExternalIdList != null
                                && familyCategoryExternalIdList.isEmpty() == false) {
                            for (String categoryId : familyCategoryExternalIdList) {
                                if (uniqueCategoryid.add(categoryId)) {
                                    List<String> contentList = new ArrayList<String>();
                                    contentList.add(ALL_CONTENT);
                                    targetMap.put(categoryId, contentList);
                                }
                            }
                        } else {
                            List<String> contentList = new ArrayList<String>();
                            contentList.add(ALL_CONTENT);
                            targetMap.put(parentCategory, contentList);
                            log.warn("Cannot find (categoryId:" + parentCategory + ") in generating Content Tree");
                        }

                    }
                }
            }
        }

        //?_? 
        //NOTE : ?  ?  ??.
        //List<Ads_disable_detail> category_disable = adsInfo.getPreplay().getAds_disable().getCategory_disable();
        //category_disable.addAll(adsInfo.getMidplay().getAds_disable().getCategory_disable());

        //?_?

        List<Ads_disable_detail> category_content_disable = new ArrayList<Ads_disable_detail>();
        if (playInfo != null && playInfo.getAds_disable() != null
                && playInfo.getAds_disable().getCategory_content_disable() != null)
            category_content_disable
                    .addAll(playInfo.getAds_disable().getCategory_content_disable().getMapping_disable());

        for (Ads_disable_detail ads_disable_detail : category_content_disable) {
            addContent2TargetMap(targetMap, ads_disable_detail.getContent_id());
        }

        List<Content> exclusiveDisableContentList = new ArrayList<Content>();

        if (playInfo != null && playInfo.getExclusive_content_disable() != null) {
            Exclusive_content_disable playinfoExclusiveContentDisable = playInfo.getExclusive_content_disable();
            exclusiveDisableContentList.addAll(playinfoExclusiveContentDisable.getContentList());
        }

        for (Content content : exclusiveDisableContentList) {
            List<String> contentIds = new ArrayList<String>();
            if (content.getContent_id() != null) {
                for (String contentId : content.getContent_id()) {
                    if (contentId != null && contentId.isEmpty() == false)
                        contentIds.add(contentId);
                }
            }
            addContent2TargetMap(targetMap, contentIds);
        }
        List<Ads> adsList = new ArrayList<Ads>();
        if (playInfo != null && playInfo.getAd_list() != null)
            adsList.addAll(playInfo.getAd_list().getAdsList(/*null, */null));

        for (Ads ads : adsList) {
            List<String> contentIds = new ArrayList<String>();
            if (ads.getTargetList() != null && ads.getTargetList().isExistTarget()) {
                for (Target target : ads.getTargetList().getTarget()) {
                    if (target.getContent_ID() != null && target.getContent_ID().isEmpty() == false)
                        contentIds.addAll(splitIds(target.getContent_ID()));
                }
                if (contentIds.isEmpty() == false)
                    addContent2TargetMap(targetMap, contentIds);
            } else if (ads.getContent_ID() != null && !ads.getContent_ID().equals("")) {
                contentIds.addAll(splitIds(ads.getContent_ID()));
                addContent2TargetMap(targetMap, contentIds);
            }
        }

        saveTargetMapbyOppType(targetMap, oppType, treeType);

    }

    private TargetedContentInfo getAllTargettedContentIdList(TreeType treeType, int dataLogId,
            InventoryType inventoryType) {
        List<TargetMap> allTargetMap = tambourineConnector.getAllTargetMap(treeType);
        Map<String, List<String>> targetMap = convertToMap(allTargetMap);

        TargetedContentInfo targetedContentInfo = new TargetedContentInfo();

        if (bContentTreeUpdatedByContentData == true) {
            List<ContentDataDTO> contentTargetList = tambourineConnector
                    .getContentDataByContentIds(targetMap.get(ALL_CATEOGRY), dataLogId);
            if (contentTargetList != null && contentTargetList.isEmpty() == false)
                targetedContentInfo.addContentTargetList(contentTargetList);

            targetMap.remove(ALL_CATEOGRY);
            List<ContentDataDTO> disableCategoryTargetList = tambourineConnector
                    .getContentDataByCategoryIds(new ArrayList<String>(targetMap.keySet()), dataLogId);
            if (disableCategoryTargetList != null && disableCategoryTargetList.isEmpty() == false)
                targetedContentInfo.addDisableCategoryTargetList(disableCategoryTargetList);

            for (String categoryId : targetMap.keySet()) {
                if (categoryId.equalsIgnoreCase(ALL_CATEOGRY))
                    continue;

                //  ? ?  id ? ? ??     .
                targetedContentInfo.addDisableCategoryTargetList(new ContentDataDTO(categoryId));
            }
        } else {
            targetedContentInfo.addContentTargetList(getContentDataDTOList(targetMap.get(ALL_CATEOGRY)));
        }

        log.info("Targetted Content Id List size : " + targetedContentInfo.getContentTargetList().size()
                + ", Disable category Id + Content Id List size : "
                + targetedContentInfo.getDisableCategoryTargetList().size());

        return targetedContentInfo;
    }

    private void saveTargetMapbyOppType(Map<String, List<String>> targetMap, PlacementOpportunityTypeEnum oppType,
            TreeType treeType) {
        tambourineConnector.saveTargetMapByOppType(targetMap, oppType, treeType, InventoryType.VOD);
    }

    private List<ContentDataDTO> getContentDataDTOList(List<String> contentIds) {
        List<ContentDataDTO> contentDataDTOs = new ArrayList<ContentDataDTO>();
        if (contentIds != null && contentIds.isEmpty() == false) {
            for (String contentId : contentIds) {
                ContentDataDTO contentDataDTO = new ContentDataDTO(contentId, contentId);
                contentDataDTOs.add(contentDataDTO);
            }
        }
        return contentDataDTOs;
    }

    private void addContent2TargetMap(Map<String, List<String>> targetMap, List<String> contentIds) {
        List<String> contentList = targetMap.get(ALL_CATEOGRY);
        if (contentList == null) {
            contentList = new ArrayList<String>();
        }
        contentList.addAll(contentIds);
        targetMap.put(ALL_CATEOGRY, contentList);
    }

    private int generateContentLinkTree(List<ContentDataDTO> contentDataDTOList, Date date,
            boolean bInvalidateAxisTreeNode, int conSchedulerId, String publisher, Platform platformType)
            throws Exception {
        int level = 0;
        NodeDTO rootNodeDTO = getRootNode(ROOT_LINK_NODE_NAME);

        int treeID = tambourineConnector.getAxisTreeId(TreeType.VOD_CONTENTS_AXIS,
                Constants.tree.CONTENT_LINK_TREE_NAME, publisher, platformType, true);
        //?
        if (treeID <= 0)
            treeID = tambourineConnector
                    .registerContentAxisTree(getAxisTreeDTO(Constants.tree.CONTENT_LINK_TREE_NAME, rootNodeDTO,
                            true, treeID, publisher, platformType), date);

        if (bInvalidateAxisTreeNode == true) {
            tambourineConnector.invalidateAxisTreeNodeExceptRootNode(treeID, date);
            log.info("invalidate ContentLinkTree ExceptRootNode done");
        }

        mergeLinkNode(treeID, level + 1, date, contentDataDTOList, conSchedulerId);
        log.info("generateContentLinkTree done");
        return treeID;
    }

    private int mergeNode(int treeID, String parentId, int level, Date date,
            List<ContentDataDTO> contentDataDTOList) throws Exception {

        try {
            Set<String> contentIdSet = new HashSet<String>();
            for (ContentDataDTO contentDataDTO : contentDataDTOList) {
                if (contentDataDTO.getContsId() != null && contentIdSet.add(contentDataDTO.getContsId()) == true) {
                    NodeDTO nodeDTO = convertContentData2Node(contentDataDTO, level);

                    if (nodeDTO != null) {
                        nodeDTO.setLicensingPeriod(new Period(date, DateUtil.string2Date("9999-12-31")));
                        tambourineConnector.mergeNodeUsingMemory(treeID, parentId, nodeDTO);
                    }
                }
            }

            return contentIdSet.size();
        } catch (Exception e) {
            throw e;
        } finally {
            //  mergeNode?? ?
            tambourineConnector.mergeNodeAfterMemoryClear();
        }
    }

    /*
     *   ??   .  ? feSyncNoticeBoard? ? ??  ?.
     */
    public boolean updateLinkNode(List<String> categoryIdList, String publisher, Platform platformType)
            throws Exception {

        try {
            int linkTreeId = tambourineConnector.getAxisTreeId(TreeType.VOD_CONTENTS_AXIS,
                    Constants.tree.CONTENT_LINK_TREE_NAME, publisher, platformType, true);
            Map<String, NodeInfoLicenseDTO> nodeInfoMap = tambourineConnector
                    .getNodeInfoLicenseByTreeId(linkTreeId);

            ADSMSchedulerLogDTO contentDataLog = tambourineConnector
                    .getLatestADSMSchedulerLog(ADSMJobNameType.CONTENT_DATA.name());
            Date date = DateUtil.getCurDate();

            Set<String> categoryIdSet = new HashSet<String>();
            List<NodeInfoLicenseDTO> updateCategoryInfoList = new ArrayList<NodeInfoLicenseDTO>();
            List<String> updateCategoryIdList = new ArrayList<String>();

            AxisTreeNodeDTO rootNodeDTO = getRootAxisTreeNode(ROOT_LINK_NODE_NAME);
            int rootNodeId = tambourineConnector.getNodeId(linkTreeId,
                    ConvertContentAxisTreeDTO.ROOT_CONTENT_LINK_PARENT);
            rootNodeDTO.setNodeID(rootNodeId);

            //?  ?? ? idList DB? .
            Map<String, List<String>> targetMap = addNewDisableCategoryIdList(categoryIdList);
            saveTargetMapbyOppType(targetMap, null, TreeType.VOD_CONTENTS_AXIS);

            for (String categoryId : categoryIdList) {
                if (categoryId != null && categoryIdSet.add(categoryId) == true) {
                    NodeInfoLicenseDTO nodeInfo = nodeInfoMap.get(categoryId);
                    if (nodeInfo == null) {
                        updateCategoryInfoList.add(
                                new NodeInfoLicenseDTO(categoryId, null, date, DateUtil.string2Date("9999-12-31")));
                        updateCategoryIdList.add(categoryId);
                    } else if (DateUtil.before(nodeInfo.getLicenseEnd(), date)) {
                        updateCategoryInfoList.add(nodeInfo);
                        updateCategoryIdList.add(categoryId);
                    }
                }
            }

            // ? ?    ?   ?? .
            if (updateCategoryInfoList != null && updateCategoryInfoList.size() > 0) {

                int treeID = tambourineConnector.getAxisTreeId(TreeType.VOD_CONTENTS_AXIS,
                        Constants.tree.CONTENT_TREE_NAME, publisher, platformType, false);
                List<ContentDataDTO> contentDataDTOList = tambourineConnector
                        .getContentDataByCategoryIds(updateCategoryIdList, contentDataLog.getId());

                int updateSize = mergeNode(treeID, ConvertContentAxisTreeDTO.ROOT_CONTENT_PARENT, 1, date,
                        contentDataDTOList);
                log.info("Content Tree Update done Size: " + updateSize + " (add)");

                List<AxisTreeNodeDTO> nodeDTOList = new ArrayList<AxisTreeNodeDTO>();
                for (NodeInfoLicenseDTO nodeInfo : updateCategoryInfoList) {
                    //  ? ??  ?? .               
                    AxisTreeNodeDTO nodeDTO = convertContentLinkData2Node(nodeInfo.getExternalId(), 1,
                            new Period(nodeInfo.getLicenseStart(), DateUtil.string2Date("9999-12-31")),
                            contentDataLog.getId(), nodeInfo.getNodeId(), linkTreeId, rootNodeDTO);

                    nodeDTOList.add(nodeDTO);
                }

                tambourineConnector.saveNodeList(nodeDTOList);
                log.info("Content Link Tree Update Done Size: " + nodeDTOList.size() + " (add)");

                tambourineConnector.saveClosureNodes(treeID);
                tambourineConnector.saveClosureNodes(linkTreeId);
                tambourineConnector.insertTreeLogNSyncNoticeboard(linkTreeId, TreeType.VOD_CONTENTS_AXIS,
                        Constants.tree.CONTENT_LINK_TREE_NAME, null, null, null);
                tambourineConnector.insertTreeLogNSyncNoticeboard(treeID, TreeType.VOD_CONTENTS_AXIS,
                        Constants.tree.CONTENT_TREE_NAME, null, null, null);

                return true;
            }

        } catch (Exception e) {
            log.error(e.getMessage());
            throw e;
        }

        return false;
    }

    private Map<String, List<String>> addNewDisableCategoryIdList(List<String> familyExternalIdList) {
        Map<String, List<String>> targetMap = new HashMap<String, List<String>>();
        for (String updateId : familyExternalIdList) {
            List<String> contentList = new ArrayList<String>();
            contentList.add(ALL_CONTENT);
            targetMap.put(updateId, contentList);
        }
        return targetMap;

    }

    private void mergeLinkNode(int treeID, int level, Date date, List<ContentDataDTO> contentDataDTOList,
            int conSchedulerId) throws Exception {

        try {
            AxisTreeNodeDTO rootNodeDTO = getRootAxisTreeNode(ROOT_LINK_NODE_NAME);
            int rootNodeId = tambourineConnector.getNodeId(treeID,
                    ConvertContentAxisTreeDTO.ROOT_CONTENT_LINK_PARENT);
            rootNodeDTO.setNodeID(rootNodeId);

            Map<String, NodeInfoLicenseDTO> nodeInfoMap = tambourineConnector.getNodeInfoLicenseByTreeId(treeID);

            Set<String> categoryIdSet = new HashSet<String>();
            List<AxisTreeNodeDTO> nodeDTOList = new ArrayList<AxisTreeNodeDTO>();

            for (ContentDataDTO contentDataDTO : contentDataDTOList) {
                if (contentDataDTO.getCatId() != null && categoryIdSet.add(contentDataDTO.getCatId()) == true) {
                    NodeInfoLicenseDTO nodeInfo = nodeInfoMap.get(contentDataDTO.getCatId());
                    AxisTreeNodeDTO nodeDTO = null;

                    if (nodeInfo != null)
                        nodeDTO = convertContentLinkData2Node(contentDataDTO.getCatId(), level,
                                new Period(nodeInfo.getLicenseStart(), DateUtil.string2Date("9999-12-31")),
                                conSchedulerId, nodeInfo.getNodeId(), treeID, rootNodeDTO);
                    else
                        nodeDTO = convertContentLinkData2Node(contentDataDTO.getCatId(), level,
                                new Period(date, DateUtil.string2Date("9999-12-31")), conSchedulerId, null, treeID,
                                rootNodeDTO);
                    nodeDTOList.add(nodeDTO);
                }
            }

            if (nodeDTOList != null && nodeDTOList.size() > 0) {
                tambourineConnector.saveNodeList(nodeDTOList);
            }

            log.info("Content Link Tree Update Done Size: " + categoryIdSet.size());

        } catch (Exception e) {
            log.error(e.getMessage());
            throw e;
        }
    }

    private AxisTreeNodeDTO convertContentLinkData2Node(String categoryId, int level, Period period,
            int conSchedulerId, Integer nodeId, int treeId, AxisTreeNodeDTO parent) {
        if (categoryId == null || categoryId.isEmpty())
            return null;

        AxisTreeNodeDTO axisTreeNodeDTO = null;

        try {
            axisTreeNodeDTO = new AxisTreeNodeDTO();
            axisTreeNodeDTO.setLevel(level);
            axisTreeNodeDTO.setName(categoryId); //TODO ? 
            axisTreeNodeDTO.setReflected(false);
            axisTreeNodeDTO.setMappingId(categoryId);
            axisTreeNodeDTO.setExternalNodeId(categoryId);
            axisTreeNodeDTO.setUseLicensingWindow(true);
            axisTreeNodeDTO.setLicensingPeriod(period);
            axisTreeNodeDTO.setTreeId(treeId);
            axisTreeNodeDTO.setParent(parent);

            if (nodeId != null && nodeId > 0)
                axisTreeNodeDTO.setNodeID(nodeId);

            List<NodeInfoWithLinkNodeDTO> contentNodes = tambourineConnector.getContentNodeInfoByCatId(categoryId,
                    conSchedulerId, (nodeId == null) ? -1 : nodeId);

            if (contentNodes != null) {
                for (NodeInfoWithLinkNodeDTO contentNode : contentNodes) {

                    List<TreeNodeLinkPeriodDTO> linkPeriods = new ArrayList<TreeNodeLinkPeriodDTO>();
                    TreeNodeLinkPeriodDTO treeNodeLinkPeriodDTO = null;
                    if (contentNode.getPeriodId() != null && contentNode.getPeriodId() > 0) {
                        treeNodeLinkPeriodDTO = new TreeNodeLinkPeriodDTO(contentNode.getPeriodId(), period);
                    } else
                        treeNodeLinkPeriodDTO = new TreeNodeLinkPeriodDTO(period);
                    linkPeriods.add(treeNodeLinkPeriodDTO);

                    TreeNodeLinkDTO treeNodeLinkDTO = null;
                    if (contentNode.getLinkId() != null && contentNode.getLinkId() > 0) {
                        treeNodeLinkDTO = new TreeNodeLinkDTO(contentNode.getLinkId(), contentNode.getTreeId(),
                                contentNode.getNodeId(), null, linkPeriods);
                    } else {
                        treeNodeLinkDTO = new TreeNodeLinkDTO(contentNode.getTreeId(), contentNode.getNodeId(),
                                null, linkPeriods);
                    }

                    axisTreeNodeDTO.addExternalLink(treeNodeLinkDTO);
                }
            }

        } catch (Exception e) {
            log.error("Fail to Generate Content Link Node (category Id = " + categoryId + ", nodeId = " + nodeId
                    + ") : ", e);
        }
        return axisTreeNodeDTO;
    }

    private NodeDTO convertContentData2Node(ContentDataDTO contentDataDTO, int level) {

        if (contentDataDTO.getContsId() == null || contentDataDTO.getContsId().isEmpty())
            return null;

        NodeDTO nodeDTO = new NodeDTO();
        nodeDTO.setLevel(level);
        nodeDTO.setName(contentDataDTO.getContsName());
        nodeDTO.setReflected(false);
        nodeDTO.setMappingId(contentDataDTO.getContsId());
        nodeDTO.setExternalNodeId(contentDataDTO.getContsId());
        nodeDTO.setUseLicensingWindow(true);
        return nodeDTO;
    }

    private NodeDTO getContentRootNode(String name) {

        NodeDTO nodeDTO = new NodeDTO();
        nodeDTO.setLevel(0);
        nodeDTO.setName(name);
        nodeDTO.setReflected(false);
        nodeDTO.setMappingId(ROOT_CONTENT_PARENT);
        nodeDTO.setExternalNodeId(ROOT_CONTENT_PARENT);
        nodeDTO.setUseLicensingWindow(true);

        return nodeDTO;
    }

    private NodeDTO getRootNode(String name) {

        NodeDTO nodeDTO = new NodeDTO();
        nodeDTO.setLevel(0);
        nodeDTO.setName(name);
        nodeDTO.setReflected(false);
        nodeDTO.setMappingId(ROOT_CONTENT_LINK_PARENT);
        nodeDTO.setExternalNodeId(ROOT_CONTENT_LINK_PARENT);
        nodeDTO.setUseLicensingWindow(true);

        return nodeDTO;
    }

    private AxisTreeNodeDTO getRootAxisTreeNode(String name) {

        AxisTreeNodeDTO nodeDTO = new AxisTreeNodeDTO();
        nodeDTO.setLevel(0);
        nodeDTO.setName(name);
        nodeDTO.setReflected(false);
        nodeDTO.setMappingId(ROOT_CONTENT_LINK_PARENT);
        nodeDTO.setExternalNodeId(ROOT_CONTENT_LINK_PARENT);
        nodeDTO.setUseLicensingWindow(true);

        return nodeDTO;
    }

    private int makeTreeNode(int treeID, Date date, String externalNodeId, TargetedContentInfo targetedContentInfo,
            boolean bInvalidateAxisTreeNode, int conSchedulerId, String publisher, Platform platformType)
            throws Exception {
        int level = 0;
        if (bInvalidateAxisTreeNode == true) {
            tambourineConnector.invalidateAxisTreeNodeExceptRootNode(treeID, date);
            log.info("invalidate ContentTree ExceptRootNode done");
        }
        //node merge
        int updateSize = mergeNode(treeID, externalNodeId, level + 1, date,
                targetedContentInfo.getContentTargetList());
        log.info("Content Tree Update done Size: " + updateSize);

        int linkTreeId = generateContentLinkTree(targetedContentInfo.getDisableCategoryTargetList(), date,
                bInvalidateAxisTreeNode, conSchedulerId, publisher, platformType);
        //??
        tambourineConnector.saveClosureNodes(linkTreeId);
        tambourineConnector.saveClosureNodes(treeID);

        return linkTreeId;
    }

}