topoXForce.js 5.41 KB
/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 ONOS GUI -- Topology Force Module.
 Visualization of the topology in an SVG layer, using a D3 Force Layout.
 */

(function () {
    'use strict';

    // injected refs
    var $log, wss;

    // selected DOM refs
    var topdiv;

    // ========================== Helper Functions

    function init() {
        topdiv = d3.select('#topoXtmp');
        $log.debug('Initialize topo force layout');
    }

    function destroy() {
        $log.debug('Destroy topo force layout');
    }

    function rmP(div) {
        div.selectAll('p').remove();
    }

    function navRequest(rid) {
        wss.sendEvent('topo2navRegion', {
            rid: rid
        });
    }

    function doTmpInstances(data) {
        var idiv = topdiv.select('.instances').select('div');
        data.members.forEach(function (m) {
            idiv.append('div').text(m.id);
        });
    }

    function doTmpCurrentLayout(data) {
        var ldDiv = topdiv.select('.layoutData'),
            bcs = ldDiv.select('.l_crumbs');

        function setSpan(v, val) {
            var cls = '.l_' + v,
                span = ldDiv.select(cls).select('span'),
                value = val || data[v];
            span.html(value);
        }

        setSpan('id');
        setSpan('parent');
        setSpan('region');
        setSpan('regionName');

        addCrumbNav(bcs, data.crumbs, data.region);
    }

    function addCrumbNav(span, array, id) {
        var rev = [];

        span.selectAll('span').remove();

        array.forEach(function (a) {
            rev.unshift(a.id);
        });

        rev.forEach(function (rid, idx) {
            if (idx) {
                span.append('span').text(' +++ ');
            }
            if (rid != id) {
                addNavigable(span, 'span', rid);
            } else {
                span.append('span').text(rid);
            }
        });
    }

    function addNavigable(span, what, rid) {
        span.append(what).classed('nav-me', true)
            .text(rid)
            .on('click', function () { navRequest(rid); });
    }

    function doTmpCurrentRegion(data) {
        var span = topdiv.select('.thisRegion').select('span');
        var div;
        span.text(data.id);

        div = topdiv.select('.subRegions').select('div');
        rmP(div);
        data.subregions.forEach(function (r) {
            addNavigable(div, 'p', r.id);
        });

        div = topdiv.select('.devices').select('div');
        rmP(div);
        data.layerOrder.forEach(function (tag, idx) {
            var devs = data.devices[idx];
            devs.forEach(function (d) {
                div.append('p')
                    .text('[' + tag + '] ' + d.id);
            });

        });

        div = topdiv.select('.hosts').select('div');
        rmP(div);
        data.layerOrder.forEach(function (tag, idx) {
            var hosts = data.hosts[idx];
            hosts.forEach(function (h) {
                div.append('p')
                    .text('[' + tag + '] ' + h.id);
            });
        });

        div = topdiv.select('.links').select('div');
        rmP(div);
        data.links.forEach(function (lnk) {
            div.append('p')
                .text(lnk.id);
        });
    }

    function doTmpPeerRegions(data) {
        var peerDiv = topdiv.select('.peers').select('div');
        rmP(peerDiv);

        function logPeer(p) {
            var o = peerDiv.append('p'),
                id = p.id,
                nt = p.nodeType;
            o.text('[' + nt + '] id = ' + id);
        }

        data.peers.forEach(function (p) {
            logPeer(p);
        });
    }

    // ========================== Event Handlers

    function allInstances(data) {
        $log.debug('>> topo2AllInstances event:', data);
        doTmpInstances(data);
    }

    function currentLayout(data) {
        $log.debug('>> topo2CurrentLayout event:', data);
        doTmpCurrentLayout(data);
    }

    function currentRegion(data) {
        $log.debug('>> topo2CurrentRegion event:', data);
        doTmpCurrentRegion(data);
    }

    function peerRegions(data) {
        $log.debug('>> topo2PeerRegions event:', data);
        doTmpPeerRegions(data);
    }

    function startDone(data) {
        $log.debug('>> topo2StartDone event:', data);
    }
    
    // ========================== Main Service Definition

    angular.module('ovTopoX')
    .factory('TopoXForceService',
        ['$log', 'WebSocketService',

        function (_$log_, _wss_) {
            $log = _$log_;
            wss = _wss_;
            
            return {
                init: init,
                destroy: destroy,
                topo2AllInstances: allInstances,
                topo2CurrentLayout: currentLayout,
                topo2CurrentRegion: currentRegion,
                topo2PeerRegions: peerRegions,
                topo2StartDone: startDone
            };
        }]);
}());