[ONOS-4159] PCE Web GUI implementation:PCE overlay app specific link details display

Change-Id: Id944a7ddfb7ec1c6c934520253b6eff716810f63
diff --git a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
index 95e9f1f..72f0118 100644
--- a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
+++ b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
@@ -431,7 +431,6 @@
                 lspTypeVal = LspType.SR_WITHOUT_SIGNALLING;
                 break;
             default:
-                log.error("Invalid LSP type");
                 break;
         }
 
@@ -539,7 +538,6 @@
             costTypeVal = CostConstraint.Type.TE_COST;
             break;
         default:
-            log.error("Invalid cost type");
             break;
         }
 
@@ -660,12 +658,17 @@
         tunnelSet = tunnelService.queryTunnel(MPLS);
         for (Tunnel tunnel : tunnelSet) {
             if (tunnel.path() == null) {
-                log.info("path does not exist");
+                log.error("path does not exist");
                 return;
             }
             paths.add(tunnel.path());
         }
 
+        if (tunnelSet.size() == 0) {
+            log.warn("Tunnel does not exist");
+            return;
+        }
+
         ImmutableSet.Builder<Link> builder = ImmutableSet.builder();
         allPathLinks = buildPaths(builder).build();
         hilightAndSendPaths();
diff --git a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovOverlay.java b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovOverlay.java
index 41f3243..044b7a2 100644
--- a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovOverlay.java
+++ b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovOverlay.java
@@ -17,18 +17,28 @@
 package org.onosproject.pceweb;
 
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.onlab.util.Bandwidth;
 import org.onosproject.net.AnnotationKeys;
 import org.onosproject.net.Annotations;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
 import org.onosproject.ui.UiTopoOverlay;
 import org.onosproject.ui.topo.ButtonId;
 import org.onosproject.ui.topo.PropertyPanel;
 import org.onosproject.net.HostId;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.link.LinkEvent;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.DiscreteResource;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
 import org.onosproject.ui.topo.TopoConstants.CoreButtons;
-
-import static org.onosproject.ui.topo.TopoConstants.Properties.*;
 import org.onosproject.cli.AbstractShellCommand;
 
 /**
@@ -42,7 +52,9 @@
 
     public static final String AS_NUMBER = "asNumber";
     public static final String DOMAIN_IDENTIFIER = "domainIdentifier";
-    public static final String ROUTING_UNIVERSE = "routingUniverse";
+    public static final String ABR_BIT = "abrBit";
+    public static final String ASBR_BIT = "externalBit";
+    public static final String TE_METRIC = "teCost";
 
     private static final ButtonId SRC_BUTTON = new ButtonId("src");
     private static final ButtonId DST_BUTTON = new ButtonId("dst");
@@ -77,34 +89,75 @@
          if (deviceService != null) {
 
             Device device = deviceService.getDevice(deviceId);
-            Annotations annot = device.annotations();
+            Annotations annots = device.annotations();
 
-            String routerId = annot.value(AnnotationKeys.ROUTER_ID);
-            String type = annot.value(AnnotationKeys.TYPE);
-            String asNumber = annot.value(AS_NUMBER);
-            String domain = annot.value(DOMAIN_IDENTIFIER);
-            String routingUnverse = annot.value(ROUTING_UNIVERSE);
+            String routerId = annots.value(AnnotationKeys.ROUTER_ID);
+            String type = annots.value(AnnotationKeys.TYPE);
+            String asNumber = annots.value(AS_NUMBER);
+            String domain = annots.value(DOMAIN_IDENTIFIER);
+            String abrStatus = annots.value(ABR_BIT);
+            String asbrStatus = annots.value(ASBR_BIT);
 
             if (type != null) {
                 pp.addProp("Type", type);
             }
-            /* TBD: Router ID need to print
+
             if (routerId != null) {
                 pp.addProp("Router-ID", routerId);
-            } */
-            if (routingUnverse != null) {
-                pp.addProp("Routing Universe", routingUnverse);
             }
+
             if (asNumber != null) {
                 pp.addProp("AS Number", asNumber);
             }
+
             if (domain != null) {
                 pp.addProp("Domain ID", domain);
             }
+
+            if (abrStatus != null) {
+                pp.addProp("ABR Role", abrStatus);
+            }
+
+            if (asbrStatus != null) {
+                pp.addProp("ASBR Role", asbrStatus);
+            }
         }
     }
 
     @Override
+    public Map<String, String> additionalLinkData(LinkEvent event) {
+        Map<String, String> map = new HashMap<>();
+        Link link = event.subject();
+
+        map.put("Src port", link.src().port().toString());
+        map.put("Dst port", link.dst().port().toString());
+        map.put("Te metric", link.annotations().value(TE_METRIC));
+
+        ResourceService resService = AbstractShellCommand.get(ResourceService.class);
+        DiscreteResource devResource = Resources.discrete(link.src().deviceId(), link.src().port()).resource();
+        if (resService == null) {
+            log.warn("resource service does not exist ");
+            return map;
+        }
+
+        if (devResource == null) {
+            log.warn("Device resources does not exist ");
+            return map;
+        }
+        Set<Resource> resources = resService.getAvailableResources(devResource.id(), Bandwidth.class);
+        if (resources.isEmpty()) {
+            log.warn("Bandwidth resources does not exist ");
+            return map;
+        }
+
+        if (resources.iterator().next() instanceof ContinuousResource) {
+            map.put("Bandwidth", ((ContinuousResource) resources.iterator().next()).toString());
+        }
+
+        return map;
+    }
+
+    @Override
     public void modifyHostDetails(PropertyPanel pp, HostId hostId) {
         pp.addButton(SRC_BUTTON).addButton(DST_BUTTON);
     }
diff --git a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
index e16e15b..586ebea 100644
--- a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
+++ b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
@@ -96,9 +96,9 @@
         addAttribute('pce-cost-type-valname', 'pce-cost-type-te', 'TE', 'radio');
         //Add the LSP type related inputs.
         addAttribute('pce-lsp-type-name', 'pce-lsp-type', 'Lsp Type', 'checkbox');
-        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-cr', 'WITH SIGNALLING', 'radio');
-        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-srbe', 'WITHOUT SR WITHOUT SIGNALLING', 'radio');
-        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-srte', 'WITH SR WITHOUT SIGNALLING', 'radio');
+        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-cr', 'With signalling', 'radio');
+        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-srbe', 'Without SR without signalling', 'radio');
+        addAttribute('pce-lsp-type-valname', 'pce-lsp-type-srte', 'With SR without signalling', 'radio');
         //Add the tunnel name
         addAttribute('pce-tunnel-name', 'pce-tunnel-name-id', 'Tunnel Name', 'text');
 
@@ -182,12 +182,12 @@
         return content;
     }
 
-    function isChecked(viewId) {
-        return d3.select('#' + viewId).property('checked');
+    function isChecked(cboxId) {
+        return d3.select('#' + cboxId).property('checked');
     }
 
-    function getCheckedValue(viewId) {
-        return d3.select('#' + viewId).property('value');
+    function getCheckedValue(cboxId) {
+        return d3.select('#' + cboxId).property('value');
     }
 
     function showTunnelInformation(data) {
@@ -198,25 +198,19 @@
             var tdString = '' ;
             tunnelNameData.a.forEach( function (val, idx) {
                 var tunnelName = isChecked('tunnel-id-'+idx);
-                if (tunnelName)
-                {
+                if (tunnelName) {
                     tdString = val;
                 }
             } );
 
-            if (tdString) {
-                constraintsUpdateDialog(tdString);
-            } else {
-                $log.debug("No tunnel id is selected.");
-            }
-
+            constraintsUpdateDialog(tdString);
             $log.debug('Dialog OK button clicked');
         }
 
         tds.openDialog()
             .setTitle('Available LSPs with selected device')
             .addContent(createUserTextUpdate(data))
-            .addOkChained(dOkUpdate, 'GOTO Selection of constraints')
+            .addOkChained(dOkUpdate, 'OK')
             .addCancel(dClose, 'Close')
             .bindKeys();
     }
@@ -266,7 +260,7 @@
             .setTitle('Select constraints for update path')
             .addContent(createUserTextUpdatePathEvent())
             .addCancel()
-            .addOk(dOkUpdateEvent, 'Update Path')     // NOTE: NOT the "chained" version!
+            .addOk(dOkUpdateEvent, 'OK')     // NOTE: NOT the "chained" version!
             .bindKeys();
 
     }
@@ -278,7 +272,7 @@
         tds.openDialog()
             .setTitle('Available Tunnels for remove')
             .addContent(createUserTextRemove(data))
-            .addOk(dOkRemove, 'Remove')
+            .addOk(dOkRemove, 'OK')
             .addCancel(dClose, 'Close')
             .bindKeys();
     }
diff --git a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovOverlay.js b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovOverlay.js
index 4ad40a0..72dd1ef 100644
--- a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovOverlay.js
+++ b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovOverlay.js
@@ -168,6 +168,29 @@
             },
             multi: function (selectOrder) {
                 selectionCallback(selectOrder);
+            },
+            modifylinkdata: function (data, extra) {
+                $log.debug("Modify link data", data, extra);
+
+                function sep() {
+                    data.propOrder.push('-');
+                }
+
+                function add(key) {
+                    var val = extra[key];
+                    if (val !== undefined) {
+                        data.propOrder.push(key);
+                        data.props[key] = val;
+                    }
+                }
+
+                sep();
+                add('Src port');
+                add('Dst port');
+                add('Te metric');
+                add('Bandwidth');
+
+                return data;
             }
         }
     };