GUI -- Added facility to upload and track various sprite JSON definitions. WIP

Change-Id: I5629e07d84b91d2d885737a9011acc4e13538cf2
diff --git a/tools/test/bin/onos-upload-sprites b/tools/test/bin/onos-upload-sprites
new file mode 100755
index 0000000..0bf9bef
--- /dev/null
+++ b/tools/test/bin/onos-upload-sprites
@@ -0,0 +1,12 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Tool to upload GUI sprites definitions using GUI REST API.
+# -----------------------------------------------------------------------------
+
+node=${1}
+sprites=${2}
+
+export URL=http://$node:8181/onos/ui/rs/topology/sprites
+export HDR="-HContent-Type:application/json"
+
+curl --fail -sS -X POST $HDR $URL --data @$sprites
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/SpriteService.java b/web/gui/src/main/java/org/onosproject/ui/impl/SpriteService.java
new file mode 100644
index 0000000..7312329
--- /dev/null
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/SpriteService.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import java.util.Set;
+
+/**
+ * Provisional service to keep track of the topology view sprite definitions.
+ */
+public interface SpriteService {
+
+    /**
+     * Returns set of registered sprite definition names.
+     *
+     * @return set of sprite definition names
+     */
+    Set<String> getNames();
+
+    /**
+     * Registers sprite data under the specified name.
+     *
+     * @param name       sprite definition name
+     * @param spriteData sprite data
+     */
+    void put(String name, JsonNode spriteData);
+
+    /**
+     * Returns the sprite definition registered under the given name.
+     *
+     * @param name sprite definition name
+     * @return sprite data
+     */
+    JsonNode get(String name);
+
+}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyResource.java b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyResource.java
index 95f9a07..5bb46f2 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyResource.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyResource.java
@@ -15,16 +15,21 @@
  */
 package org.onosproject.ui.impl;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onlab.rest.BaseResource;
 import org.slf4j.Logger;
 
+import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Map;
 
 import static org.slf4j.LoggerFactory.getLogger;
@@ -39,8 +44,7 @@
 
     private final ObjectMapper mapper = new ObjectMapper();
 
-
-    @Path("/geoloc")
+    @Path("geoloc")
     @GET
     @Produces("application/json")
     public Response getGeoLocations() {
@@ -77,4 +81,14 @@
         }
     }
 
+    @Path("sprites")
+    @POST
+    @Consumes("application/json")
+    public Response setSprites(InputStream stream) throws IOException {
+        JsonNode root = mapper.readTree(stream);
+        String name = root.path("defn_id").asText("sprites");
+        get(SpriteService.class).put(name, root);
+        return Response.ok().build();
+    }
+
 }
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 e63dbf7..cd8c3c2 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
@@ -145,7 +145,9 @@
                               "cancelTraffic",
                               "requestSummary",
                               "cancelSummary",
-                              "equalizeMasters"
+                              "equalizeMasters",
+                              "spriteListRequest",
+                              "spriteDataRequest"
         ));
     }
 
@@ -211,6 +213,11 @@
         } else if (type.equals("equalizeMasters")) {
             equalizeMasters(event);
 
+        } else if (type.equals("spriteListRequest")) {
+            sendSpriteList(event);
+        } else if (type.equals("spriteDataRequest")) {
+            sendSpriteData(event);
+
         } else if (type.equals("topoStart")) {
             sendAllInitialData();
         } else if (type.equals("topoStop")) {
@@ -563,6 +570,22 @@
         directory.get(MastershipAdminService.class).balanceRoles();
     }
 
+    // Sends a list of sprite names.
+    private void sendSpriteList(ObjectNode event) {
+        ObjectNode root = mapper.createObjectNode();
+        ArrayNode names = mapper.createArrayNode();
+        get(SpriteService.class).getNames().forEach(names::add);
+        root.set("names", names);
+        sendMessage(envelope("spriteListResponse", number(event, "sid"), root));
+    }
+
+    // Sends requested sprite data.
+    private void sendSpriteData(ObjectNode event) {
+        ObjectNode root = mapper.createObjectNode();
+        root.set("defn", get(SpriteService.class).get(event.path("payload").path("name").asText()));
+        sendMessage(envelope("spriteDataResponse", number(event, "sid"), root));
+    }
+
 
     // Adds all internal listeners.
     private void addListeners() {
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiExtensionManager.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiExtensionManager.java
index e818071..66138e7 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiExtensionManager.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiExtensionManager.java
@@ -15,7 +15,9 @@
  */
 package org.onosproject.ui.impl;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.apache.felix.scr.annotations.Activate;
@@ -31,6 +33,7 @@
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static com.google.common.collect.ImmutableList.of;
 import static java.util.stream.Collectors.toSet;
@@ -40,7 +43,7 @@
  */
 @Component(immediate = true)
 @Service
-public class UiExtensionManager implements UiExtensionService {
+public class UiExtensionManager implements UiExtensionService, SpriteService {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
@@ -115,4 +118,25 @@
     public synchronized UiExtension getViewExtension(String viewId) {
         return views.get(viewId);
     }
+
+
+    // Provisional tracking of sprite definitions
+    private Map<String, JsonNode> sprites = Maps.newHashMap();
+
+    @Override
+    public Set<String> getNames() {
+        return ImmutableSet.copyOf(sprites.keySet());
+    }
+
+    @Override
+    public void put(String name, JsonNode spriteData) {
+        log.info("Registered sprite definition {}", name);
+        sprites.put(name, spriteData);
+    }
+
+    @Override
+    public JsonNode get(String name) {
+        return sprites.get(name);
+    }
+
 }
diff --git a/web/gui/src/main/webapp/app/view/topo/topoEvent.js b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
index 6d52a37..154cd4c 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoEvent.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
@@ -86,6 +86,8 @@
                 openListener = wss.addOpenListener(wsOpen);
                 wss.bindHandlers(handlerMap);
                 wss.sendEvent('topoStart');
+                wss.sendEvent('spriteListRequest');
+                wss.sendEvent('spriteDataRequest', {name: 'sample'});
                 $log.debug('topo comms started');
             }
 
diff --git a/web/gui/src/main/webapp/data/ext/sprites.json b/web/gui/src/main/webapp/data/ext/sprites.json
index 74b9129..ca8c2fe 100644
--- a/web/gui/src/main/webapp/data/ext/sprites.json
+++ b/web/gui/src/main/webapp/data/ext/sprites.json
@@ -1,4 +1,5 @@
 {
+  "defn_id": "sample",
   "file_desc": "Cloud Sprite Data",
 
   "_comment": [