DriverViewMessageHandler.java 5.68 KB
/*
 * 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.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Message handler for driver matrix view related messages.
 */
public class DriverViewMessageHandler extends UiMessageHandler {

    private final Logger log = LoggerFactory.getLogger(getClass());

    private static final int ONE = 1;
    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 String MATRIX = "matrix";

    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()
                // TODO: for row selection, produce data for detail panel
//                new DetailRequestHandler()
        );
    }

    // handler for driver matrix requests
    private final class DataRequestHandler extends RequestHandler {

        private DataRequestHandler() {
            super(DRIVER_DATA_REQUEST);
        }

        @Override
        public void process(long sid, ObjectNode payload) {
            DriverService driverService = get(DriverService.class);

            List<Driver> drivers = new ArrayList<>(driverService.getDrivers());
            drivers = orderDrivers(drivers);

            // Produce a union of all behaviours (and order them)
            List<Class<? extends Behaviour>> behaviours = orderBehaviours(drivers);

            // Produce a JSON structure and send it
            sendMessage(DRIVER_DATA_RESPONSE, 0, driversJson(drivers, behaviours));
        }

        private List<Driver> orderDrivers(List<Driver> drivers) {
            // For now order by alphanumeric name of the driver
            drivers.sort(DRIVER_BY_NAME);
            return drivers;
        }

        private List<Class<? extends Behaviour>> orderBehaviours(List<Driver> drivers) {
            // first, produce a set-union of all behaviours from all drivers...
            Set<Class<? extends Behaviour>> allBehaviours = new HashSet<>();
            drivers.forEach(d -> allBehaviours.addAll(d.behaviours()));

            // for now, order by alphanumeric name of the abstract behaviour simple name
            List<Class<? extends Behaviour>> ordered = new ArrayList<>(allBehaviours);
            ordered.sort(BEHAVIOUR_BY_NAME);
            return ordered;
        }

        private ObjectNode driversJson(List<Driver> drivers,
                                       List<Class<? extends Behaviour>> behaviours) {
            ObjectNode root = objectNode();
            addBehaviours(root, behaviours);
            addDrivers(root, drivers);
            addMatrixCells(root, drivers);
            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 Set<Driver> findLineage(Driver driver) {
            ImmutableSet.Builder<Driver> lineage = ImmutableSet.builder();
            lineage.add(driver);
            List<Driver> parents = driver.parents();
            if (parents != null) {
                parents.forEach(p -> lineage.addAll(findLineage(p)));
            }
            return lineage.build();
        }

        private void addMatrixCells(ObjectNode root, List<Driver> drivers) {
            ObjectNode matrix = objectNode();
            root.set(MATRIX, matrix);

            drivers.forEach(driver -> {
                ObjectNode dnode = objectNode();
                matrix.set(driver.name(), dnode);
                Set<Driver> lineage = findLineage(driver);
                lineage.forEach(d -> d.behaviours().forEach(b -> {
                    // TODO: can put a payload here, rather than a '1' marker
                    dnode.put(b.getSimpleName(), ONE);
                }));
            });
        }
    }
}