Adding commands for managing layouts.

Adding support for wiping out regions and layouts.
Refactored UI layout manager to allow public knowledge of default layout id.
Enhanced test topo for layout hierarchy.

Change-Id: I254fd494175e753f542f12a664618c1a83f72127
diff --git a/cli/src/main/java/org/onosproject/cli/net/LayoutAddCommand.java b/cli/src/main/java/org/onosproject/cli/net/LayoutAddCommand.java
new file mode 100644
index 0000000..5d160bd
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/LayoutAddCommand.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionService;
+import org.onosproject.ui.UiTopoLayoutService;
+import org.onosproject.ui.model.topo.UiTopoLayout;
+import org.onosproject.ui.model.topo.UiTopoLayoutId;
+
+import static org.onosproject.net.region.RegionId.regionId;
+import static org.onosproject.ui.model.topo.UiTopoLayoutId.layoutId;
+
+/**
+ * Creates a new UI layout.
+ */
+@Command(scope = "onos", name = "layout-add",
+        description = "Creates a new UI layout")
+public class LayoutAddCommand extends AbstractShellCommand {
+
+    private static final String FMT = "id=%s, name=%s, type=%s";
+    private static final String FMT_MASTER = "  master=%s";
+
+    @Argument(index = 0, name = "id", description = "Layout ID",
+            required = true, multiValued = false)
+    String id = null;
+
+    @Argument(index = 1, name = "id", description = "Region ID (optional)",
+            required = false, multiValued = false)
+    String regionId = null;
+
+    @Argument(index = 2, name = "id", description = "Parent layout ID (optional)",
+            required = false, multiValued = false)
+    String parentId = null;
+
+    private RegionService regionService;
+
+    @Override
+    protected void execute() {
+        UiTopoLayoutService service = get(UiTopoLayoutService.class);
+        RegionService regionService = get(RegionService.class);
+
+        Region region = regionId == null ? null : regionService.getRegion(regionId(regionId));
+        UiTopoLayoutId pid = parentId == null ? UiTopoLayoutId.DEFAULT_ID : layoutId(parentId);
+
+        UiTopoLayout layout = new UiTopoLayout(layoutId(id), region, pid);
+        service.addLayout(layout);
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/LayoutListCommand.java b/cli/src/main/java/org/onosproject/cli/net/LayoutListCommand.java
new file mode 100644
index 0000000..014717d
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/LayoutListCommand.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.ui.UiTopoLayoutService;
+import org.onosproject.ui.model.topo.UiTopoLayout;
+import org.onosproject.ui.model.topo.UiTopoLayoutId;
+import org.onosproject.utils.Comparators;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * List layout details.
+ */
+@Command(scope = "onos", name = "layouts",
+        description = "List layout details")
+public class LayoutListCommand extends AbstractShellCommand {
+
+    private static final String FMT = "id=%s, region=%s, parent=%s";
+
+    @Argument(index = 0, name = "id", description = "Layout ID",
+            required = false, multiValued = false)
+    String id = null;
+
+    private UiTopoLayoutService layoutService;
+
+    @Override
+    protected void execute() {
+        layoutService = get(UiTopoLayoutService.class);
+        if (id == null) {
+            for (UiTopoLayout layout : getSortedLayouts(layoutService)) {
+                printLayout(layout);
+            }
+        } else {
+            UiTopoLayout layout = layoutService.getLayout(UiTopoLayoutId.layoutId(id));
+            if (layout == null) {
+                error("No such region %s", id);
+            } else {
+                printLayout(layout);
+            }
+        }
+    }
+
+    private List<UiTopoLayout> getSortedLayouts(UiTopoLayoutService service) {
+        List<UiTopoLayout> layouts = newArrayList(service.getLayouts());
+        Collections.sort(layouts, Comparators.LAYOUT_COMPARATOR);
+        return layouts;
+    }
+
+    private void printLayout(UiTopoLayout layout) {
+        print(FMT, layout.id(), layout.regionId(),
+              layout.parent() != null ? layout.parent().id() : "none");
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java b/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java
index f64a304..ddd9970 100644
--- a/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java
@@ -26,6 +26,8 @@
 import org.onosproject.net.intent.IntentService;
 import org.onosproject.net.intent.IntentState;
 import org.onosproject.net.link.LinkAdminService;
+import org.onosproject.net.region.RegionAdminService;
+import org.onosproject.ui.UiTopoLayoutService;
 
 /**
  * Wipes-out the entire network information base, i.e. devices, links, hosts, intents.
@@ -51,6 +53,9 @@
         wipeOutHosts();
         wipeOutDevices();
         wipeOutLinks();
+
+        wipeOutLayouts();
+        wipeOutRegions();
     }
 
     private void wipeOutIntents() {
@@ -106,4 +111,16 @@
             }
         }
     }
+
+    private void wipeOutLayouts() {
+        print("Wiping UI layouts");
+        UiTopoLayoutService service = get(UiTopoLayoutService.class);
+        service.getLayouts().forEach(service::removeLayout);
+    }
+
+    private void wipeOutRegions() {
+        print("Wiping regions");
+        RegionAdminService service = get(RegionAdminService.class);
+        service.getRegions().forEach(r -> service.removeRegion(r.id()));
+    }
 }
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index c767289..5e3577e 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -631,6 +631,19 @@
             </completers>
         </command>
 
+        <!-- UI Layout commands -->
+        <command>
+            <action class="org.onosproject.cli.net.LayoutListCommand"/>
+        </command>
+        <command>
+            <action class="org.onosproject.cli.net.LayoutAddCommand"/>
+        </command>
+        <!--TODO: add this + completers
+        <command>
+            <action class="org.onosproject.cli.net.LayoutRemoveCommand"/>
+        </command>
+        -->
+
         <!--virtual network commands -->
         <command>
             <action class="org.onosproject.cli.net.vnet.TenantListCommand"/>