ONOS-2186 - GUI Topo Overlay - (WIP)
- moved TopoUtils, NodeSelection, BiLink and Map (and Base derivatives) to core API.

Change-Id: I105f6df6508b1597ffde19fe7e360d3775abf250
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/BaseLink.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/BaseLink.java
deleted file mode 100644
index 043b471..0000000
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/BaseLink.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 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.ui.impl.topo;
-
-import org.onosproject.net.Link;
-import org.onosproject.net.LinkKey;
-import org.onosproject.ui.topo.LinkHighlight;
-
-/**
- * A simple concrete implementation of a {@link BiLink}.
- * Note that this implementation does not generate any link highlights.
- */
-public class BaseLink extends BiLink {
-
-    /**
-     * Constructs a base link for the given key and initial link.
-     *
-     * @param key  canonical key for this base link
-     * @param link first link
-     */
-    public BaseLink(LinkKey key, Link link) {
-        super(key, link);
-    }
-
-    @Override
-    public LinkHighlight highlight(Enum<?> type) {
-        return null;
-    }
-}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/BaseLinkMap.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/BaseLinkMap.java
deleted file mode 100644
index 14c66ea..0000000
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/BaseLinkMap.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 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.ui.impl.topo;
-
-import org.onosproject.net.Link;
-import org.onosproject.net.LinkKey;
-
-/**
- * Collection of {@link BaseLink}s.
- */
-public class BaseLinkMap extends BiLinkMap<BaseLink> {
-    @Override
-    public BaseLink create(LinkKey key, Link link) {
-        return new BaseLink(key, link);
-    }
-}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/BiLink.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/BiLink.java
deleted file mode 100644
index 8ccf543..0000000
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/BiLink.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 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.ui.impl.topo;
-
-import org.onosproject.net.Link;
-import org.onosproject.net.LinkKey;
-import org.onosproject.ui.topo.LinkHighlight;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Representation of a link and its inverse, as a partial implementation.
- * <p>
- * Subclasses will decide how to generate the link highlighting (coloring
- * and labeling) for the topology view.
- */
-public abstract class BiLink {
-
-    private final LinkKey key;
-    private final Link one;
-    private Link two;
-
-    /**
-     * Constructs a bi-link for the given key and initial link. It is expected
-     * that the caller will have used {@link TopoUtils#canonicalLinkKey(Link)}
-     * to generate the key.
-     *
-     * @param key canonical key for this bi-link
-     * @param link first link
-     */
-    public BiLink(LinkKey key, Link link) {
-        this.key = checkNotNull(key);
-        this.one = checkNotNull(link);
-    }
-
-    /**
-     * Sets the second link for this bi-link.
-     *
-     * @param link second link
-     */
-    public void setOther(Link link) {
-        this.two = checkNotNull(link);
-    }
-
-    /**
-     * Returns the link identifier in the form expected on the Topology View
-     * in the web client.
-     *
-     * @return link identifier
-     */
-    public String linkId() {
-        return TopoUtils.compactLinkString(one);
-    }
-
-    /**
-     * Returns the key for this bi-link.
-     *
-     * @return the key
-     */
-    public LinkKey key() {
-        return key;
-    }
-
-    /**
-     * Returns the first link in this bi-link.
-     *
-     * @return the first link
-     */
-    public Link one() {
-        return one;
-    }
-
-    /**
-     * Returns the second link in this bi-link.
-     *
-     * @return the second link
-     */
-    public Link two() {
-        return two;
-    }
-
-    /**
-     * Returns the link highlighting to use, based on this bi-link's current
-     * state.
-     *
-     * @param type optional highlighting type parameter
-     * @return link highlighting model
-     */
-    public abstract LinkHighlight highlight(Enum<?> type);
-}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/BiLinkMap.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/BiLinkMap.java
deleted file mode 100644
index 18565d7..0000000
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/BiLinkMap.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 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.ui.impl.topo;
-
-import org.onosproject.net.Link;
-import org.onosproject.net.LinkKey;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Represents a collection of {@link BiLink} concrete classes. These maps
- * are used to collate a set of unidirectional {@link Link}s into a smaller
- * set of bi-directional {@link BiLink} derivatives.
- * <p>
- * @param <B> the type of bi-link subclass
- */
-public abstract class BiLinkMap<B extends BiLink> {
-
-    private final Map<LinkKey, B> map = new HashMap<>();
-
-    /**
-     * Creates a new instance of a bi-link. Concrete subclasses should
-     * instantiate and return the appropriate bi-link subclass.
-     *
-     * @param key the link key
-     * @param link the initial link
-     * @return a new instance
-     */
-    public abstract B create(LinkKey key, Link link);
-
-    /**
-     * Adds the given link to our collection, returning the corresponding
-     * bi-link (creating one if needed necessary).
-     *
-     * @param link the link to add to the collection
-     * @return the corresponding bi-link wrapper
-     */
-    public B add(Link link) {
-        LinkKey key = TopoUtils.canonicalLinkKey(checkNotNull(link));
-        B blink = map.get(key);
-        if (blink == null) {
-            // no bi-link yet exists for this link
-            blink = create(key, link);
-            map.put(key, blink);
-        } else {
-            // we have a bi-link for this link.
-            if (!blink.one().equals(link)) {
-                blink.setOther(link);
-            }
-        }
-        return blink;
-    }
-
-    /**
-     * Returns the bi-link instances in the collection.
-     *
-     * @return the bi-links in this map
-     */
-    public Collection<B> biLinks() {
-        return map.values();
-    }
-
-    /**
-     * Returns the number of bi-links in the collection.
-     *
-     * @return number of bi-links
-     */
-    public int size() {
-        return map.size();
-    }
-}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/IntentSelection.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/IntentSelection.java
index ae7eab4..f99ff7c 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/IntentSelection.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/IntentSelection.java
@@ -18,6 +18,7 @@
 package org.onosproject.ui.impl.topo;
 
 import org.onosproject.net.intent.Intent;
+import org.onosproject.ui.topo.NodeSelection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/NodeSelection.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/NodeSelection.java
deleted file mode 100644
index c0597aa..0000000
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/NodeSelection.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 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.ui.impl.topo;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.net.Device;
-import org.onosproject.net.Host;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.host.HostService;
-import org.onosproject.ui.JsonUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.HostId.hostId;
-
-/**
- * Encapsulates a selection of devices and/or hosts from the topology view.
- */
-public class NodeSelection {
-
-    private static final Logger log =
-            LoggerFactory.getLogger(NodeSelection.class);
-
-    private static final String IDS = "ids";
-    private static final String HOVER = "hover";
-
-    private final DeviceService deviceService;
-    private final HostService hostService;
-
-    private final Set<String> ids;
-    private final String hover;
-
-    private final Set<Device> devices = new HashSet<>();
-    private final Set<Host> hosts = new HashSet<>();
-
-    /**
-     * Creates a node selection entity, from the given payload, using the
-     * supplied device and host services.
-     *
-     * @param payload message payload
-     * @param deviceService device service
-     * @param hostService host service
-     */
-    public NodeSelection(ObjectNode payload,
-                         DeviceService deviceService,
-                         HostService hostService) {
-        this.deviceService = deviceService;
-        this.hostService = hostService;
-
-        ids = extractIds(payload);
-        hover = extractHover(payload);
-
-        Set<String> unmatched = findDevices(ids);
-        unmatched = findHosts(unmatched);
-        if (unmatched.size() > 0) {
-            log.debug("Skipping unmatched IDs {}", unmatched);
-        }
-
-        if (!isNullOrEmpty(hover)) {
-            unmatched = new HashSet<>();
-            unmatched.add(hover);
-            unmatched = findDevices(unmatched);
-            unmatched = findHosts(unmatched);
-            if (unmatched.size() > 0) {
-                log.debug("Skipping unmatched HOVER {}", unmatched);
-            }
-        }
-    }
-
-    /**
-     * Returns a view of the selected devices.
-     *
-     * @return selected devices
-     */
-    public Set<Device> devices() {
-        return Collections.unmodifiableSet(devices);
-    }
-
-    /**
-     * Returns a view of the selected hosts.
-     *
-     * @return selected hosts
-     */
-    public Set<Host> hosts() {
-        return Collections.unmodifiableSet(hosts);
-    }
-
-    /**
-     * Returns true if nothing is selected.
-     *
-     * @return true if nothing selected
-     */
-    public boolean none() {
-        return devices().size() == 0 && hosts().size() == 0;
-    }
-
-    @Override
-    public String toString() {
-        return "NodeSelection{" +
-                "ids=" + ids +
-                ", hover='" + hover + '\'' +
-                ", #devices=" + devices.size() +
-                ", #hosts=" + hosts.size() +
-                '}';
-    }
-
-    // == helper methods
-
-    private Set<String> extractIds(ObjectNode payload) {
-        ArrayNode array = (ArrayNode) payload.path(IDS);
-        if (array == null || array.size() == 0) {
-            return Collections.emptySet();
-        }
-
-        Set<String> ids = new HashSet<>();
-        for (JsonNode node : array) {
-            ids.add(node.asText());
-        }
-        return ids;
-    }
-
-    private String extractHover(ObjectNode payload) {
-        return JsonUtils.string(payload, HOVER);
-    }
-
-    private Set<String> findDevices(Set<String> ids) {
-        Set<String> unmatched = new HashSet<>();
-        Device device;
-
-        for (String id : ids) {
-            try {
-                device = deviceService.getDevice(deviceId(id));
-                if (device != null) {
-                    devices.add(device);
-                } else {
-                    log.debug("Device with ID {} not found", id);
-                }
-            } catch (IllegalArgumentException e) {
-                unmatched.add(id);
-            }
-        }
-        return unmatched;
-    }
-
-    private Set<String> findHosts(Set<String> ids) {
-        Set<String> unmatched = new HashSet<>();
-        Host host;
-
-        for (String id : ids) {
-            try {
-                host = hostService.getHost(hostId(id));
-                if (host != null) {
-                    hosts.add(host);
-                } else {
-                    log.debug("Host with ID {} not found", id);
-                }
-            } catch (IllegalArgumentException e) {
-                unmatched.add(id);
-            }
-        }
-        return unmatched;
-    }
-}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoUtils.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoUtils.java
deleted file mode 100644
index d43b376..0000000
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoUtils.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 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.ui.impl.topo;
-
-import org.onosproject.net.Link;
-import org.onosproject.net.LinkKey;
-
-import java.text.DecimalFormat;
-
-import static org.onosproject.net.LinkKey.linkKey;
-
-/**
- * Utility methods for helping out with formatting data for the Topology View
- * in the web client.
- */
-public final class TopoUtils {
-
-    // explicit decision made to not 'javadoc' these self explanatory constants
-    public static final double KILO = 1024;
-    public static final double MEGA = 1024 * KILO;
-    public static final double GIGA = 1024 * MEGA;
-
-    public static final String GBITS_UNIT = "Gb";
-    public static final String MBITS_UNIT = "Mb";
-    public static final String KBITS_UNIT = "Kb";
-    public static final String BITS_UNIT = "b";
-    public static final String GBYTES_UNIT = "GB";
-    public static final String MBYTES_UNIT = "MB";
-    public static final String KBYTES_UNIT = "KB";
-    public static final String BYTES_UNIT = "B";
-
-
-    private static final DecimalFormat DF2 = new DecimalFormat("#,###.##");
-
-    private static final String COMPACT = "%s/%s-%s/%s";
-    private static final String EMPTY = "";
-    private static final String SPACE = " ";
-    private static final String PER_SEC = "ps";
-    private static final String FLOW = "flow";
-    private static final String FLOWS = "flows";
-
-    // non-instantiable
-    private TopoUtils() { }
-
-    /**
-     * Returns a compact identity for the given link, in the form
-     * used to identify links in the Topology View on the client.
-     *
-     * @param link link
-     * @return compact link identity
-     */
-    public static String compactLinkString(Link link) {
-        return String.format(COMPACT, link.src().elementId(), link.src().port(),
-                             link.dst().elementId(), link.dst().port());
-    }
-
-    /**
-     * Produces a canonical link key, that is, one that will match both a link
-     * and its inverse.
-     *
-     * @param link the link
-     * @return canonical key
-     */
-    public static LinkKey canonicalLinkKey(Link link) {
-        String sn = link.src().elementId().toString();
-        String dn = link.dst().elementId().toString();
-        return sn.compareTo(dn) < 0 ?
-                linkKey(link.src(), link.dst()) : linkKey(link.dst(), link.src());
-    }
-
-    /**
-     * Returns human readable count of bytes, to be displayed as a label.
-     *
-     * @param bytes number of bytes
-     * @return formatted byte count
-     */
-    public static String formatBytes(long bytes) {
-        String unit;
-        double value;
-        if (bytes > GIGA) {
-            value = bytes / GIGA;
-            unit = GBYTES_UNIT;
-        } else if (bytes > MEGA) {
-            value = bytes / MEGA;
-            unit = MBYTES_UNIT;
-        } else if (bytes > KILO) {
-            value = bytes / KILO;
-            unit = KBYTES_UNIT;
-        } else {
-            value = bytes;
-            unit = BYTES_UNIT;
-        }
-        return DF2.format(value) + SPACE + unit;
-    }
-
-    /**
-     * Returns human readable bit rate, to be displayed as a label.
-     *
-     * @param bytes bytes per second
-     * @return formatted bits per second
-     */
-    public static String formatBitRate(long bytes) {
-        String unit;
-        double value;
-
-        //Convert to bits
-        long bits = bytes * 8;
-        if (bits > GIGA) {
-            value = bits / GIGA;
-            unit = GBITS_UNIT;
-
-            // NOTE: temporary hack to clip rate at 10.0 Gbps
-            //  Added for the CORD Fabric demo at ONS 2015
-            // TODO: provide a more elegant solution to this issue
-            if (value > 10.0) {
-                value = 10.0;
-            }
-
-        } else if (bits > MEGA) {
-            value = bits / MEGA;
-            unit = MBITS_UNIT;
-        } else if (bits > KILO) {
-            value = bits / KILO;
-            unit = KBITS_UNIT;
-        } else {
-            value = bits;
-            unit = BITS_UNIT;
-        }
-        return DF2.format(value) + SPACE + unit + PER_SEC;
-    }
-
-    /**
-     * Returns human readable flow count, to be displayed as a label.
-     *
-     * @param flows number of flows
-     * @return formatted flow count
-     */
-    public static String formatFlows(long flows) {
-        if (flows < 1) {
-            return EMPTY;
-        }
-        return String.valueOf(flows) + SPACE + (flows > 1 ? FLOWS : FLOW);
-    }
-}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TrafficLink.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TrafficLink.java
index e83f9fc..a0e1662 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TrafficLink.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TrafficLink.java
@@ -20,8 +20,10 @@
 import org.onosproject.net.Link;
 import org.onosproject.net.LinkKey;
 import org.onosproject.net.statistic.Load;
+import org.onosproject.ui.topo.BiLink;
 import org.onosproject.ui.topo.LinkHighlight;
 import org.onosproject.ui.topo.LinkHighlight.Flavor;
+import org.onosproject.ui.topo.TopoUtils;
 
 import static org.onosproject.ui.topo.LinkHighlight.Flavor.NO_HIGHLIGHT;
 import static org.onosproject.ui.topo.LinkHighlight.Flavor.PRIMARY_HIGHLIGHT;
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TrafficLinkMap.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TrafficLinkMap.java
index 59965ad..081964f 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TrafficLinkMap.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TrafficLinkMap.java
@@ -19,6 +19,7 @@
 
 import org.onosproject.net.Link;
 import org.onosproject.net.LinkKey;
+import org.onosproject.ui.topo.BiLinkMap;
 
 /**
  * Collection of {@link TrafficLink}s.