Sketching out driver matrix data structures.

Change-Id: I8739e0a49de250bc015b994638bfc6df42393000
diff --git a/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverMatrixMessageHandler.java b/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverMatrixMessageHandler.java
deleted file mode 100644
index edc1b88..0000000
--- a/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverMatrixMessageHandler.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2014,2015 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.drivermatrix;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableSet;
-import org.onosproject.ui.RequestHandler;
-import org.onosproject.ui.UiMessageHandler;
-import org.onosproject.ui.table.TableModel;
-import org.onosproject.ui.table.TableRequestHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Skeletal ONOS UI Table-View message handler.
- */
-public class DriverMatrixMessageHandler extends UiMessageHandler {
-
-    private static final String SAMPLE_TABLE_DATA_REQ = "driverMatrixDataRequest";
-    private static final String SAMPLE_TABLE_DATA_RESP = "driverMatrixDataResponse";
-    private static final String SAMPLE_TABLES = "driverMatrixs";
-
-    private static final String SAMPLE_TABLE_DETAIL_REQ = "driverMatrixDetailsRequest";
-    private static final String SAMPLE_TABLE_DETAIL_RESP = "driverMatrixDetailsResponse";
-    private static final String DETAILS = "details";
-
-    private static final String ID = "id";
-    private static final String LABEL = "label";
-    private static final String CODE = "code";
-    private static final String COMMENT = "comment";
-    private static final String RESULT = "result";
-
-    private static final String[] COLUMN_IDS = {ID, LABEL, CODE};
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-
-    @Override
-    protected Collection<RequestHandler> createRequestHandlers() {
-        return ImmutableSet.of(
-                new SampleTableDataRequestHandler(),
-                new SampleTableDetailRequestHandler()
-        );
-    }
-
-    // handler for sample table requests
-    private final class SampleTableDataRequestHandler extends TableRequestHandler {
-
-        private static final String NO_ROWS_MESSAGE = "No data found";
-
-        private SampleTableDataRequestHandler() {
-            super(SAMPLE_TABLE_DATA_REQ, SAMPLE_TABLE_DATA_RESP, SAMPLE_TABLES);
-        }
-
-        // if necessary, override defaultColumnId() -- if it isn't "id"
-
-        @Override
-        protected String[] getColumnIds() {
-            return COLUMN_IDS;
-        }
-
-        @Override
-        protected String noRowsMessage(ObjectNode payload) {
-            return NO_ROWS_MESSAGE;
-        }
-
-        // if required, override createTableModel() to set column formatters / comparators
-
-        @Override
-        protected void populateTable(TableModel tm, ObjectNode payload) {
-            // === NOTE: the table model supplied here will have been created
-            // via  a call to createTableModel(). To assign non-default
-            // cell formatters or comparators to the table model, override
-            // createTableModel() and set them there.
-
-            // === retrieve table row items from some service...
-            // SomeService ss = get(SomeService.class);
-            // List<Item> items = ss.getItems()
-
-            // fake data for demonstration purposes...
-            List<Item> items = getItems();
-            for (Item item : items) {
-                populateRow(tm.addRow(), item);
-            }
-        }
-
-        private void populateRow(TableModel.Row row, Item item) {
-            row.cell(ID, item.id())
-                    .cell(LABEL, item.label())
-                    .cell(CODE, item.code());
-        }
-    }
-
-
-    // handler for sample item details requests
-    private final class SampleTableDetailRequestHandler extends RequestHandler {
-
-        private SampleTableDetailRequestHandler() {
-            super(SAMPLE_TABLE_DETAIL_REQ);
-        }
-
-        @Override
-        public void process(long sid, ObjectNode payload) {
-            String id = string(payload, ID, "(none)");
-
-            // SomeService ss = get(SomeService.class);
-            // Item item = ss.getItemDetails(id)
-
-            // fake data for demonstration purposes...
-            Item item = getItem(id);
-
-            ObjectNode rootNode = objectNode();
-            ObjectNode data = objectNode();
-            rootNode.set(DETAILS, data);
-
-            if (item == null) {
-                rootNode.put(RESULT, "Item with id '" + id + "' not found");
-                log.warn("attempted to get item detail for id '{}'", id);
-
-            } else {
-                rootNode.put(RESULT, "Found item with id '" + id + "'");
-
-                data.put(ID, item.id());
-                data.put(LABEL, item.label());
-                data.put(CODE, item.code());
-                data.put(COMMENT, "Some arbitrary comment");
-            }
-
-            sendMessage(SAMPLE_TABLE_DETAIL_RESP, 0, rootNode);
-        }
-    }
-
-
-    // ===================================================================
-    // NOTE: The code below this line is to create fake data for this
-    //       sample code. Normally you would use existing services to
-    //       provide real data.
-
-    // Lookup a single item.
-    private static Item getItem(String id) {
-        // We realize this code is really inefficient, but
-        // it suffices for our purposes of demonstration...
-        for (Item item : getItems()) {
-            if (item.id().equals(id)) {
-                return item;
-            }
-        }
-        return null;
-    }
-
-    // Produce a list of items.
-    private static List<Item> getItems() {
-        List<Item> items = new ArrayList<>();
-        items.add(new Item("item-1", "foo", 42));
-        items.add(new Item("item-2", "bar", 99));
-        items.add(new Item("item-3", "baz", 65));
-        return items;
-    }
-
-    // Simple model class to provide sample data
-    private static class Item {
-        private final String id;
-        private final String label;
-        private final int code;
-
-        Item(String id, String label, int code) {
-            this.id = id;
-            this.label = label;
-            this.code = code;
-        }
-
-        String id() {
-            return id;
-        }
-
-        String label() {
-            return label;
-        }
-
-        int code() {
-            return code;
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverMatrixComponent.java b/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverViewComponent.java
similarity index 91%
rename from apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverMatrixComponent.java
rename to apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverViewComponent.java
index e2b3b2e..5f4f918 100644
--- a/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverMatrixComponent.java
+++ b/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverViewComponent.java
@@ -31,10 +31,10 @@
 import java.util.List;
 
 /**
- * Skeletal ONOS UI Table-View application component.
+ * Registers driver matrix view.
  */
 @Component(immediate = true)
-public class DriverMatrixComponent {
+public class DriverViewComponent {
 
     private static final String VIEW_ID = "driverMatrix";
     private static final String VIEW_TEXT = "Driver Matrix";
@@ -46,13 +46,13 @@
 
     // List of application views
     private final List<UiView> uiViews = ImmutableList.of(
-            new UiView(UiView.Category.OTHER, VIEW_ID, VIEW_TEXT)
+            new UiView(UiView.Category.PLATFORM, VIEW_ID, VIEW_TEXT)
     );
 
     // Factory for UI message handlers
     private final UiMessageHandlerFactory messageHandlerFactory =
             () -> ImmutableList.of(
-                    new DriverMatrixMessageHandler()
+                    new DriverViewMessageHandler()
             );
 
     // Application UI extension
diff --git a/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverViewMessageHandler.java b/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverViewMessageHandler.java
new file mode 100644
index 0000000..8e9cdb5
--- /dev/null
+++ b/apps/drivermatrix/src/main/java/org/onosproject/drivermatrix/DriverViewMessageHandler.java
@@ -0,0 +1,140 @@
+/*
+ * 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.drivermatrix;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.ui.RequestHandler;
+import org.onosproject.ui.UiMessageHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Message handler for device view related messages.
+ */
+public class DriverViewMessageHandler extends UiMessageHandler {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private static final String DRIVER_DATA_REQUEST = "driverDataRequest";
+    private static final String DRIVER_DATA_RESPONSE = "driverDataResponse";
+
+    private static final String DRIVERS = "drivers";
+    private static final String BEHAVIOURS = "behaviours";
+
+    private static final Comparator<? super Class<? extends Behaviour>> BEHAVIOUR_BY_NAME =
+            (o1, o2) -> o1.getSimpleName().compareTo(o2.getSimpleName());
+    private static final Comparator<? super Driver> DRIVER_BY_NAME =
+            (o1, o2) -> o1.name().compareTo(o2.name());
+
+
+    @Override
+    protected Collection<RequestHandler> createRequestHandlers() {
+        return ImmutableSet.of(
+                new DataRequestHandler()
+//                new DetailRequestHandler()
+        );
+    }
+
+    // handler for device table requests
+    private final class DataRequestHandler extends RequestHandler {
+
+        private DataRequestHandler() {
+            super(DRIVER_DATA_REQUEST);
+        }
+
+        @Override
+        public void process(long sid, ObjectNode payload) {
+            // Search for drivers producing two artifacts:
+            // 1) list of abstract behaviours as column listing
+            // 2) sparse matrix of drivers-to-concrete behaviours
+
+            DriverService driverService = get(DriverService.class);
+
+            // Collect all behaviours for all drivers
+            Map<Driver, Set<Class<? extends Behaviour>>> driverBehaviours = new HashMap<>();
+            driverService.getDrivers().forEach(d -> driverBehaviours.put(d, d.behaviours()));
+
+            // Order all drivers
+            List<Driver> drivers = orderDrivers(driverBehaviours.keySet());
+
+            // Produce a union of all behaviours (and order them)
+            List<Class<? extends Behaviour>> behaviours = orderBehaviours(driverBehaviours.values());
+
+            // Produce a JSON structure and send it
+            sendMessage(DRIVER_DATA_RESPONSE, 0, driversJson(driverBehaviours, drivers, behaviours));
+        }
+
+        private List<Driver> orderDrivers(Set<Driver> drivers) {
+            // For now order by alphanumeric name of the driver
+            List<Driver> ordered = new ArrayList<>(drivers);
+            ordered.sort(DRIVER_BY_NAME);
+            return ordered;
+        }
+
+        private List<Class<? extends Behaviour>>
+        orderBehaviours(Collection<Set<Class<? extends Behaviour>>> behaviours) {
+            // For now order by alphanumeric name of the abstract behaviour simple name
+            Set<Class<? extends Behaviour>> allBehaviours = new HashSet<>();
+            behaviours.forEach(allBehaviours::addAll);
+            List<Class<? extends Behaviour>> ordered = new ArrayList<>(allBehaviours);
+            ordered.sort(BEHAVIOUR_BY_NAME);
+            return ordered;
+        }
+
+        private ObjectNode driversJson(Map<Driver, Set<Class<? extends Behaviour>>> driverBehaviours,
+                                       List<Driver> drivers,
+                                       List<Class<? extends Behaviour>> behaviours) {
+            ObjectNode root = objectNode();
+            addBehaviours(root, behaviours);
+            addDrivers(root, drivers);
+            addRelationships(root, drivers, behaviours, driverBehaviours);
+            return root;
+        }
+
+        private void addBehaviours(ObjectNode root, List<Class<? extends Behaviour>> behaviours) {
+            ArrayNode array = arrayNode();
+            root.set(BEHAVIOURS, array);
+            behaviours.forEach(b -> array.add(b.getSimpleName()));
+        }
+
+        private void addDrivers(ObjectNode root, List<Driver> drivers) {
+            ArrayNode array = arrayNode();
+            root.set(DRIVERS, array);
+            drivers.forEach(d -> array.add(d.name()));
+        }
+
+        private void addRelationships(ObjectNode root,
+                                      List<Driver> drivers, List<Class<? extends Behaviour>> behaviours,
+                                      Map<Driver, Set<Class<? extends Behaviour>>> driverBehaviours) {
+        }
+    }
+
+}
diff --git a/apps/drivermatrix/src/main/resources/app/view/driverMatrix/driverMatrix.js b/apps/drivermatrix/src/main/resources/app/view/driverMatrix/driverMatrix.js
index 2f33a54..3c77c87 100644
--- a/apps/drivermatrix/src/main/resources/app/view/driverMatrix/driverMatrix.js
+++ b/apps/drivermatrix/src/main/resources/app/view/driverMatrix/driverMatrix.js
@@ -6,8 +6,8 @@
     var $log, $scope, fs, wss;
 
     // constants
-    var detailsReq = 'driverMatrixDetailsRequest',
-        detailsResp = 'driverMatrixDetailsResponse',
+    var detailsReq = 'driverDataRequest',
+        detailsResp = 'driverDataResponse',
         pName = 'ov-driver-matrix-item-details-panel',
 
         propOrder = ['id', 'label', 'code'],
@@ -40,8 +40,9 @@
     }
 
     function respDetailsCb(data) {
-        $scope.panelDetails = data.details;
-        $scope.$apply();
+        $log.debug(data);
+        //$scope.panelDetails = data.details;
+        //$scope.$apply();
     }
 
     angular.module('ovDriverMatrix', [])
@@ -62,22 +63,24 @@
                 handlers[detailsResp] = respDetailsCb;
                 wss.bindHandlers(handlers);
 
-                // custom selection callback
-                function selCb($event, row) {
-                    if ($scope.selId) {
-                        wss.sendEvent(detailsReq, { id: row.id });
-                    } else {
-                        $scope.hidePanel();
-                    }
-                    $log.debug('Got a click on:', row);
-                }
+                wss.sendEvent(detailsReq);
 
-                // TableBuilderService creating a table for us
-                tbs.buildTable({
-                    scope: $scope,
-                    tag: 'driverMatrix',
-                    selCb: selCb
-                });
+                //// custom selection callback
+                //function selCb($event, row) {
+                //    if ($scope.selId) {
+                //        wss.sendEvent(detailsReq, { id: row.id });
+                //    } else {
+                //        $scope.hidePanel();
+                //    }
+                //    $log.debug('Got a click on:', row);
+                //}
+
+                //// TableBuilderService creating a table for us
+                //tbs.buildTable({
+                //    scope: $scope,
+                //    tag: 'driverMatrix',
+                //    selCb: selCb
+                //});
 
                 // cleanup
                 $scope.$on('$destroy', function () {