GUI2 Topo Added base common base for Topo2ViewMessageHandler and TopologyViewMessageHandlerBase

Change-Id: I6818b764a3dbafb134786c4f6cdddd051b0c88ba
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2TrafficMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2TrafficMessageHandler.java
index 586ff8c..5f5d84d 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2TrafficMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2TrafficMessageHandler.java
@@ -17,36 +17,56 @@
 
 package org.onosproject.ui.impl.topo;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.ImmutableSet;
 import org.onlab.osgi.ServiceDirectory;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.MultiPointToSinglePointIntent;
 import org.onosproject.ui.RequestHandler;
 import org.onosproject.ui.UiConnection;
-import org.onosproject.ui.UiMessageHandler;
 import org.onosproject.ui.impl.TrafficMonitorBase.Mode;
 import org.onosproject.ui.impl.UiWebSocket;
 import org.onosproject.ui.impl.topo.util.ServicesBundle;
 import org.onosproject.ui.model.topo.UiLinkId;
 import org.onosproject.ui.model.topo.UiSynthLink;
 import org.onosproject.ui.topo.Highlights;
+import org.onosproject.ui.topo.NodeSelection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
+import static org.onosproject.net.HostId.hostId;
 import static org.onosproject.ui.topo.TopoJson.topo2HighlightsMessage;
 
 /**
  * Server-side component to handle messages pertaining to topo-2 traffic.
  */
-public class Topo2TrafficMessageHandler extends UiMessageHandler {
+public class Topo2TrafficMessageHandler extends TopoologyTrafficMessageHandlerAbstract {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     // === Inbound event identifiers
     private static final String REQUEST_ALL_TRAFFIC = "topo2RequestAllTraffic";
     private static final String CANCEL_TRAFFIC = "topo2CancelTraffic";
+    private static final String ADD_HOST_INTENT = "topo2AddHostIntent";
+    private static final String ADD_MULTI_SRC_INTENT = "topo2AddMultiSourceIntent";
+    private static final String REQ_RELATED_INTENTS = "topo2RequestRelatedIntents";
 
     // field values
     private static final String TRAFFIC_TYPE = "trafficType";
@@ -54,21 +74,29 @@
     private static final String PORT_STATS_BIT_SEC = "portStatsBitSec";
     private static final String PORT_STATS_PKT_SEC = "portStatsPktSec";
 
+    // fields
+    private static final String ONE = "one";
+    private static final String TWO = "two";
+    private static final String SRC = "src";
+    private static final String DST = "dst";
+
     // configuration parameters
     private static final long TRAFFIC_PERIOD = 5000;
 
     protected ServicesBundle services;
-
+    private static final String MY_APP_ID = "org.onosproject.gui";
+    private ApplicationId appId;
     private UiTopoSession topoSession;
-    private Traffic2Monitor traffic;
+    private Topo2OverlayCache overlay2Cache;
+    private Traffic2Monitor traffic2;
 
 
     @Override
     public void init(UiConnection connection, ServiceDirectory directory) {
         super.init(connection, directory);
-
+        appId = directory.get(CoreService.class).registerApplication(MY_APP_ID);
         services = new ServicesBundle(directory);
-        traffic = new Traffic2Monitor(TRAFFIC_PERIOD, services, this);
+        traffic2 = new Traffic2Monitor(TRAFFIC_PERIOD, services, this);
         topoSession = ((UiWebSocket) connection).topoSession();
     }
 
@@ -76,15 +104,26 @@
     protected Collection<RequestHandler> createRequestHandlers() {
         return ImmutableSet.of(
                 new Topo2AllTraffic(),
-                new Topo2CancelTraffic()
+                new Topo2CancelTraffic(),
+                new Topo2AddHostIntent(),
+                new Topo2AddMultiSourceIntent()
         );
     }
 
     /**
+     * Injects the topology overlay cache.
+     *
+     * @param overlay2Cache injected cache
+     */
+    public void setOverlayCache(Topo2OverlayCache overlay2Cache) {
+        this.overlay2Cache = overlay2Cache;
+    }
+
+    /**
      * Shuts down the background traffic monitoring task.
      */
     void ceaseAndDesist() {
-        traffic.stopMonitoring();
+        traffic2.stopMonitoring();
     }
 
     /**
@@ -92,7 +131,8 @@
      *
      * @param highlights the highlights for transmission
      */
-    void sendHighlights(Highlights highlights) {
+    @Override
+    public void sendHighlights(Highlights highlights) {
         sendMessage(topo2HighlightsMessage(highlights));
     }
 
@@ -121,15 +161,15 @@
 
             switch (mode) {
                 case FLOW_STATS_BYTES:
-                    traffic.monitor(Mode.ALL_FLOW_TRAFFIC_BYTES);
+                    traffic2.monitor(Mode.ALL_FLOW_TRAFFIC_BYTES);
                     break;
 
                 case PORT_STATS_BIT_SEC:
-                    traffic.monitor(Mode.ALL_PORT_TRAFFIC_BIT_PS);
+                    traffic2.monitor(Mode.ALL_PORT_TRAFFIC_BIT_PS);
                     break;
 
                 case PORT_STATS_PKT_SEC:
-                    traffic.monitor(Mode.ALL_PORT_TRAFFIC_PKT_PS);
+                    traffic2.monitor(Mode.ALL_PORT_TRAFFIC_PKT_PS);
                     break;
 
                 default:
@@ -147,9 +187,105 @@
         @Override
         public void process(ObjectNode payload) {
             log.debug("CANCEL TRAFFIC");
-            traffic.stopMonitoring();
+            traffic2.stopMonitoring();
         }
     }
+
+    private final class Topo2AddHostIntent extends RequestHandler {
+        private Topo2AddHostIntent() {
+            super(ADD_HOST_INTENT);
+        }
+
+        @Override
+        public void process(ObjectNode payload) {
+            // TODO: add protection against device ids and non-existent hosts.
+            HostId one = hostId(string(payload, ONE));
+            HostId two = hostId(string(payload, TWO));
+
+            HostToHostIntent intent = HostToHostIntent.builder()
+                    .appId(appId)
+                    .one(one)
+                    .two(two)
+                    .build();
+
+            services.intent().submit(intent);
+            if (overlay2Cache.isActive(Traffic2Overlay.OVERLAY_ID)) {
+                traffic2.monitor(intent);
+            }
+        }
+    }
+
+    private final class Topo2AddMultiSourceIntent extends RequestHandler {
+        private Topo2AddMultiSourceIntent() {
+            super(ADD_MULTI_SRC_INTENT);
+        }
+
+        @Override
+        public void process(ObjectNode payload) {
+            // TODO: add protection against device ids and non-existent hosts.
+            Set<HostId> src = getHostIds((ArrayNode) payload.path(SRC));
+            HostId dst = hostId(string(payload, DST));
+            Host dstHost = services.host().getHost(dst);
+
+            Set<FilteredConnectPoint> ingressPoints = getHostLocations(src);
+
+            // FIXME: clearly, this is not enough
+            TrafficSelector selector = DefaultTrafficSelector.builder()
+                    .matchEthDst(dstHost.mac()).build();
+            TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+
+            MultiPointToSinglePointIntent intent =
+                    MultiPointToSinglePointIntent.builder()
+                            .appId(appId)
+                            .selector(selector)
+                            .treatment(treatment)
+                            .filteredIngressPoints(ingressPoints)
+                            .filteredEgressPoint(new FilteredConnectPoint(dstHost.location()))
+                            .build();
+
+            services.intent().submit(intent);
+            if (overlay2Cache.isActive(Traffic2Overlay.OVERLAY_ID)) {
+                traffic2.monitor(intent);
+            }
+        }
+    }
+
+    private final class ReqRelatedIntents extends RequestHandler {
+        private ReqRelatedIntents() {
+            super(REQ_RELATED_INTENTS);
+        }
+
+        @Override
+        public void process(ObjectNode payload) {
+            traffic2.monitor(Mode.RELATED_INTENTS, makeNodeSelection(payload));
+        }
+    }
+
+    // Produces a list of host ids from the specified JSON array.
+    private Set<HostId> getHostIds(ArrayNode ids) {
+        Set<HostId> hostIds = new HashSet<>();
+        for (JsonNode id : ids) {
+            hostIds.add(hostId(id.asText()));
+        }
+        return hostIds;
+    }
+
+    private Set<FilteredConnectPoint> getHostLocations(Set<HostId> hostIds) {
+        Set<FilteredConnectPoint> points = new HashSet<>();
+        for (HostId hostId : hostIds) {
+            points.add(new FilteredConnectPoint(getHostLocation(hostId)));
+        }
+        return points;
+    }
+
+    private HostLocation getHostLocation(HostId hostId) {
+        return services.host().getHost(hostId).location();
+    }
+
+    private NodeSelection makeNodeSelection(ObjectNode payload) {
+        return new NodeSelection(payload, services.device(), services.host(),
+                                 services.link());
+    }
 }
 
 
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
index 5fbb444..057a050 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2ViewMessageHandler.java
@@ -67,7 +67,11 @@
     private static final String CURRENT_REGION = "topo2CurrentRegion";
     private static final String PEER_REGIONS = "topo2PeerRegions";
     private static final String OVERLAYS = "topo2Overlays";
+    private static final String TOPO_SELECT_OVERLAY = "topoSelectOverlay";
 
+    // fields
+    private static final String ACTIVATE = "activate";
+    private static final String DEACTIVATE = "deactivate";
 
     private UiTopoSession topoSession;
     private Topo2Jsonifier t2json;
@@ -114,6 +118,19 @@
         );
     }
 
+    private final class TopoSelectOverlay extends RequestHandler {
+        private TopoSelectOverlay() {
+            super(TOPO_SELECT_OVERLAY);
+        }
+
+        @Override
+        public void process(ObjectNode payload) {
+            String deact = string(payload, DEACTIVATE);
+            String act = string(payload, ACTIVATE);
+            overlay2Cache.switchOverlay(deact, act);
+        }
+    }
+
     // ==================================================================
 
     private ObjectNode mkLayoutMessage(UiTopoLayout currentLayout) {
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoologyTrafficMessageHandlerAbstract.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoologyTrafficMessageHandlerAbstract.java
new file mode 100644
index 0000000..900f4df
--- /dev/null
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoologyTrafficMessageHandlerAbstract.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * 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.
+ */
+package org.onosproject.ui.impl.topo;
+
+import org.onosproject.ui.UiMessageHandler;
+import org.onosproject.ui.topo.Highlights;
+
+/**
+ * Base superclass for traffic message handler (both 'classic' and 'topo2' versions).
+ */
+public abstract class TopoologyTrafficMessageHandlerAbstract extends UiMessageHandler {
+    public abstract void sendHighlights(Highlights highlights);
+}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Traffic2Monitor.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Traffic2Monitor.java
index 4e78525..d0d40bd 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Traffic2Monitor.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Traffic2Monitor.java
@@ -54,7 +54,7 @@
      */
     public Traffic2Monitor(long trafficPeriod, ServicesBundle servicesBundle,
                            Topo2TrafficMessageHandler msgHandler) {
-        super(trafficPeriod, servicesBundle);
+        super(trafficPeriod, servicesBundle, msgHandler);
         this.msgHandler = msgHandler;
     }
 
@@ -90,7 +90,8 @@
 
     @Override
     protected void sendSelectedIntentTraffic() {
-        log.debug("sendSelectedIntentTraffic: NOT IMPLEMENTED YET");
+        log.debug("sendSelectedIntentTraffic: {}", selectedIntents);
+        msgHandler.sendHighlights(intentTraffic());
     }
 
     @Override
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Traffic2Overlay.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Traffic2Overlay.java
index 26692fe..057a5987 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Traffic2Overlay.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Traffic2Overlay.java
@@ -29,7 +29,7 @@
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     // NOTE: this must match the ID defined in topo2TrafficOverlay.js
-    private static final String OVERLAY_ID = "traffic-2-overlay";
+    public static final String OVERLAY_ID = "traffic-2-overlay";
 
     /**
      * Creates a traffic overlay instance.