Modified UI model objects to be backed merely by IDs of the core model objects.

Change-Id: I4ca81fb1c877ee4ce4209d405fd8c6645c8f5d20
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiClusterMember.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiClusterMember.java
index 934559f..f30d9dc 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiClusterMember.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiClusterMember.java
@@ -20,6 +20,7 @@
 import org.onosproject.cluster.ControllerNode;
 import org.onosproject.cluster.NodeId;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onosproject.cluster.ControllerNode.State.INACTIVE;
 
 /**
@@ -27,8 +28,10 @@
  */
 public class UiClusterMember extends UiElement {
 
+    private static final String NODE_CANNOT_BE_NULL = "Node cannot be null";
+
     private final UiTopology topology;
-    private final ControllerNode cnode;
+    private final NodeId nodeId;
 
     private ControllerNode.State state = INACTIVE;
 
@@ -40,13 +43,14 @@
      * @param cnode    underlying controller node
      */
     public UiClusterMember(UiTopology topology, ControllerNode cnode) {
+        checkNotNull(cnode, NODE_CANNOT_BE_NULL);
         this.topology = topology;
-        this.cnode = cnode;
+        this.nodeId = cnode.id();
     }
 
     @Override
     public String toString() {
-        return "UiClusterMember{" + cnode +
+        return "UiClusterMember{" + nodeId +
                 ", online=" + isOnline() +
                 ", ready=" + isReady() +
                 "}";
@@ -63,7 +67,7 @@
      * @return the backing controller node instance
      */
     public ControllerNode backingNode() {
-        return cnode;
+        return topology.services.cluster().getNode(nodeId);
     }
 
     /**
@@ -81,7 +85,7 @@
      * @return member identifier
      */
     public NodeId id() {
-        return cnode.id();
+        return nodeId;
     }
 
     /**
@@ -90,7 +94,7 @@
      * @return the IP address
      */
     public IpAddress ip() {
-        return cnode.ip();
+        return backingNode().ip();
     }
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiDevice.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiDevice.java
index 84522de..e836233 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiDevice.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiDevice.java
@@ -21,13 +21,17 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.region.RegionId;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * Represents a device.
  */
 public class UiDevice extends UiNode {
 
+    private static final String DEVICE_CANNOT_BE_NULL = "Device cannot be null";
+
     private final UiTopology topology;
-    private final Device device;
+    private final DeviceId deviceId;
 
     private RegionId regionId;
 
@@ -38,8 +42,9 @@
      * @param device   backing device
      */
     public UiDevice(UiTopology topology, Device device) {
+        checkNotNull(device, DEVICE_CANNOT_BE_NULL);
         this.topology = topology;
-        this.device = device;
+        this.deviceId = device.id();
     }
 
     /**
@@ -65,7 +70,7 @@
      * @return device ID
      */
     public DeviceId id() {
-        return device.id();
+        return deviceId;
     }
 
     @Override
@@ -79,7 +84,7 @@
      * @return the backing device instance
      */
     public Device backingDevice() {
-        return device;
+        return topology.services.device().getDevice(deviceId);
     }
 
     /**
@@ -107,6 +112,6 @@
      * @return the device type
      */
     public String type() {
-        return device.type().toString().toLowerCase();
+        return backingDevice().type().toString().toLowerCase();
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
index ff22116..377dc16 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
@@ -23,14 +23,17 @@
 import org.onosproject.net.region.RegionId;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Represents an end-station host.
  */
 public class UiHost extends UiNode {
 
+    private static final String HOST_CANNOT_BE_NULL = "Host cannot be null";
+
     private final UiTopology topology;
-    private final Host host;
+    private final HostId hostId;
 
     // Host location
     private DeviceId locDevice;
@@ -46,14 +49,11 @@
      * @param host     backing host
      */
     public UiHost(UiTopology topology, Host host) {
+        checkNotNull(host, HOST_CANNOT_BE_NULL);
         this.topology = topology;
-        this.host = host;
+        this.hostId = host.id();
     }
 
-//    @Override
-//    protected void destroy() {
-//    }
-
     @Override
     public String toString() {
         return toStringHelper(this)
@@ -69,7 +69,7 @@
      * @return host ID
      */
     public HostId id() {
-        return host.id();
+        return hostId;
     }
 
     /**
@@ -113,7 +113,7 @@
      * @return the backing host instance
      */
     public Host backingHost() {
-        return host;
+        return topology.services.host().getHost(hostId);
     }
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
index 7cd0da9..7a565fe 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
@@ -60,7 +60,7 @@
 
     private final UiTopology topology;
 
-    private final Region region;
+    private final RegionId regionId;
 
     // keep track of hierarchy (inferred from UiTopoLayoutService)
     private RegionId parent;
@@ -76,7 +76,7 @@
         // Implementation Note: if region is null, this UiRegion is being used
         //  as a container for devices, hosts, links that belong to no region.
         this.topology = topology;
-        this.region = region;
+        this.regionId = region == null ? NULL_ID : region.id();
 
         setLayerOrder(DEFAULT_LAYER_TAGS);
     }
@@ -104,7 +104,7 @@
      * @return region ID
      */
     public RegionId id() {
-        return region == null ? NULL_ID : region.id();
+        return regionId;
     }
 
     /**
@@ -169,6 +169,7 @@
 
     @Override
     public String name() {
+        Region region = backingRegion();
         return region == null ? NULL_NAME : region.name();
     }
 
@@ -179,7 +180,7 @@
      * @return the backing region instance
      */
     public Region backingRegion() {
-        return region;
+        return topology.services.region().getRegion(regionId);
     }
 
     /**
@@ -210,6 +211,7 @@
      * @return region type
      */
     public Region.Type type() {
+        Region region = backingRegion();
         return region == null ? null : region.type();
     }
 
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiTopology.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiTopology.java
index 744c996..58e1b13 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiTopology.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiTopology.java
@@ -21,6 +21,7 @@
 import org.onosproject.net.HostId;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.region.RegionId;
+import org.onosproject.ui.model.ServiceBundle;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,6 +73,16 @@
     // a container for devices, hosts, etc. belonging to no region
     private final UiRegion nullRegion = new UiRegion(this, null);
 
+    final ServiceBundle services;
+
+    /**
+     * Creates a new UI topology backed by the specified service bundle.
+     *
+     * @param services service bundle
+     */
+    public UiTopology(ServiceBundle services) {
+        this.services = services;
+    }
 
     @Override
     public String toString() {
diff --git a/core/api/src/test/java/org/onosproject/ui/model/AbstractUiModelTest.java b/core/api/src/test/java/org/onosproject/ui/model/AbstractUiModelTest.java
index 15b3870..e25aa4a 100644
--- a/core/api/src/test/java/org/onosproject/ui/model/AbstractUiModelTest.java
+++ b/core/api/src/test/java/org/onosproject/ui/model/AbstractUiModelTest.java
@@ -16,9 +16,11 @@
 
 package org.onosproject.ui.model;
 
+import org.onlab.packet.IpAddress;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.ClusterServiceAdapter;
 import org.onosproject.cluster.ControllerNode;
+import org.onosproject.cluster.DefaultControllerNode;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.device.DeviceService;
@@ -88,10 +90,21 @@
                 }
             };
 
-    private static final ClusterService MOCK_CLUSTER = new MockClusterService();
+    protected static final ClusterService MOCK_CLUSTER = new MockClusterService();
 
+    protected static final NodeId NODE_ID = NodeId.nodeId("Node-1");
+    protected static final IpAddress NODE_IP = IpAddress.valueOf("1.2.3.4");
+
+    protected static final ControllerNode CNODE_1 =
+            new DefaultControllerNode(NODE_ID, NODE_IP);
 
     private static class MockClusterService extends ClusterServiceAdapter {
+
+        @Override
+        public ControllerNode getNode(NodeId nodeId) {
+            return CNODE_1;
+        }
+
         @Override
         public ControllerNode.State getState(NodeId nodeId) {
             // For now, a hardcoded state of ACTIVE (but not READY)
diff --git a/core/api/src/test/java/org/onosproject/ui/model/topo/UiClusterMemberTest.java b/core/api/src/test/java/org/onosproject/ui/model/topo/UiClusterMemberTest.java
index f29e8dd..2e26989 100644
--- a/core/api/src/test/java/org/onosproject/ui/model/topo/UiClusterMemberTest.java
+++ b/core/api/src/test/java/org/onosproject/ui/model/topo/UiClusterMemberTest.java
@@ -18,10 +18,6 @@
 
 import org.junit.Before;
 import org.junit.Test;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cluster.ControllerNode;
-import org.onosproject.cluster.DefaultControllerNode;
-import org.onosproject.cluster.NodeId;
 import org.onosproject.ui.model.AbstractUiModelTest;
 
 import static org.junit.Assert.assertEquals;
@@ -31,18 +27,12 @@
  */
 public class UiClusterMemberTest extends AbstractUiModelTest {
 
-    private static final NodeId NODE_ID = NodeId.nodeId("Node-1");
-    private static final IpAddress NODE_IP = IpAddress.valueOf("1.2.3.4");
-
-    private static final ControllerNode CNODE_1 =
-            new DefaultControllerNode(NODE_ID, NODE_IP);
-
     private UiTopology topo;
     private UiClusterMember member;
 
     @Before
     public void setUp() {
-        topo = new UiTopology();
+        topo = new UiTopology(MOCK_SERVICES);
     }
 
     @Test
diff --git a/core/api/src/test/java/org/onosproject/ui/model/topo/UiTopologyTest.java b/core/api/src/test/java/org/onosproject/ui/model/topo/UiTopologyTest.java
index 5df0a9f..cb6a316 100644
--- a/core/api/src/test/java/org/onosproject/ui/model/topo/UiTopologyTest.java
+++ b/core/api/src/test/java/org/onosproject/ui/model/topo/UiTopologyTest.java
@@ -25,7 +25,7 @@
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.net.region.RegionId;
-import org.onosproject.ui.AbstractUiTest;
+import org.onosproject.ui.model.AbstractUiModelTest;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -38,7 +38,7 @@
 /**
  * Unit tests for {@link UiTopology}.
  */
-public class UiTopologyTest extends AbstractUiTest {
+public class UiTopologyTest extends AbstractUiModelTest {
 
     private static final DeviceId DEV_X = deviceId("dev-X");
     private static final DeviceId DEV_Y = deviceId("dev-Y");
@@ -79,7 +79,7 @@
 
     @Before
     public void setUp() {
-        topo = new UiTopology();
+        topo = new UiTopology(MOCK_SERVICES);
         devLink = new UiDeviceLink(null, DX1_DY2);
         devLink.attachBackingLink(LINK_X1_TO_Y2);
     }
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 2377499..12d75f3 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
@@ -85,13 +85,14 @@
 
     private final ServiceBundle services;
     private final EventDispatcher dispatcher;
-    private final UiTopology uiTopology = new UiTopology();
+    private final UiTopology uiTopology;
 
     private Topo2Jsonifier t2json;
 
     ModelCache(ServiceBundle services, EventDispatcher eventDispatcher) {
         this.services = services;
         this.dispatcher = eventDispatcher;
+        uiTopology = new UiTopology(services);
     }
 
     @Override