Fix for ONOS-291. Highlighting intents in ONOS GUI for selected links.

Change-Id: I757aa40b96d92014fa2d720539da20dd309ec9b1
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
index fdfdd1b..1c7e22e 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
@@ -534,7 +534,7 @@
         @Override
         public void process(long sid, ObjectNode payload) {
             NodeSelection nodeSelection =
-                    new NodeSelection(payload, deviceService, hostService);
+                    new NodeSelection(payload, deviceService, hostService, linkService);
             traffic.monitor(Mode.DEV_LINK_FLOWS, nodeSelection);
         }
     }
@@ -547,7 +547,7 @@
         @Override
         public void process(long sid, ObjectNode payload) {
             NodeSelection nodeSelection =
-                    new NodeSelection(payload, deviceService, hostService);
+                    new NodeSelection(payload, deviceService, hostService, linkService);
             traffic.monitor(Mode.RELATED_INTENTS, nodeSelection);
         }
     }
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/util/IntentSelection.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/util/IntentSelection.java
index 58c649e..dd48768 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/util/IntentSelection.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/util/IntentSelection.java
@@ -49,7 +49,10 @@
      */
     public IntentSelection(NodeSelection nodes, TopoIntentFilter filter) {
         this.nodes = nodes;
-        intents = filter.findPathIntents(nodes.hostsWithHover(), nodes.devicesWithHover());
+        intents = filter.findPathIntents(
+                nodes.hostsWithHover(),
+                nodes.devicesWithHover(),
+                nodes.linksWithHover());
         if (intents.size() == 1) {
             index = 0;  // pre-select a single intent
         }
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/util/TopoIntentFilter.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/util/TopoIntentFilter.java
index 2b65762..54a43d4 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/util/TopoIntentFilter.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/util/TopoIntentFilter.java
@@ -74,9 +74,12 @@
      *
      * @param hosts         set of hosts to query by
      * @param devices       set of devices to query by
-     * @return set of intents that 'match' all hosts and devices given
+     * @param links       set of links to query by
+     * @return set of intents that 'match' all hosts, devices and links given
      */
-    public List<Intent> findPathIntents(Set<Host> hosts, Set<Device> devices) {
+    public List<Intent> findPathIntents(Set<Host> hosts,
+                                        Set<Device> devices,
+                                        Set<Link> links) {
         // start with all intents
         Iterable<Intent> sourceIntents = intentService.getIntents();
 
@@ -85,7 +88,7 @@
 
         // Iterate over all intents and produce a set that contains only those
         // intents that target all selected hosts or derived edge connect points.
-        return getIntents(hosts, devices, edgePoints, sourceIntents);
+        return getIntents(hosts, devices, links, edgePoints, sourceIntents);
     }
 
 
@@ -98,12 +101,12 @@
         return edgePoints;
     }
 
-    // Produces a list of intents that target all selected hosts, devices or connect points.
-    private List<Intent> getIntents(Set<Host> hosts, Set<Device> devices,
+    // Produces a list of intents that target all selected hosts, devices, links or connect points.
+    private List<Intent> getIntents(Set<Host> hosts, Set<Device> devices, Set<Link> links,
                                     Set<ConnectPoint> edgePoints,
                                     Iterable<Intent> sourceIntents) {
         List<Intent> intents = new ArrayList<>();
-        if (hosts.isEmpty() && devices.isEmpty()) {
+        if (hosts.isEmpty() && devices.isEmpty() && links.isEmpty()) {
             return intents;
         }
 
@@ -115,13 +118,13 @@
                 boolean isRelevant = false;
                 if (intent instanceof HostToHostIntent) {
                     isRelevant = isIntentRelevantToHosts((HostToHostIntent) intent, hosts) &&
-                            isIntentRelevantToDevices(intent, devices);
+                            isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
                 } else if (intent instanceof PointToPointIntent) {
                     isRelevant = isIntentRelevant((PointToPointIntent) intent, edgePoints) &&
-                            isIntentRelevantToDevices(intent, devices);
+                            isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
                 } else if (intent instanceof MultiPointToSinglePointIntent) {
                     isRelevant = isIntentRelevant((MultiPointToSinglePointIntent) intent, edgePoints) &&
-                            isIntentRelevantToDevices(intent, devices);
+                            isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
                 } else if (intent instanceof OpticalConnectivityIntent) {
                     opticalIntents.add((OpticalConnectivityIntent) intent);
                 }
@@ -167,6 +170,17 @@
         return true;
     }
 
+    // Indicates whether the specified intent involves all of the given links.
+    private boolean isIntentRelevantToLinks(Intent intent, Iterable<Link> links) {
+        List<Intent> installables = intentService.getInstallableIntents(intent.key());
+        for (Link link : links) {
+            if (!isIntentRelevantToLink(installables, link)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     // Indicates whether the specified intent involves the given device.
     private boolean isIntentRelevantToDevice(List<Intent> installables, Device device) {
         if (installables != null) {
@@ -196,6 +210,38 @@
         return false;
     }
 
+    // Indicates whether the specified intent involves the given link.
+    private boolean isIntentRelevantToLink(List<Intent> installables, Link link) {
+        Link reverseLink = linkService.getLink(link.dst(), link.src());
+
+        if (installables != null) {
+            for (Intent installable : installables) {
+                if (installable instanceof PathIntent) {
+                    PathIntent pathIntent = (PathIntent) installable;
+                    return pathIntent.path().links().contains(link) ||
+                            pathIntent.path().links().contains(reverseLink);
+
+                } else if (installable instanceof FlowRuleIntent) {
+                    FlowRuleIntent flowRuleIntent = (FlowRuleIntent) installable;
+                    return flowRuleIntent.resources().contains(link) ||
+                            flowRuleIntent.resources().contains(reverseLink);
+
+                } else if (installable instanceof FlowObjectiveIntent) {
+                    FlowObjectiveIntent objectiveIntent = (FlowObjectiveIntent) installable;
+                    return objectiveIntent.resources().contains(link) ||
+                            objectiveIntent.resources().contains(reverseLink);
+
+                } else if (installable instanceof LinkCollectionIntent) {
+                    LinkCollectionIntent linksIntent = (LinkCollectionIntent) installable;
+                    return linksIntent.links().contains(link) ||
+                            linksIntent.links().contains(reverseLink);
+
+                }
+            }
+        }
+        return false;
+    }
+
     // Indicates whether the specified links involve the given device.
     private boolean pathContainsDevice(Iterable<Link> links, DeviceId id) {
         for (Link link : links) {