ONOS-2186 - GUI Topo Overlay - (WIP)
- Basic ability to visually suppress (two levels) other links/nodes, added to Highlights model.
- Added javadocs to Highlights class.
- Added unit tests for Highlights and TopoJson classes.

Change-Id: Id7a9990dcbad20139a4dab89cf54e476c2174ec0
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.css b/web/gui/src/main/webapp/app/view/topo/topo.css
index f26f478..f4b089a 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.css
+++ b/web/gui/src/main/webapp/app/view/topo/topo.css
@@ -323,6 +323,10 @@
 /* --- Topo Nodes --- */
 
 #ov-topo svg .suppressed {
+    opacity: 0.5 !important;
+}
+
+#ov-topo svg .suppressedmax {
     opacity: 0.2 !important;
 }
 
diff --git a/web/gui/src/main/webapp/app/view/topo/topoFilter.js b/web/gui/src/main/webapp/app/view/topo/topoFilter.js
index 1226664..f9b96ae 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoFilter.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoFilter.js
@@ -33,6 +33,8 @@
      link()     // get ref to D3 selection of links
      */
 
+    var smax = 'suppressedmax';
+
     // which "layer" a particular item "belongs to"
     var layerLookup = {
             host: {
@@ -93,23 +95,21 @@
         api.node().each(function (d) {
             var node = d.el;
             if (inLayer(d, which)) {
-                node.classed('suppressed', false);
+                node.classed(smax, false);
             }
         });
 
         api.link().each(function (d) {
             var link = d.el;
             if (inLayer(d, which)) {
-                link.classed('suppressed', false);
+                link.classed(smax, false);
             }
         });
     }
 
     function suppressLayers(b) {
-        api.node().classed('suppressed', b);
-        api.link().classed('suppressed', b);
-//        d3.selectAll('svg .port').classed('inactive', false);
-//        d3.selectAll('svg .portText').classed('inactive', false);
+        api.node().classed(smax, b);
+        api.link().classed(smax, b);
     }
 
     function showLayer(which) {
diff --git a/web/gui/src/main/webapp/app/view/topo/topoForce.js b/web/gui/src/main/webapp/app/view/topo/topoForce.js
index f3c053e..555fa50 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -491,16 +491,37 @@
         suppressLayers(true);
         node.each(function (n) {
             if (n.master === id) {
-                n.el.classed('suppressed', false);
+                n.el.classed('suppressedmax', false);
             }
         });
     }
 
-    function suppressLayers(b) {
-        node.classed('suppressed', b);
-        link.classed('suppressed', b);
-//        d3.selectAll('svg .port').classed('inactive', b);
-//        d3.selectAll('svg .portText').classed('inactive', b);
+    function supAmt(less) {
+        return less ? "suppressed" : "suppressedmax";
+    }
+
+    function suppressLayers(b, less) {
+        var cls = supAmt(less);
+        node.classed(cls, b);
+        link.classed(cls, b);
+    }
+
+    function unsuppressNode(id, less) {
+        var cls = supAmt(less);
+        node.each(function (n) {
+            if (n.id === id) {
+                n.el.classed(cls, false);
+            }
+        });
+    }
+
+    function unsuppressLink(id, less) {
+        var cls = supAmt(less);
+        link.each(function (n) {
+            if (n.id === id) {
+                n.el.classed(cls, false);
+            }
+        });
     }
 
     function showBadLinks() {
@@ -900,8 +921,12 @@
         return {
             clearLinkTrafficStyle: clearLinkTrafficStyle,
             removeLinkLabels: removeLinkLabels,
+            findLinkById: tms.findLinkById,
             updateLinks: updateLinks,
-            findLinkById: tms.findLinkById
+            updateNodes: updateNodes,
+            supLayers: suppressLayers,
+            unsupNode: unsuppressNode,
+            unsupLink: unsuppressLink
         };
     }
 
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 85dc0ff..4a432e0 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
@@ -294,18 +294,34 @@
     }
 
     function showHighlights(data) {
+        var less;
+
         /*
            API to topoForce
              clearLinkTrafficStyle()
              removeLinkLabels()
-             updateLinks()
              findLinkById( id )
+             updateLinks()
+             updateNodes()
+             supLayers( bool, [less] )
+             unsupNode( id, [less] )
+             unsupLink( id, [less] )
          */
 
         // TODO: clear node highlighting
         api.clearLinkTrafficStyle();
         api.removeLinkLabels();
 
+        // handle element suppression
+        if (data.subdue) {
+            less = data.subdue === 'min';
+            api.supLayers(true, less);
+
+        } else {
+            api.supLayers(false);
+            api.supLayers(false, true);
+        }
+
         // TODO: device and host highlights
 
         data.links.forEach(function (lnk) {
@@ -314,6 +330,7 @@
                 units, portcls, magnitude;
 
             if (ldata && !ldata.el.empty()) {
+                api.unsupLink(ldata.id, less);
                 ldata.el.classed(lnk.css, true);
                 ldata.label = lab;
 
@@ -334,7 +351,7 @@
             }
         });
 
-        // TODO: api.updateNodes()
+        api.updateNodes();
         api.updateLinks();
     }