ONOS-4971: Synthetic Link Data -- WIP, merge anyway

- created temp Topology2 View (topoX) to "process" and display topology data.
- made root layout parent of itself (just like /.. = /) to simplify layout hierarchy operations.
- added nodeType property to JSON rep of regions/devices/hosts.
- augmented peers to include devices.
- added skeleton topo2NavRegion event.

Change-Id: I8219125d7dfe33d211350ae27111a3d9de6eb4ca
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
index 02df84c..8a26a92 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/Topo2Jsonifier.java
@@ -40,6 +40,8 @@
 import org.onosproject.ui.model.topo.UiNode;
 import org.onosproject.ui.model.topo.UiRegion;
 import org.onosproject.ui.model.topo.UiTopoLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -62,6 +64,12 @@
     private static final String E_UNKNOWN_UI_NODE =
             "Unknown subclass of UiNode: ";
 
+    private static final String REGION = "region";
+    private static final String DEVICE = "device";
+    private static final String HOST = "host";
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
     private final ObjectMapper mapper = new ObjectMapper();
 
     private ServiceDirectory directory;
@@ -245,6 +253,7 @@
     private ObjectNode json(UiDevice device) {
         ObjectNode node = objectNode()
                 .put("id", device.idAsString())
+                .put("nodeType", DEVICE)
                 .put("type", device.type())
                 .put("online", device.isOnline())
                 .put("master", nullIsEmpty(device.master()))
@@ -266,6 +275,7 @@
     private ObjectNode json(UiHost host) {
         return objectNode()
                 .put("id", host.idAsString())
+                .put("nodeType", HOST)
                 .put("layer", host.layer());
         // TODO: complete host details
     }
@@ -281,10 +291,31 @@
     private ObjectNode jsonClosedRegion(UiRegion region) {
         return objectNode()
                 .put("id", region.idAsString())
+                .put("nodeType", REGION)
                 .put("nDevs", region.deviceCount());
         // TODO: complete closed-region details
     }
 
+    /**
+     * Returns a JSON array representation of a set of regions/devices. Note
+     * that the information is sufficient for showing regions as nodes.
+     *
+     * @param nodes the nodes
+     * @return a JSON representation of the nodes
+     */
+    public ArrayNode closedNodes(Set<UiNode> nodes) {
+        ArrayNode array = arrayNode();
+        for (UiNode node: nodes) {
+            if (node instanceof UiRegion) {
+                array.add(jsonClosedRegion((UiRegion) node));
+            } else if (node instanceof UiDevice) {
+                array.add(json((UiDevice) node));
+            } else {
+                log.warn("Unexpected node instance: {}", node.getClass());
+            }
+        }
+        return array;
+    }
 
     /**
      * Returns a JSON array representation of a list of regions. Note that the