Started fleshing out the UI topo model classes.
If reviewing this, please refer to http://tinyurl.com/onos-ui-topo-model

Change-Id: I4738392bec1a89c37dff15eff6fe04d66fcabd95
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 d72ff3d..6a76eb5 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
@@ -16,9 +16,19 @@
 
 package org.onosproject.ui.impl.topo.model;
 
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.cluster.RoleInfo;
 import org.onosproject.event.EventDispatcher;
 import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.Link;
+import org.onosproject.net.region.Region;
 import org.onosproject.ui.model.topo.UiDevice;
+import org.onosproject.ui.model.topo.UiTopology;
+
+import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.DEVICE_ADDED;
+import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.DEVICE_REMOVED;
 
 /**
  * UI Topology Model cache.
@@ -26,6 +36,7 @@
 class ModelCache {
 
     private final EventDispatcher dispatcher;
+    private final UiTopology uiTopology = new UiTopology();
 
     ModelCache(EventDispatcher eventDispatcher) {
         this.dispatcher = eventDispatcher;
@@ -35,7 +46,7 @@
      * Clear our model.
      */
     void clear() {
-        // TODO: clear our internal state
+        uiTopology.clear();
     }
 
     /**
@@ -50,26 +61,72 @@
     }
 
 
-    // add or update device
     void addOrUpdateDevice(Device device) {
-        // fetch UiDevice
+        // TODO: find or create device assoc. with parameter
+        // FIXME
         UiDevice uiDevice = new UiDevice();
 
-        dispatcher.post(
-                new UiModelEvent(UiModelEvent.Type.DEVICE_ADDED, uiDevice)
-        );
-
+        // TODO: post the (correct) event
+        dispatcher.post(new UiModelEvent(DEVICE_ADDED, uiDevice));
     }
 
     void removeDevice(Device device) {
+        // TODO: get UiDevice associated with the given parameter; remove from model
+        // FIXME
         UiDevice uiDevice = new UiDevice();
 
-        dispatcher.post(
-                new UiModelEvent(UiModelEvent.Type.DEVICE_REMOVED, uiDevice)
-        );
+        // TODO: post the (correct) event
+        dispatcher.post(new UiModelEvent(DEVICE_REMOVED, uiDevice));
 
     }
 
-    // TODO remaining model objects
+    void addOrUpdateClusterMember(ControllerNode cnode) {
+        // TODO: find or create cluster member assoc. with parameter
+        // TODO: post event
+    }
 
+    void removeClusterMember(ControllerNode cnode) {
+        // TODO: find cluster member assoc. with parameter; remove from model
+        // TODO: post event
+    }
+
+
+    void updateMasterships(DeviceId deviceId, RoleInfo roleInfo) {
+        // TODO: store the updated mastership information
+        // TODO: post event
+    }
+
+    void addOrUpdateRegion(Region region) {
+        // TODO: find or create region assoc. with parameter
+        // TODO: post event
+    }
+
+    void removeRegion(Region region) {
+        // TODO: find region assoc. with parameter; remove from model
+        // TODO: post event
+    }
+
+    void addOrUpdateLink(Link link) {
+        // TODO: find ui-link assoc. with parameter; create or update.
+        // TODO: post event
+    }
+
+    void removeLink(Link link) {
+        // TODO: find ui-link assoc. with parameter; update or remove.
+        // TODO: post event
+    }
+
+    void addOrUpdateHost(Host host) {
+        // TODO: find or create host assoc. with parameter
+        // TODO: post event
+    }
+
+    void moveHost(Host host, Host prevHost) {
+        // TODO: process host-move
+        // TODO: post event
+    }
+
+    void removeHost(Host host) {
+        // TODO: find host assoc. with parameter; remove from model
+    }
 }
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 885eed2..0a4ce99 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
@@ -25,6 +25,8 @@
 import org.onosproject.cluster.ClusterEvent;
 import org.onosproject.cluster.ClusterEventListener;
 import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.cluster.RoleInfo;
 import org.onosproject.event.AbstractListenerManager;
 import org.onosproject.incubator.net.PortStatisticsService;
 import org.onosproject.incubator.net.tunnel.TunnelService;
@@ -32,6 +34,9 @@
 import org.onosproject.mastership.MastershipListener;
 import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.Link;
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
@@ -47,6 +52,7 @@
 import org.onosproject.net.link.LinkEvent;
 import org.onosproject.net.link.LinkListener;
 import org.onosproject.net.link.LinkService;
+import org.onosproject.net.region.Region;
 import org.onosproject.net.region.RegionEvent;
 import org.onosproject.net.region.RegionListener;
 import org.onosproject.net.region.RegionService;
@@ -178,28 +184,71 @@
     private class InternalClusterListener implements ClusterEventListener {
         @Override
         public void event(ClusterEvent event) {
-            // TODO: handle cluster event
+            ControllerNode cnode = event.subject();
+
+            switch (event.type()) {
+
+                case INSTANCE_ADDED:
+                case INSTANCE_ACTIVATED:
+                case INSTANCE_READY:
+                case INSTANCE_DEACTIVATED:
+                    cache.addOrUpdateClusterMember(cnode);
+                    break;
+
+                case INSTANCE_REMOVED:
+                    cache.removeClusterMember(cnode);
+                    break;
+
+                default:
+                    break;
+            }
         }
     }
 
     private class InternalMastershipListener implements MastershipListener {
         @Override
         public void event(MastershipEvent event) {
-            // TODO: handle mastership event
+            DeviceId deviceId = event.subject();
+            RoleInfo roleInfo = event.roleInfo();
+
+            switch (event.type()) {
+                case MASTER_CHANGED:
+                case BACKUPS_CHANGED:
+                    cache.updateMasterships(deviceId, roleInfo);
+                    break;
+
+                default:
+                    break;
+            }
         }
     }
 
     private class InternalRegionListener implements RegionListener {
         @Override
         public void event(RegionEvent event) {
-            // TODO: handle region event
+            Region region = event.subject();
+
+            switch (event.type()) {
+
+                case REGION_ADDED:
+                case REGION_UPDATED:
+                case REGION_MEMBERSHIP_CHANGED:
+                    cache.addOrUpdateRegion(region);
+                    break;
+
+                case REGION_REMOVED:
+                    cache.removeRegion(region);
+                    break;
+
+                default:
+                    break;
+            }
         }
     }
 
     private class InternalDeviceListener implements DeviceListener {
         @Override
         public void event(DeviceEvent event) {
-
             Device device = event.subject();
 
             switch (event.type()) {
@@ -224,28 +273,71 @@
     private class InternalLinkListener implements LinkListener {
         @Override
         public void event(LinkEvent event) {
-            // TODO: handle link event
+            Link link = event.subject();
+
+            switch (event.type()) {
+
+                case LINK_ADDED:
+                case LINK_UPDATED:
+                    cache.addOrUpdateLink(link);
+                    break;
+
+                case LINK_REMOVED:
+                    cache.removeLink(link);
+                    break;
+
+                default:
+                    break;
+            }
         }
     }
 
     private class InternalHostListener implements HostListener {
         @Override
         public void event(HostEvent event) {
-            // TODO: handle host event
+            Host host = event.subject();
+            Host prevHost = event.prevSubject();
+
+            switch (event.type()) {
+
+                case HOST_ADDED:
+                case HOST_UPDATED:
+                    cache.addOrUpdateHost(host);
+                    break;
+
+                case HOST_MOVED:
+                    cache.moveHost(host, prevHost);
+                    break;
+
+                case HOST_REMOVED:
+                    cache.removeHost(host);
+                    break;
+
+                default:
+                    break;
+            }
         }
     }
 
+    // =======================================================================
+    // NOTE: Neither intents nor flows are modeled by the UiTopology.
+    //       Rather, they are serviced directly from this class.
+    //       Additionally, since we are only retrieving counts (in the current
+    //        implementation), we'll fetch them on demand from the service.
+    //       Thus, the following internal listeners are stubs only (for now).
+    // =======================================================================
+
     private class InternalIntentListener implements IntentListener {
         @Override
         public void event(IntentEvent event) {
-            // TODO: handle intent event
+            // do nothing (for now)
         }
     }
 
     private class InternalFlowRuleListener implements FlowRuleListener {
         @Override
         public void event(FlowRuleEvent event) {
-            // TODO: handle flowrule event
+            // do nothing (for now)
         }
     }