<commit_before>'use strict';

pinpointApp.constant('serverMapConfig', {
    serverMapDataUrl: '/getServerMapData.pinpoint',
    filteredServerMapDataUrl: '/getFilteredServerMapData.pinpoint',
    filtermapUrl: '/filtermap.pinpoint',
    lastTransactionListUrl: '/lastTransactionList.pinpoint',
    transactionListUrl: '/transactionList.pinpoint',
    options: {
        "sContainerId": 'servermap',
        "sImageDir": '/images/icons/',
        "htIcons": {
            'APACHE': 'APACHE.png',
            'ARCUS': 'ARCUS.png',
            'CUBRID': 'CUBRID.png',
            'ETC': 'ETC.png',
            'MEMCACHED': 'MEMCACHED.png',
            'MYSQL': 'MYSQL.png',
            'QUEUE': 'QUEUE.png',
            'TOMCAT': 'TOMCAT.png',
            'UNKNOWN_CLOUD': 'UNKNOWN_CLOUD.png',
            'UNKNOWN_GROUP': 'UNKNOWN_CLOUD.png',
            'USER': 'USER.png',
            'ORACLE': 'ORACLE.png'
        },
        "htLinkType": {
            "sRouting": "AvoidsNodes", // Normal, Orthogonal, AvoidNodes
            "sCurve": "JumpGap" // Bezier, JumpOver, JumpGap
        }
    },
    FILTER_DELIMETER: "^",
    FILTER_ENTRY_DELIMETER: "|",
    FILTER_FETCH_LIMIT: 3
});

pinpointApp.directive('serverMap', [ 'serverMapConfig', '$rootScope', '$window', 'Alerts', 'ProgressBar', function (cfg, $rootScope, $window, Alerts, ProgressBar) {
    return {
        restrict: 'EA',
        replace: true,
        templateUrl: 'views/serverMap.html',
        link: function postLink(scope, element, attrs) {

            // define private variables
            var serverMapCachedQuery, serverMapCachedData, bUseNodeContextMenu, bUseLinkContextMenu,
                bUseBackgroundContextMenu, oServerMap, SERVERMAP_METHOD_CACHE, oAlert, oProgressBar, htLastMapData;

            // define private variables of methods
            var showServerMap, getServerMapData, getFilteredServerMapData, reset, setNodeContextMenuPosition,
                setLinkContextMenuPosition, setBackgroundContextMenuPosition, serverMapCallback, mergeUnknown,
                setLinkOption, mergeFilteredMapData, findExistingNodeFromLastMapData, mergeNodeData,
                findExistingLinkFromLastMapData, mergeLinkData;

            // initialize
            oServerMap = null;
            SERVERMAP_METHOD_CACHE = {};
            htLastMapData = {
                applicationMapData : {
                    linkDataArray : [],
                    nodeDataArray : []
                },
                lastFetchedTimestamp : []
            };
            oAlert = new Alerts(element);
            oProgressBar = new ProgressBar(element);
            scope.oNavbar = null;
            scope.mergeUnknowns = true;
            scope.totalRequestCount = true;
            scope.bShowServerMapStatus = false;
            scope.linkRouting = cfg.options.htLinkType.sRouting;
            scope.linkCurve = cfg.options.htLinkType.sCurve;

            /**
             * show server map
             * @param applicationName
             * @param serviceType
             * @param to
             * @param period
             * @param filterText
             * @param mergeUnknowns
             * @param linkRouting
             * @param linkCurve
             */
            showServerMap = function (applicationName, serviceType, to, period, filterText, mergeUnknowns, linkRouting, linkCurve) {
                oProgressBar.startLoading();
                if (oServerMap) {
                    oServerMap.clear();
                }
                oProgressBar.setLoading(10);

                var query = {
                    applicationName: applicationName,
                    serviceType: serviceType,
                    from: to - period,
                    to: to,
                    period: period,
                    filter: filterText
                };

                if (filterText) {
                    getFilteredServerMapData(query, function (query, result) {
                        if (query.from === result.lastFetchedTimestamp) {
                            scope.$emit('serverMap.allFetched');
                        } else {
                            htLastMapData.lastFetchedTimestamp = result.lastFetchedTimestamp - 1;
                            scope.$emit('serverMap.fetched', htLastMapData.lastFetchedTimestamp, result.applicationMapData.nodeDataArray.length);
                        }
                        serverMapCallback(query, mergeFilteredMapData(result), mergeUnknowns, linkRouting, linkCurve);
                    });
                } else {
                    getServerMapData(query, function (query, result) {
                        serverMapCallback(query, result, mergeUnknowns, linkRouting, linkCurve);
                    });
                }
            };

            /**
             * merge filtered map data
             * @param mapData
             * @returns {{applicationMapData: {linkDataArray: Array, nodeDataArray: Array}, lastFetchedTimestamp: Array}}
             */
            mergeFilteredMapData = function (mapData) {
                if (htLastMapData.applicationMapData.linkDataArray.length === 0 && htLastMapData.applicationMapData.nodeDataArray.length === 0) {
                    htLastMapData.applicationMapData.linkDataArray = mapData.applicationMapData.linkDataArray;
                    htLastMapData.applicationMapData.nodeDataArray = mapData.applicationMapData.nodeDataArray;
                } else {
                    var newKey = {};
                    angular.forEach(mapData.applicationMapData.nodeDataArray, function (node, key) {
                        var foundNodeKeyFromLastMapData = findExistingNodeFromLastMapData(node);
                        if (foundNodeKeyFromLastMapData) {
                            mergeNodeData(foundNodeKeyFromLastMapData, node);
                            newKey[node.key] = foundNodeKeyFromLastMapData;
                        } else {
                            node.key = node.id = newKey[node.key] = htLastMapData.applicationMapData.nodeDataArray.length + 1;
                            htLastMapData.applicationMapData.nodeDataArray.push(node);
                        }
                    });
                    angular.forEach(mapData.applicationMapData.linkDataArray, function (link, key) {
                        var foundLinkKeyFromLastMapData = findExistingLinkFromLastMapData(link, newKey);
                        if (foundLinkKeyFromLastMapData) {
                            mergeLinkData(foundLinkKeyFromLastMapData, link);
                        } else {
                            link.from = newKey[link.from];
                            link.to = newKey[link.to];
                            link.id = [link.from, '-', link.to].join('');
                            htLastMapData.applicationMapData.linkDataArray.push(link);
                        }
                    });
                }
                return htLastMapData;
            };

            /**
             * find existing node from last map data
             * @param node
             * @returns {*}
             */
            findExistingNodeFromLastMapData = function (node) {
                for (var key in htLastMapData.applicationMapData.nodeDataArray) {
                    if (htLastMapData.applicationMapData.nodeDataArray[key].text === node.text && htLastMapData.applicationMapData.nodeDataArray[key].serviceTypeCode === node.serviceTypeCode) {
                        return htLastMapData.applicationMapData.nodeDataArray[key].key;
                    }
                }
                return false;
            };

            /**
             * merge node data
             * @param nodeKey
             * @param node
             */
            mergeNodeData = function (nodeKey, node) {
                for (var key in node.serverList) {
                    if (htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key]) {
                        for (var innerKey in node.serverList[key].instanceList) {
                            if (htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey]) {
                                for (var insideKey in node.serverList[key].instanceList[innerKey].histogram) {
                                    if (htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey].histogram[insideKey]) {
                                        htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey].histogram[insideKey] += node.serverList[key].instanceList[innerKey].histogram[insideKey];
                                    } else {
                                        htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey].histogram[insideKey] = node.serverList[key].instanceList[innerKey].histogram[insideKey];
                                    }
                                }
                            } else {
                                htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey] = node.serverList[key].instanceList[innerKey];
                            }
                        }
                    } else {
                        htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key] = node.serverList[key];
                    }
                }
            };

            /**
             * find existing link from last map data
             * @param link
             * @param newKey
             * @returns {*}
             */
            findExistingLinkFromLastMapData = function (link, newKey) {
                for (var key in htLastMapData.applicationMapData.linkDataArray) {
                    console.log(htLastMapData.applicationMapData.linkDataArray[key].from , newKey[link.from] , htLastMapData.applicationMapData.linkDataArray[key].to , newKey[link.to]);
                    if (htLastMapData.applicationMapData.linkDataArray[key].from === newKey[link.from] && htLastMapData.applicationMapData.linkDataArray[key].to === newKey[link.to]) {
                        return key;
                    }
                }
                return false;
            };

            /**
             * merge link data
             * @param linkKey
             * @param link
             */
            mergeLinkData = function (linkKey, link) {
                htLastMapData.applicationMapData.linkDataArray[linkKey].text += link.text;
                htLastMapData.applicationMapData.linkDataArray[linkKey].error += link.error;
                htLastMapData.applicationMapData.linkDataArray[linkKey].slow += link.slow;
                for (var key in link.histogram) {
                    if (htLastMapData.applicationMapData.linkDataArray[linkKey].histogram[key]) {
                        htLastMapData.applicationMapData.linkDataArray[linkKey].histogram[key] += link.histogram[key];
                    } else {
                        htLastMapData.applicationMapData.linkDataArray[linkKey].histogram[key] = link.histogram[key];
                    }
                }
                for (var key in link.targetHosts) {
                    if (htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key]) {
                        for (var innerKey in link.targetHosts[key].histogram) {
                            if (htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key].histogram[innerKey]) {
                                htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key].histogram[innerKey] += link.targetHosts[key].histogram[innerKey];
                            } else {
                                htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key].histogram[innerKey] = link.targetHosts[key].histogram[innerKey];
                            }
                        }
                    } else {
                        htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key] = link.targetHosts[key];
                    }
                }
            };

            /**
             * get server map data 2
             * @param query
             * @param callback
             */
            getServerMapData = function (query, callback) {
                oProgressBar.setLoading(50);
                jQuery.ajax({
                    type: 'GET',
                    url: cfg.serverMapDataUrl,
                    cache: false,
                    dataType: 'json',
                    data: {
                        application: query.applicationName,
                        serviceType: query.serviceType,
                        from: query.from,
                        to: query.to
                    },
                    success: function (result) {
                        oProgressBar.setLoading(30);
                        callback(query, result);
                    },
                    error: function (xhr, status, error) {
                        console.log("ERROR", status, error);
                        oProgressBar.stopLoading();
                        oAlert.showError('There is some error.');
                    }
                });
            };

            /**
             * get filtered server map data
             * @param query
             * @param callback
             */
            getFilteredServerMapData = function (query, callback) {
                oProgressBar.setLoading(30);
                jQuery.ajax({
                    type: 'GET',
                    url: cfg.filteredServerMapDataUrl,
                    cache: false,
                    dataType: 'json',
                    data: {
                        application: query.applicationName,
                        serviceType: query.serviceType,
                        from: query.from,
                        to: query.to,
                        filter: query.filter,
                        limit: cfg.FILTER_FETCH_LIMIT
                    },
                    success: function (result) {<commit_msg>[임대현] [NOBTS] servermap mergenode 하는거 수정<commit_after>'use strict';

pinpointApp.constant('serverMapConfig', {
    serverMapDataUrl: '/getServerMapData.pinpoint',
    filteredServerMapDataUrl: '/getFilteredServerMapData.pinpoint',
    filtermapUrl: '/filtermap.pinpoint',
    lastTransactionListUrl: '/lastTransactionList.pinpoint',
    transactionListUrl: '/transactionList.pinpoint',
    options: {
        "sContainerId": 'servermap',
        "sImageDir": '/images/icons/',
        "htIcons": {
            'APACHE': 'APACHE.png',
            'ARCUS': 'ARCUS.png',
            'CUBRID': 'CUBRID.png',
            'ETC': 'ETC.png',
            'MEMCACHED': 'MEMCACHED.png',
            'MYSQL': 'MYSQL.png',
            'QUEUE': 'QUEUE.png',
            'TOMCAT': 'TOMCAT.png',
            'UNKNOWN_CLOUD': 'UNKNOWN_CLOUD.png',
            'UNKNOWN_GROUP': 'UNKNOWN_CLOUD.png',
            'USER': 'USER.png',
            'ORACLE': 'ORACLE.png'
        },
        "htLinkType": {
            "sRouting": "AvoidsNodes", // Normal, Orthogonal, AvoidNodes
            "sCurve": "JumpGap" // Bezier, JumpOver, JumpGap
        }
    },
    FILTER_DELIMETER: "^",
    FILTER_ENTRY_DELIMETER: "|",
    FILTER_FETCH_LIMIT: 3
});

pinpointApp.directive('serverMap', [ 'serverMapConfig', '$rootScope', '$window', 'Alerts', 'ProgressBar', function (cfg, $rootScope, $window, Alerts, ProgressBar) {
    return {
        restrict: 'EA',
        replace: true,
        templateUrl: 'views/serverMap.html',
        link: function postLink(scope, element, attrs) {

            // define private variables
            var serverMapCachedQuery, serverMapCachedData, bUseNodeContextMenu, bUseLinkContextMenu,
                bUseBackgroundContextMenu, oServerMap, SERVERMAP_METHOD_CACHE, oAlert, oProgressBar, htLastMapData;

            // define private variables of methods
            var showServerMap, getServerMapData, getFilteredServerMapData, reset, setNodeContextMenuPosition,
                setLinkContextMenuPosition, setBackgroundContextMenuPosition, serverMapCallback, mergeUnknown,
                setLinkOption, mergeFilteredMapData, findExistingNodeFromLastMapData, mergeNodeData,
                findExistingLinkFromLastMapData, mergeLinkData;

            // initialize
            oServerMap = null;
            SERVERMAP_METHOD_CACHE = {};
            htLastMapData = {
                applicationMapData : {
                    linkDataArray : [],
                    nodeDataArray : []
                },
                lastFetchedTimestamp : []
            };
            oAlert = new Alerts(element);
            oProgressBar = new ProgressBar(element);
            scope.oNavbar = null;
            scope.mergeUnknowns = true;
            scope.totalRequestCount = true;
            scope.bShowServerMapStatus = false;
            scope.linkRouting = cfg.options.htLinkType.sRouting;
            scope.linkCurve = cfg.options.htLinkType.sCurve;

            /**
             * show server map
             * @param applicationName
             * @param serviceType
             * @param to
             * @param period
             * @param filterText
             * @param mergeUnknowns
             * @param linkRouting
             * @param linkCurve
             */
            showServerMap = function (applicationName, serviceType, to, period, filterText, mergeUnknowns, linkRouting, linkCurve) {
                oProgressBar.startLoading();
                if (oServerMap) {
                    oServerMap.clear();
                }
                oProgressBar.setLoading(10);

                var query = {
                    applicationName: applicationName,
                    serviceType: serviceType,
                    from: to - period,
                    to: to,
                    period: period,
                    filter: filterText
                };

                if (filterText) {
                    getFilteredServerMapData(query, function (query, result) {
                        if (query.from === result.lastFetchedTimestamp) {
                            scope.$emit('serverMap.allFetched');
                        } else {
                            htLastMapData.lastFetchedTimestamp = result.lastFetchedTimestamp - 1;
                            scope.$emit('serverMap.fetched', htLastMapData.lastFetchedTimestamp, result.applicationMapData.nodeDataArray.length);
                        }
                        serverMapCallback(query, mergeFilteredMapData(result), mergeUnknowns, linkRouting, linkCurve);
                    });
                } else {
                    getServerMapData(query, function (query, result) {
                        serverMapCallback(query, result, mergeUnknowns, linkRouting, linkCurve);
                    });
                }
            };

            /**
             * merge filtered map data
             * @param mapData
             * @returns {{applicationMapData: {linkDataArray: Array, nodeDataArray: Array}, lastFetchedTimestamp: Array}}
             */
            mergeFilteredMapData = function (mapData) {
                if (htLastMapData.applicationMapData.linkDataArray.length === 0 && htLastMapData.applicationMapData.nodeDataArray.length === 0) {
                    htLastMapData.applicationMapData.linkDataArray = mapData.applicationMapData.linkDataArray;
                    htLastMapData.applicationMapData.nodeDataArray = mapData.applicationMapData.nodeDataArray;
                } else {
                    var newKey = {};
                    angular.forEach(mapData.applicationMapData.nodeDataArray, function (node, key) {
                        var foundNodeKeyFromLastMapData = findExistingNodeFromLastMapData(node);
                        if (foundNodeKeyFromLastMapData) {
                            mergeNodeData(foundNodeKeyFromLastMapData - 1, node);
                            newKey[node.key] = foundNodeKeyFromLastMapData;
                        } else {
                            node.key = node.id = newKey[node.key] = htLastMapData.applicationMapData.nodeDataArray.length + 1;
                            htLastMapData.applicationMapData.nodeDataArray.push(node);
                        }
                    });
                    angular.forEach(mapData.applicationMapData.linkDataArray, function (link, key) {
                        var foundLinkKeyFromLastMapData = findExistingLinkFromLastMapData(link, newKey);
                        if (foundLinkKeyFromLastMapData) {
                            mergeLinkData(foundLinkKeyFromLastMapData, link);
                        } else {
                            link.from = newKey[link.from];
                            link.to = newKey[link.to];
                            link.id = [link.from, '-', link.to].join('');
                            htLastMapData.applicationMapData.linkDataArray.push(link);
                        }
                    });
                }
                return htLastMapData;
            };

            /**
             * find existing node from last map data
             * @param node
             * @returns {*}
             */
            findExistingNodeFromLastMapData = function (node) {
                for (var key in htLastMapData.applicationMapData.nodeDataArray) {
                    if (htLastMapData.applicationMapData.nodeDataArray[key].text === node.text && htLastMapData.applicationMapData.nodeDataArray[key].serviceTypeCode === node.serviceTypeCode) {
                        return htLastMapData.applicationMapData.nodeDataArray[key].key;
                    }
                }
                return false;
            };

            /**
             * merge node data
             * @param nodeKey
             * @param node
             */
            mergeNodeData = function (nodeKey, node) {
                for (var key in node.serverList) {
//                    if (angular.isUndefined(htLastMapData.applicationMapData.nodeDataArray[nodeKey])) {
//                        htLastMapData.applicationMapData.nodeDataArray[nodeKey] = {
//                            serverList: []
//                        };
//                    }
                    if (htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key]) {
                        for (var innerKey in node.serverList[key].instanceList) {
                            if (htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey]) {
                                for (var insideKey in node.serverList[key].instanceList[innerKey].histogram) {
                                    if (htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey].histogram[insideKey]) {
                                        htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey].histogram[insideKey] += node.serverList[key].instanceList[innerKey].histogram[insideKey];
                                    } else {
                                        htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey].histogram[insideKey] = node.serverList[key].instanceList[innerKey].histogram[insideKey];
                                    }
                                }
                            } else {
                                htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key].instanceList[innerKey] = node.serverList[key].instanceList[innerKey];
                            }
                        }
                    } else {
                        htLastMapData.applicationMapData.nodeDataArray[nodeKey].serverList[key] = node.serverList[key];
                    }
                }
            };

            /**
             * find existing link from last map data
             * @param link
             * @param newKey
             * @returns {*}
             */
            findExistingLinkFromLastMapData = function (link, newKey) {
                for (var key in htLastMapData.applicationMapData.linkDataArray) {
                    console.log(htLastMapData.applicationMapData.linkDataArray[key].from , newKey[link.from] , htLastMapData.applicationMapData.linkDataArray[key].to , newKey[link.to]);
                    if (htLastMapData.applicationMapData.linkDataArray[key].from === newKey[link.from] && htLastMapData.applicationMapData.linkDataArray[key].to === newKey[link.to]) {
                        return key;
                    }
                }
                return false;
            };

            /**
             * merge link data
             * @param linkKey
             * @param link
             */
            mergeLinkData = function (linkKey, link) {
                htLastMapData.applicationMapData.linkDataArray[linkKey].text += link.text;
                htLastMapData.applicationMapData.linkDataArray[linkKey].error += link.error;
                htLastMapData.applicationMapData.linkDataArray[linkKey].slow += link.slow;
                for (var key in link.histogram) {
                    if (htLastMapData.applicationMapData.linkDataArray[linkKey].histogram[key]) {
                        htLastMapData.applicationMapData.linkDataArray[linkKey].histogram[key] += link.histogram[key];
                    } else {
                        htLastMapData.applicationMapData.linkDataArray[linkKey].histogram[key] = link.histogram[key];
                    }
                }
                for (var key in link.targetHosts) {
                    if (htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key]) {
                        for (var innerKey in link.targetHosts[key].histogram) {
                            if (htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key].histogram[innerKey]) {
                                htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key].histogram[innerKey] += link.targetHosts[key].histogram[innerKey];
                            } else {
                                htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key].histogram[innerKey] = link.targetHosts[key].histogram[innerKey];
                            }
                        }
                    } else {
                        htLastMapData.applicationMapData.linkDataArray[linkKey].targetHosts[key] = link.targetHosts[key];
                    }
                }
            };

            /**
             * get server map data 2
             * @param query
             * @param callback
             */
            getServerMapData = function (query, callback) {
                oProgressBar.setLoading(50);
                jQuery.ajax({
                    type: 'GET',
                    url: cfg.serverMapDataUrl,
                    cache: false,
                    dataType: 'json',
                    data: {
                        application: query.applicationName,
                        serviceType: query.serviceType,
                        from: query.from,
                        to: query.to
                    },
                    success: function (result) {
                        oProgressBar.setLoading(30);
                        callback(query, result);
                    },
                    error: function (xhr, status, error) {
                        console.log("ERROR", status, error);
                        oProgressBar.stopLoading();
                        oAlert.showError('There is some error.');
                    }
                });
            };

            /**
             * get filtered server map data
             * @param query
             * @param callback
             */
            getFilteredServerMapData = function (query, callback) {
                oProgressBar.setLoading(30);
                var url;
                if (oServerMap) {
                    url = 'test2.json';
                } else {
                    url = 'test1.json';
                }
                jQuery.ajax({
                    type: 'GET',
//                    url: cfg.filteredServerMapDataUrl,
                    url: url,
                    cache: false,
                    dataType: 'json',
                    data: {
                        application: query.applicationName,
                        serviceType: query.serviceType,
                        from: query.from,
                        to: query.to,
                        filter: query.filter,
                        limit: cfg.FILTER_FETCH_LIMIT
                    },
                    success: function (result) {
{'fraction_non_alphanumeric': 0.09098771838782217, 'fraction_numerical': 0.001072478809894482, 'mean_word_length': 1.43994260150249, 'pattern_counts': {'":': 12, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7313058', 'n_tokens_mistral': 7259, 'n_tokens_neox': 6916, 'n_words': 1105}