ONOS-4971: Synthetic Link Data -- WIP

- Breaking out UiLink to subclasses for device links, host links, region links, region-device links,
    - (soon, also peer links).
- Augmenting UiLinkId to include regions as endpoints.
- Introduced UiSynthLink to encapsulate synthetic links bound to regions.
- Model Cache now computes synthetic links from the underlying link data.
- Added endPointA/B() and type() methods to UiLink.
- Updated topo2CurrentRegion response to include synth-links for the region.

Change-Id: Ifa62a15fbe0a58b134d92278b201fa7a72cbfa83
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 781650d..02c21dc 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
@@ -33,11 +33,13 @@
 import org.onosproject.ui.model.ServiceBundle;
 import org.onosproject.ui.model.topo.UiClusterMember;
 import org.onosproject.ui.model.topo.UiDevice;
+import org.onosproject.ui.model.topo.UiDeviceLink;
+import org.onosproject.ui.model.topo.UiEdgeLink;
 import org.onosproject.ui.model.topo.UiElement;
 import org.onosproject.ui.model.topo.UiHost;
-import org.onosproject.ui.model.topo.UiLink;
 import org.onosproject.ui.model.topo.UiLinkId;
 import org.onosproject.ui.model.topo.UiRegion;
+import org.onosproject.ui.model.topo.UiSynthLink;
 import org.onosproject.ui.model.topo.UiTopoLayout;
 import org.onosproject.ui.model.topo.UiTopoLayoutId;
 import org.onosproject.ui.model.topo.UiTopology;
@@ -101,7 +103,7 @@
         loadClusterMembers();
         loadRegions();
         loadDevices();
-        loadLinks();
+        loadDeviceLinks();
         loadHosts();
     }
 
@@ -334,66 +336,72 @@
     }
 
 
-    // === LINKS
+    // === LINKS ===
 
-    private UiLink addNewLink(UiLinkId id) {
-        UiLink uiLink = new UiLink(uiTopology, id);
-        uiTopology.add(uiLink);
-        return uiLink;
+    private UiDeviceLink addNewDeviceLink(UiLinkId id) {
+        UiDeviceLink uiDeviceLink = new UiDeviceLink(uiTopology, id);
+        uiTopology.add(uiDeviceLink);
+        return uiDeviceLink;
     }
 
-    private void updateLink(UiLink uiLink, Link link) {
-        uiLink.attachBackingLink(link);
+    private UiEdgeLink addNewEdgeLink(UiLinkId id) {
+        UiEdgeLink uiEdgeLink = new UiEdgeLink(uiTopology, id);
+        uiTopology.add(uiEdgeLink);
+        return uiEdgeLink;
     }
 
-    private void loadLinks() {
+    private void updateDeviceLink(UiDeviceLink uiDeviceLink, Link link) {
+        uiDeviceLink.attachBackingLink(link);
+    }
+
+    private void loadDeviceLinks() {
         for (Link link : services.link().getLinks()) {
             UiLinkId id = uiLinkId(link);
 
-            UiLink uiLink = uiTopology.findLink(id);
-            if (uiLink == null) {
-                uiLink = addNewLink(id);
+            UiDeviceLink uiDeviceLink = uiTopology.findDeviceLink(id);
+            if (uiDeviceLink == null) {
+                uiDeviceLink = addNewDeviceLink(id);
             }
-            updateLink(uiLink, link);
+            updateDeviceLink(uiDeviceLink, link);
         }
     }
 
     // invoked from UiSharedTopologyModel link listener
-    void addOrUpdateLink(Link link) {
+    void addOrUpdateDeviceLink(Link link) {
         UiLinkId id = uiLinkId(link);
-        UiLink uiLink = uiTopology.findLink(id);
-        if (uiLink == null) {
-            uiLink = addNewLink(id);
+        UiDeviceLink uiDeviceLink = uiTopology.findDeviceLink(id);
+        if (uiDeviceLink == null) {
+            uiDeviceLink = addNewDeviceLink(id);
         }
-        updateLink(uiLink, link);
+        updateDeviceLink(uiDeviceLink, link);
 
-        postEvent(LINK_ADDED_OR_UPDATED, uiLink);
+        postEvent(LINK_ADDED_OR_UPDATED, uiDeviceLink);
     }
 
     // package private for unit test access
-    UiLink accessLink(UiLinkId id) {
-        return uiTopology.findLink(id);
+    UiDeviceLink accessDeviceLink(UiLinkId id) {
+        return uiTopology.findDeviceLink(id);
     }
 
     // invoked from UiSharedTopologyModel link listener
-    void removeLink(Link link) {
+    void removeDeviceLink(Link link) {
         UiLinkId id = uiLinkId(link);
-        UiLink uiLink = uiTopology.findLink(id);
-        if (uiLink != null) {
-            boolean remaining = uiLink.detachBackingLink(link);
+        UiDeviceLink uiDeviceLink = uiTopology.findDeviceLink(id);
+        if (uiDeviceLink != null) {
+            boolean remaining = uiDeviceLink.detachBackingLink(link);
             if (remaining) {
-                postEvent(LINK_ADDED_OR_UPDATED, uiLink);
+                postEvent(LINK_ADDED_OR_UPDATED, uiDeviceLink);
             } else {
-                uiTopology.remove(uiLink);
-                postEvent(LINK_REMOVED, uiLink);
+                uiTopology.remove(uiDeviceLink);
+                postEvent(LINK_REMOVED, uiDeviceLink);
             }
         } else {
-            log.warn(E_NO_ELEMENT, "link", id);
+            log.warn(E_NO_ELEMENT, "Device link", id);
         }
     }
 
-    Set<UiLink> getAllLinks() {
-        return uiTopology.allLinks();
+    Set<UiDeviceLink> getAllDeviceLinks() {
+        return uiTopology.allDeviceLinks();
     }
 
     // === HOSTS
@@ -411,20 +419,19 @@
         host.setEdgeLinkId(elinkId);
 
         // add synthesized edge link to the topology
-        UiLink edgeLink = addNewLink(elinkId);
+        UiEdgeLink edgeLink = addNewEdgeLink(elinkId);
         edgeLink.attachEdgeLink(elink);
 
         return host;
     }
 
-    private void insertNewUiLink(UiLinkId id, EdgeLink e) {
-        UiLink newEdgeLink = addNewLink(id);
+    private void insertNewUiEdgeLink(UiLinkId id, EdgeLink e) {
+        UiEdgeLink newEdgeLink = addNewEdgeLink(id);
         newEdgeLink.attachEdgeLink(e);
-
     }
 
     private void updateHost(UiHost uiHost, Host h) {
-        UiLink existing = uiTopology.findLink(uiHost.edgeLinkId());
+        UiEdgeLink existing = uiTopology.findEdgeLink(uiHost.edgeLinkId());
 
         EdgeLink currentElink = synthesizeLink(h);
         UiLinkId currentElinkId = uiLinkId(currentElink);
@@ -432,7 +439,7 @@
         if (existing != null) {
             if (!currentElinkId.equals(existing.id())) {
                 // edge link has changed
-                insertNewUiLink(currentElinkId, currentElink);
+                insertNewUiEdgeLink(currentElinkId, currentElink);
                 uiHost.setEdgeLinkId(currentElinkId);
 
                 uiTopology.remove(existing);
@@ -440,7 +447,7 @@
 
         } else {
             // no previously existing edge link
-            insertNewUiLink(currentElinkId, currentElink);
+            insertNewUiEdgeLink(currentElinkId, currentElink);
             uiHost.setEdgeLinkId(currentElinkId);
 
         }
@@ -489,7 +496,7 @@
         HostId id = host.id();
         UiHost uiHost = uiTopology.findHost(id);
         if (uiHost != null) {
-            UiLink edgeLink = uiTopology.findLink(uiHost.edgeLinkId());
+            UiEdgeLink edgeLink = uiTopology.findEdgeLink(uiHost.edgeLinkId());
             uiTopology.remove(edgeLink);
             uiTopology.remove(uiHost);
             postEvent(HOST_REMOVED, uiHost);
@@ -503,11 +510,17 @@
     }
 
 
+    // === SYNTHETIC LINKS
+
+    List<UiSynthLink> getSynthLinks(RegionId regionId) {
+        return uiTopology.findSynthLinks(regionId);
+    }
+
     /**
      * Refreshes the internal state.
      */
     public void refresh() {
-        // fix up internal linkages if they aren't correct
+        // fix up internal linkages to ensure they are correct
 
         // make sure regions reflect layout containment hierarchy
         fixupContainmentHierarchy(uiTopology.nullRegion());
@@ -542,8 +555,13 @@
         Set<DeviceId> leftOver = new HashSet<>(allDevices.size());
         allDevices.forEach(d -> leftOver.add(d.id()));
         uiTopology.nullRegion().reconcileDevices(leftOver);
+
+        // now that we have correct region hierarchy, and devices are in their
+        //  respective regions, we can compute synthetic links for each region.
+        uiTopology.computeSynthLinks();
     }
 
+
     // === CACHE STATISTICS
 
     /**
@@ -583,12 +601,21 @@
     }
 
     /**
-     * Returns the number of links in the topology.
+     * Returns the number of device links in the topology.
      *
-     * @return number of links
+     * @return number of device links
      */
-    public int linkCount() {
-        return uiTopology.linkCount();
+    public int deviceLinkCount() {
+        return uiTopology.deviceLinkCount();
+    }
+
+    /**
+     * Returns the number of edge links in the topology.
+     *
+     * @return number of edge links
+     */
+    public int edgeLinkCount() {
+        return uiTopology.edgeLinkCount();
     }
 
     /**
@@ -600,4 +627,12 @@
         return uiTopology.hostCount();
     }
 
+    /**
+     * Returns the number of synthetic links in the topology.
+     *
+     * @return the number of synthetic links
+     */
+    public int synthLinkCount() {
+        return uiTopology.synthLinkCount();
+    }
 }