ONOS-1479 -- GUI - augmenting topology view for extensibility:
- Preliminary work in implementing installation of custom buttons to details panel for selected device.

Change-Id: Id26ac301f72b4521d2a388d34ee0a287f400c68c
diff --git a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
index e2b3125..9dddc9b 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
@@ -44,26 +44,36 @@
         $log.warn(tos + fn + '(): ' + msg);
     }
 
-    function handleGlyph(o) {
-        var gdata = fs.isO(o.glyph),
-            oid,
-            data = {};
+    function mkGlyphId(oid, gid) {
+        return (gid[0] === '*') ? oid + '-' + gid.slice(1) : gid;
+    }
 
-        if (!gdata) {
-            o._glyphId = 'unknown';
-        } else {
-            if (gdata.id) {
-                o._glyphId = gdata.id;
-            } else if (gdata.vb && gdata.d) {
-                oid = o.overlayId;
-                data['_' + oid] = gdata.vb;
-                data[oid] = gdata.d;
-                gs.registerGlyphs(data);
-                o._glyphId = oid;
-                $log.debug('registered overlay glyph:', oid);
-            } else {
-                warn('registerGlyph', 'problem with glyph data');
-            }
+    function handleGlyphs(o) {
+        var gdata = fs.isO(o.glyphs),
+            oid = o.overlayId,
+            gid = o.glyphId || 'unknown',
+            data = {},
+            note = [];
+
+        o._glyphId = mkGlyphId(oid, gid);
+
+        o.mkGid = function (g) {
+            return mkGlyphId(oid, g);
+        };
+        o.mkId = function (s) {
+            return oid + '-' + s;
+        };
+
+        // process glyphs if defined
+        if (gdata) {
+            angular.forEach(gdata, function (value, key) {
+                var fullkey = oid + '-' + key;
+                data['_' + fullkey] = value.vb;
+                data[fullkey] = value.d;
+                note.push('*' + key);
+            });
+            gs.registerGlyphs(data);
+            $log.debug('registered overlay glyphs:', oid, note);
         }
     }
 
@@ -79,7 +89,7 @@
             return warn(r, 'already registered: "' + id + '"');
         }
         overlays[id] = overlay;
-        handleGlyph(overlay);
+        handleGlyphs(overlay);
         $log.debug(tos + 'registered overlay: ' + id, overlay);
     }
 
@@ -132,6 +142,28 @@
         }
     }
 
+    // install buttons from the current overlay
+    function installButtons(bids, addFn, data) {
+        if (current) {
+            bids.forEach(function (bid) {
+                var btn = current.buttons[bid],
+                    funcWrap = function () {
+                        btn.cb(data);
+                    };
+
+                if (btn) {
+                    addFn({
+                        id: current.mkId(bid),
+                        gid: current.mkGid(btn.gid),
+                        cb: funcWrap,
+                        tt: btn.tt
+                    });
+                }
+            });
+        }
+
+    }
+
     angular.module('ovTopo')
     .factory('TopoOverlayService',
         ['$log', 'FnService', 'GlyphService', 'WebSocketService',
@@ -147,7 +179,8 @@
                 unregister: unregister,
                 list: list,
                 overlay: overlay,
-                tbSelection: tbSelection
+                tbSelection: tbSelection,
+                installButtons: installButtons
             }
         }]);
 
diff --git a/web/gui/src/main/webapp/app/view/topo/topoSelect.js b/web/gui/src/main/webapp/app/view/topo/topoSelect.js
index 051ce05..c02ef51 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoSelect.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoSelect.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected refs
-    var $log, fs, wss, tps, tts, ns;
+    var $log, fs, wss, tov, tps, tts, ns;
 
     // api to topoForce
     var api;
@@ -229,9 +229,13 @@
     //  Event Handlers
 
     function showDetails(data) {
+        var buttons = fs.isA(data.buttons);
+
         // display the data for the single selected node
         tps.displaySingle(data);
 
+        // TODO: use server-side-button-descriptors to add buttons
+
         // always add the 'show traffic' action
         tps.addAction({
             id: '-sin-rel-traf-btn',
@@ -249,6 +253,13 @@
                 tt: 'Show Device Flows'
             });
         }
+
+        // TODO: for now, install overlay buttons here
+        if (buttons) {
+            tov.installButtons(buttons, tps.addAction, data);
+        }
+
+
         // TODO: have the server return explicit class and ID of each node
         // for now, we assume the node is a device if it has a URI
         if ((data.props).hasOwnProperty('URI')) {
@@ -308,13 +319,14 @@
 
     angular.module('ovTopo')
     .factory('TopoSelectService',
-        ['$log', 'FnService', 'WebSocketService',
+        ['$log', 'FnService', 'WebSocketService', 'TopoOverlayService',
             'TopoPanelService', 'TopoTrafficService', 'NavService',
 
-        function (_$log_, _fs_, _wss_, _tps_, _tts_, _ns_) {
+        function (_$log_, _fs_, _wss_, _tov_, _tps_, _tts_, _ns_) {
             $log = _$log_;
             fs = _fs_;
             wss = _wss_;
+            tov = _tov_;
             tps = _tps_;
             tts = _tts_;
             ns = _ns_;
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
index 1da60c1..71cb94c 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
@@ -29,7 +29,7 @@
     // traffic overlay definition
     var overlay = {
         overlayId: 'traffic',
-        glyph: { id: 'allTraffic' },
+        glyphId: 'allTraffic',
         tooltip: 'Traffic Overlay',
 
         activate: activateTraffic,