ONOS-1479 - GUI Topology Overlay Work - (WIP)
- UiExtension now uses Builder Pattern; added topology overlay factory.
- Refactored UiExtensionTest (and other classes) to use builder.
- Created UiTopoOverlayFactory, UiTopoOverlay, and TopoOverlayCache.
- Started implementation of TrafficOverlay.
- Inject TopoOverlayCache into TopologyViewMessageHandler; added TopoSelectOverlay request handler.
- Modified UiExtensionManager to create traffic overlay.
- Augmented UiWebSocket to create overlays on demand, and inject overlay cache into topo view message handler.
- added client side wiring to switch overlays.

Change-Id: I6f99596aefb3b87382517ce929d268a2447545ee
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
index b80c11f..761c2a3 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
@@ -27,6 +27,7 @@
 import org.onosproject.ui.UiExtensionService;
 import org.onosproject.ui.UiMessageHandlerFactory;
 import org.onosproject.ui.UiMessageHandler;
+import org.onosproject.ui.UiTopoOverlayFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -58,6 +59,7 @@
     private long lastActive = System.currentTimeMillis();
 
     private Map<String, UiMessageHandler> handlers;
+    private TopoOverlayCache overlayCache;
 
     /**
      * Creates a new web-socket for serving data to GUI.
@@ -72,7 +74,7 @@
      * Issues a close on the connection.
      */
     synchronized void close() {
-        destroyHandlers();
+        destroyHandlersAndOverlays();
         if (connection.isOpen()) {
             connection.close();
         }
@@ -104,7 +106,7 @@
         this.connection = connection;
         this.control = (FrameConnection) connection;
         try {
-            createHandlers();
+            createHandlersAndOverlays();
             sendInstanceData();
             log.info("GUI client connected");
 
@@ -118,7 +120,7 @@
 
     @Override
     public synchronized void onClose(int closeCode, String message) {
-        destroyHandlers();
+        destroyHandlersAndOverlays();
         log.info("GUI client disconnected [close-code={}, message={}]",
                  closeCode, message);
     }
@@ -131,6 +133,7 @@
 
     @Override
     public void onMessage(String data) {
+        log.debug("onMessage: {}", data);
         lastActive = System.currentTimeMillis();
         try {
             ObjectNode message = (ObjectNode) mapper.reader().readTree(data);
@@ -172,8 +175,11 @@
     }
 
     // Creates new message handlers.
-    private synchronized void createHandlers() {
+    private synchronized void createHandlersAndOverlays() {
+        log.debug("creating handlers and overlays...");
         handlers = new HashMap<>();
+        overlayCache = new TopoOverlayCache();
+
         UiExtensionService service = directory.get(UiExtensionService.class);
         service.getExtensions().forEach(ext -> {
             UiMessageHandlerFactory factory = ext.messageHandlerFactory();
@@ -181,15 +187,33 @@
                 factory.newHandlers().forEach(handler -> {
                     handler.init(this, directory);
                     handler.messageTypes().forEach(type -> handlers.put(type, handler));
+
+                    // need to inject the overlay cache into topology message handler
+                    if (handler instanceof TopologyViewMessageHandler) {
+                        ((TopologyViewMessageHandler) handler).setOverlayCache(overlayCache);
+                    }
                 });
             }
+
+            UiTopoOverlayFactory overlayFactory = ext.topoOverlayFactory();
+            if (overlayFactory != null) {
+                overlayFactory.newOverlays().forEach(overlayCache::add);
+            }
         });
+        log.debug("#handlers = {}, #overlays = {}", handlers.size(),
+                  overlayCache.size());
     }
 
     // Destroys message handlers.
-    private synchronized void destroyHandlers() {
+    private synchronized void destroyHandlersAndOverlays() {
+        log.debug("destroying handlers and overlays...");
         handlers.forEach((type, handler) -> handler.destroy());
         handlers.clear();
+
+        if (overlayCache != null) {
+            overlayCache.destroy();
+            overlayCache = null;
+        }
     }
 
     // Sends cluster node/instance information to allow GUI to fail-over.