UI-Lion: uberlion event transmitted to the web UI.
- extension manager now sets runtime locale _before_ initializing core extension.
- web-socket sends uber-lion bundle "onOpen" (along with bootstrap data).
- deleted unused UiLionService.

Change-Id: Ic8f1f852dae50a49c1a7567f7ab33536b6d873aa
diff --git a/core/api/src/main/java/org/onosproject/ui/UiLionService.java b/core/api/src/main/java/org/onosproject/ui/UiLionService.java
deleted file mode 100644
index ecfb60b..0000000
--- a/core/api/src/main/java/org/onosproject/ui/UiLionService.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2017-present 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;
-
-import org.onlab.util.ItemNotFoundException;
-import org.onosproject.ui.lion.LionBundle;
-
-/**
- * Service for accessing registered localization bundles.
- */
-public interface UiLionService {
-
-    /**
-     * Returns the bundle for the given key. If no such bundle is registered
-     * an ItemNotFound exception will be thrown.
-     *
-     * @param key the bundle key
-     * @return the associated bundle
-     * @throws ItemNotFoundException if no bundle exists for
-     *                               the given key
-     */
-    LionBundle getBundle(String key);
-
-}
diff --git a/core/api/src/main/java/org/onosproject/ui/lion/LionBundle.java b/core/api/src/main/java/org/onosproject/ui/lion/LionBundle.java
index 9f4fae4..5b6f110 100644
--- a/core/api/src/main/java/org/onosproject/ui/lion/LionBundle.java
+++ b/core/api/src/main/java/org/onosproject/ui/lion/LionBundle.java
@@ -85,6 +85,15 @@
     }
 
     /**
+     * Returns an immutable set of the items in this bundle.
+     *
+     * @return the items in this bundle
+     */
+    public Set<LionItem> getItems() {
+        return items;
+    }
+
+    /**
      * Dump the contents of the bundle.
      *
      * @return dumped contents
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 dfc4edf..26692c9 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
@@ -69,6 +69,7 @@
 import java.security.SecureRandom;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -116,6 +117,9 @@
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
+    // First thing to do is to set the locale (before creating core extension).
+    private final Locale runtimeLocale = LionUtils.setupRuntimeLocale();
+
     // List of all extensions
     private final List<UiExtension> extensions = Lists.newArrayList();
 
@@ -237,11 +241,11 @@
     @Activate
     public void activate() {
         Serializer serializer = Serializer.using(KryoNamespaces.API,
-                                                 ObjectNode.class, ArrayNode.class,
-                                                 JsonNodeFactory.class, LinkedHashMap.class,
-                                                 TextNode.class, BooleanNode.class,
-                                                 LongNode.class, DoubleNode.class, ShortNode.class,
-                                                 IntNode.class, NullNode.class, UiSessionToken.class);
+                     ObjectNode.class, ArrayNode.class,
+                     JsonNodeFactory.class, LinkedHashMap.class,
+                     TextNode.class, BooleanNode.class,
+                     LongNode.class, DoubleNode.class, ShortNode.class,
+                     IntNode.class, NullNode.class, UiSessionToken.class);
 
         prefsConsistentMap = storageService.<String, ObjectNode>consistentMapBuilder()
                 .withName(ONOS_USER_PREFERENCES)
@@ -259,7 +263,6 @@
         tokens = tokensConsistentMap.asJavaMap();
 
         register(core);
-        LionUtils.setupRuntimeLocale();
 
         log.info("Started");
     }
@@ -289,7 +292,8 @@
     public synchronized void unregister(UiExtension extension) {
         checkPermission(UI_WRITE);
         extensions.remove(extension);
-        extension.views().stream().map(UiView::id).collect(toSet()).forEach(views::remove);
+        extension.views().stream()
+                .map(UiView::id).collect(toSet()).forEach(views::remove);
         UiWebSocketServlet.sendToAll(GUI_REMOVED, null);
     }
 
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 6c4fc1e..46b0859 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
@@ -69,6 +69,9 @@
     private static final String USER = "user";
     private static final String BOOTSTRAP = "bootstrap";
 
+    private static final String UBERLION = "uberlion";
+    private static final String LION = "lion";
+
     private static final String TOPO = "topo";
 
     private static final long MAX_AGE_MS = 30_000;
@@ -140,6 +143,14 @@
         topoSession.enableEvent(viewId.equals(TOPO));
     }
 
+    private ObjectNode objectNode() {
+        return mapper.createObjectNode();
+    }
+
+    private ArrayNode arrayNode() {
+        return mapper.createArrayNode();
+    }
+
     /**
      * Provides a reference to the topology session.
      *
@@ -188,6 +199,7 @@
             topoSession.init();
             createHandlersAndOverlays();
             sendBootstrapData();
+            sendUberLionBundle();
             log.info("GUI client connected -- user <{}>", userName);
 
         } catch (ServiceNotFoundException e) {
@@ -258,9 +270,9 @@
 
     @Override
     public synchronized void sendMessage(String type, ObjectNode payload) {
-        ObjectNode message = mapper.createObjectNode();
+        ObjectNode message = objectNode();
         message.put(EVENT, type);
-        message.set(PAYLOAD, payload != null ? payload : mapper.createObjectNode());
+        message.set(PAYLOAD, payload != null ? payload : objectNode());
         sendMessage(message);
     }
 
@@ -317,7 +329,7 @@
     }
 
     private ObjectNode notAuthorized(UiSessionToken token) {
-        return mapper.createObjectNode()
+        return objectNode()
                 .put("message", "invalid authentication token")
                 .put("badToken", token.toString());
     }
@@ -378,10 +390,10 @@
     // fail-over to an alternate cluster member if necessary.
     private void sendBootstrapData() {
         ClusterService service = directory.get(ClusterService.class);
-        ArrayNode instances = mapper.createArrayNode();
+        ArrayNode instances = arrayNode();
 
         for (ControllerNode node : service.getNodes()) {
-            ObjectNode instance = mapper.createObjectNode()
+            ObjectNode instance = objectNode()
                     .put(ID, node.id().toString())
                     .put(IP, node.ip().toString())
                     .put(GlyphConstants.UI_ATTACHED,
@@ -389,7 +401,7 @@
             instances.add(instance);
         }
 
-        ObjectNode payload = mapper.createObjectNode();
+        ObjectNode payload = objectNode();
         payload.set(CLUSTER_NODES, instances);
         payload.put(USER, userName);
         sendMessage(BOOTSTRAP, payload);
@@ -402,4 +414,24 @@
         }
         return service;
     }
+
+    // sends the collated localization bundle data up to the client.
+    private void sendUberLionBundle() {
+        UiExtensionService service = directory.get(UiExtensionService.class);
+        ObjectNode lion = objectNode();
+
+        service.getExtensions().forEach(ext -> {
+            ext.lionBundles().forEach(lb -> {
+                ObjectNode lionMap = objectNode();
+                lb.getItems().forEach(item -> {
+                    lionMap.put(item.key(), item.value());
+                });
+                lion.set(lb.id(), lionMap);
+            });
+        });
+
+        ObjectNode payload = objectNode();
+        payload.set(LION, lion);
+        sendMessage(UBERLION, payload);
+    }
 }