Enhanced layout service and hooked-in the ui topo session.

Change-Id: I357143766deb3f0d697a3e7963a53968ccdf3bc8
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoLayoutManager.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoLayoutManager.java
index bc58121..60797f4 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoLayoutManager.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoLayoutManager.java
@@ -35,7 +35,11 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Manages the user interface topology layouts.
@@ -47,6 +51,11 @@
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
+    private static final String ID_NULL = "Layout ID cannot be null";
+    private static final String LAYOUT_NULL = "Layout cannot be null";
+
+    private static final UiTopoLayoutId DEFAULT_ID = UiTopoLayoutId.layoutId("_default_");
+
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected StorageService storageService;
 
@@ -57,6 +66,7 @@
     public void activate() {
         KryoNamespace.Builder kryoBuilder = new KryoNamespace.Builder()
                 .register(KryoNamespaces.API)
+                .register(UiTopoLayoutId.class)
                 .register(UiTopoLayout.class);
 
         layouts = storageService.<UiTopoLayoutId, UiTopoLayout>consistentMapBuilder()
@@ -66,6 +76,9 @@
                 .build();
         layoutMap = layouts.asJavaMap();
 
+        // Create and add the default layout, if needed.
+        layoutMap.computeIfAbsent(DEFAULT_ID, k -> new UiTopoLayout(k, null, null));
+
         log.info("Started");
     }
 
@@ -76,22 +89,38 @@
 
 
     @Override
+    public UiTopoLayout getRootLayout() {
+        return getLayout(DEFAULT_ID);
+    }
+
+    @Override
     public Set<UiTopoLayout> getLayouts() {
         return ImmutableSet.copyOf(layoutMap.values());
     }
 
     @Override
     public boolean addLayout(UiTopoLayout layout) {
+        checkNotNull(layout, LAYOUT_NULL);
         return layouts.put(layout.id(), layout) == null;
     }
 
     @Override
     public UiTopoLayout getLayout(UiTopoLayoutId layoutId) {
+        checkNotNull(layoutId, ID_NULL);
         return layoutMap.get(layoutId);
     }
 
     @Override
+    public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) {
+        checkNotNull(layoutId, ID_NULL);
+        return layoutMap.values().stream()
+                .filter(l -> Objects.equals(l.parent(), layoutId))
+                .collect(Collectors.toSet());
+    }
+
+    @Override
     public boolean removeLayout(UiTopoLayout layout) {
+        checkNotNull(layout, LAYOUT_NULL);
         return layouts.remove(layout.id()) != null;
     }
 
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoSession.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoSession.java
index 70698ec..0ffe2ca 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoSession.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/UiTopoSession.java
@@ -45,19 +45,24 @@
 
     private boolean registered = false;
 
-    private UiTopoLayoutService service;
+    private UiTopoLayoutService layoutService;
     private UiTopoLayout currentLayout;
+    private boolean messagesEnabled;
 
     /**
      * Creates a new topology session for the specified web socket connection.
      *
-     * @param webSocket web socket
-     * @param model share topology model
+     * @param webSocket     web socket
+     * @param model         share topology model
+     * @param layoutService topology layout service
      */
-    public UiTopoSession(UiWebSocket webSocket, UiSharedTopologyModel model) {
+    public UiTopoSession(UiWebSocket webSocket,
+                         UiSharedTopologyModel model,
+                         UiTopoLayoutService layoutService) {
         this.webSocket = webSocket;
         this.username = webSocket.userName();
         this.sharedModel = model;
+        this.layoutService = layoutService;
     }
 
     /**
@@ -67,6 +72,7 @@
         if (!registered) {
             log.debug("{} : Registering with shared model", this);
             sharedModel.register(this);
+            currentLayout = layoutService.getRootLayout();
             registered = true;
         } else {
             log.warn("already registered");
@@ -96,4 +102,31 @@
         log.info("Event received: {}", event);
         // TODO: handle model events from the cache...
     }
+
+    /**
+     * Returns the current layout context.
+     *
+     * @return current topology layout
+     */
+    public UiTopoLayout currentLayout() {
+        return currentLayout;
+    }
+
+    /**
+     * Changes the current layout context to the specified layout.
+     *
+     * @param topoLayout new topology layout context
+     */
+    public void setCurrentLayout(UiTopoLayout topoLayout) {
+        currentLayout = topoLayout;
+    }
+
+    /**
+     * Enables or disables the transmission of topology event update messages.
+     *
+     * @param enabled true if messages should be sent
+     */
+    public void enableEvent(boolean enabled) {
+        messagesEnabled = enabled;
+    }
 }
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
index 19ab015..6566511 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/ModelCache.java
@@ -224,7 +224,10 @@
     }
 
     private void updateDevice(UiDevice device) {
-        device.setRegionId(services.region().getRegionForDevice(device.id()).id());
+        Region regionForDevice = services.region().getRegionForDevice(device.id());
+        if (regionForDevice != null) {
+            device.setRegionId(regionForDevice.id());
+        }
     }
 
     private void loadDevices() {
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/UiSharedTopologyModel.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/UiSharedTopologyModel.java
index 7dca64e..7cb0ffc 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/UiSharedTopologyModel.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/model/UiSharedTopologyModel.java
@@ -66,7 +66,7 @@
 /**
  * Service that creates and maintains the UI-model of the network topology.
  */
-@Component(immediate = true, enabled = false)
+@Component(immediate = true, enabled = true)
 @Service(value = UiSharedTopologyModel.class)
 public final class UiSharedTopologyModel
         extends AbstractListenerManager<UiModelEvent, UiModelListener> {