Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/ClusterId.java b/net/api/src/main/java/org/onlab/onos/net/topology/ClusterId.java
new file mode 100644
index 0000000..af8f122
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/ClusterId.java
@@ -0,0 +1,49 @@
+package org.onlab.onos.net.topology;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Representation of the topology cluster identity.
+ */
+public final class ClusterId {
+
+    private final int id;
+
+    // Public construction is prohibit
+    private ClusterId(int id) {
+        this.id = id;
+    }
+
+    /**
+     * Returns the cluster identifier, represented by the specified integer
+     * serial number.
+     *
+     * @param id integer serial number
+     * @return cluster identifier
+     */
+    public static ClusterId clusterId(int id) {
+        return new ClusterId(id);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof ClusterId) {
+            final ClusterId other = (ClusterId) obj;
+            return Objects.equals(this.id, other.id);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this).add("id", id).toString();
+    }
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyCluster.java b/net/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyCluster.java
new file mode 100644
index 0000000..f33dcf7
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyCluster.java
@@ -0,0 +1,81 @@
+package org.onlab.onos.net.topology;
+
+import org.onlab.onos.net.DeviceId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Default implementation of a network topology cluster.
+ */
+public class DefaultTopologyCluster implements TopologyCluster {
+
+    private final ClusterId id;
+    private final int deviceCount;
+    private final int linkCount;
+    private final DeviceId root;
+
+    /**
+     * Creates a new topology cluster descriptor with the specified attributes.
+     *
+     * @param id          cluster id
+     * @param deviceCount number of devices in the cluster
+     * @param linkCount   number of links in the cluster
+     * @param root        cluster root node
+     */
+    public DefaultTopologyCluster(ClusterId id, int deviceCount, int linkCount,
+                                  DeviceId root) {
+        this.id = id;
+        this.deviceCount = deviceCount;
+        this.linkCount = linkCount;
+        this.root = root;
+    }
+
+    @Override
+    public ClusterId id() {
+        return id;
+    }
+
+    @Override
+    public int deviceCount() {
+        return deviceCount;
+    }
+
+    @Override
+    public int linkCount() {
+        return linkCount;
+    }
+
+    @Override
+    public DeviceId root() {
+        return root;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, deviceCount, linkCount, root);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof DefaultTopologyCluster) {
+            final DefaultTopologyCluster other = (DefaultTopologyCluster) obj;
+            return Objects.equals(this.id, other.id) &&
+                    Objects.equals(this.deviceCount, other.deviceCount) &&
+                    Objects.equals(this.linkCount, other.linkCount) &&
+                    Objects.equals(this.root, other.root);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("id", id)
+                .add("deviceCount", deviceCount)
+                .add("linkCount", linkCount)
+                .add("root", root)
+                .toString();
+    }
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/Topology.java b/net/api/src/main/java/org/onlab/onos/net/topology/Topology.java
similarity index 93%
rename from net/api/src/main/java/org/onlab/onos/net/Topology.java
rename to net/api/src/main/java/org/onlab/onos/net/topology/Topology.java
index ed1bfb5..f71a5ec 100644
--- a/net/api/src/main/java/org/onlab/onos/net/Topology.java
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/Topology.java
@@ -1,4 +1,6 @@
-package org.onlab.onos.net;
+package org.onlab.onos.net.topology;
+
+import org.onlab.onos.net.Provided;
 
 /**
  * Represents a network topology computation snapshot.
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyCluster.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyCluster.java
index e58c784..46c9872 100644
--- a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyCluster.java
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyCluster.java
@@ -1,10 +1,38 @@
 package org.onlab.onos.net.topology;
 
+import org.onlab.onos.net.DeviceId;
+
 /**
  * Representation of an SCC (strongly-connected component) in a network topology.
  */
 public interface TopologyCluster {
 
-    // TODO: add stuff in here: id, deviceCount, linkCount
+    /**
+     * Returns the cluster id.
+     *
+     * @return cluster identifier
+     */
+    ClusterId id();
+
+    /**
+     * Returns the number of devices in the cluster.
+     *
+     * @return number of cluster devices
+     */
+    int deviceCount();
+
+    /**
+     * Returns the number of infrastructure links in the cluster.
+     *
+     * @return number of cluster links
+     */
+    int linkCount();
+
+    /**
+     * Returns the device identifier of the cluster root device.
+     *
+     * @return cluster root device identifier
+     */
+    DeviceId root();
 
 }
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyDescription.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyDescription.java
index d9ec746..dd0102d 100644
--- a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyDescription.java
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyDescription.java
@@ -1,8 +1,12 @@
 package org.onlab.onos.net.topology;
 
+import org.onlab.graph.Graph;
+import org.onlab.graph.GraphPathSearch;
 import org.onlab.onos.net.Description;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.Link;
 
-import java.util.Collection;
+import java.util.Set;
 
 /**
  * Describes attribute(s) of a network topology.
@@ -10,21 +14,58 @@
 public interface TopologyDescription extends Description {
 
     /**
-     * A collection of Device, Link, and Host descriptors that describe
-     * the changes tha have occurred in the network topology.
+     * Returns the creation timestamp of the topology description. This is
+     * expressed in system nanos to allow proper sequencing.
      *
-     * @return network element descriptions describing topology change
+     * @return topology description creation timestamp
      */
-    Collection<Description> details();
+    long timestamp();
 
-    // Default topology provider/computor should do the following:
-    // create graph
-    // search graph for SCC clusters (Tarjan)
-    // search graph for all pairs shortest paths based on hop-count
-    //      this means all shortest paths, between all pairs; not just one shortest path
-    // optionally use path results to produce destination-rooted broadcast trees
+    /**
+     * Returns the topology graph.
+     *
+     * @return network graph
+     */
+    Graph<TopoVertex, TopoEdge> graph();
 
-    // provide description with the graph, clusters, paths and trees upwards
+    /**
+     * Returns the results of the path search through the network graph. This
+     * is assumed to contain results of seach fro the given device to all
+     * other devices.
+     *
+     * @param srcDeviceId source device identifier
+     * @return path search result for the given source node
+     */
+    GraphPathSearch.Result pathResults(DeviceId srcDeviceId);
+
+    /**
+     * Returns the set of topology SCC clusters.
+     *
+     * @return set of SCC clusters
+     */
+    Set<TopologyCluster> clusters();
+
+    /**
+     * Returns the set of devices contained by the specified topology cluster.
+     *
+     * @return set of devices that belong to the specified cluster
+     */
+    Set<DeviceId> clusterDevices(TopologyCluster cluster);
+
+    /**
+     * Returns the set of infrastructure links contained by the specified cluster.
+     *
+     * @return set of links that form the given cluster
+     */
+    Set<Link> clusterLinks(TopologyCluster cluster);
+
+    /**
+     * Returns the topology SCC cluster which contains the given device.
+     *
+     * @param deviceId device identifier
+     * @return topology cluster that contains the specified device
+     */
+    TopologyCluster clusterFor(DeviceId deviceId);
 
 }
 
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyEvent.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyEvent.java
index fcbe858..0be5323 100644
--- a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyEvent.java
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyEvent.java
@@ -1,7 +1,6 @@
 package org.onlab.onos.net.topology;
 
 import org.onlab.onos.event.AbstractEvent;
-import org.onlab.onos.net.Topology;
 
 /**
  * Describes network topology event.
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java
index b3d85ad..0e03767 100644
--- a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java
@@ -1,7 +1,10 @@
 package org.onlab.onos.net.topology;
 
+import org.onlab.onos.event.Event;
 import org.onlab.onos.net.provider.ProviderService;
 
+import java.util.List;
+
 /**
  * Means for injecting topology information into the core.
  */
@@ -14,7 +17,9 @@
      * Signals the core that some aspect of the topology has changed.
      *
      * @param topoDescription information about topology
+     * @param reasons         events that triggered topology change
      */
-    void topologyChanged(TopologyDescription topoDescription);
+    void topologyChanged(TopologyDescription topoDescription,
+                         List<Event> reasons);
 
 }
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyService.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyService.java
index a6962a2..36ee666 100644
--- a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyService.java
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyService.java
@@ -4,7 +4,6 @@
 import org.onlab.onos.net.ConnectPoint;
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.Path;
-import org.onlab.onos.net.Topology;
 
 import java.util.Set;
 
@@ -37,8 +36,8 @@
     Graph<TopoVertex, TopoEdge> getGraph(Topology topology);
 
     /**
-     * Returns the set of all shortest paths, in terms of hop-count, between
-     * the specified source and destination devices.
+     * Returns the set of all shortest paths, precomputed in terms of hop-count,
+     * between the specified source and destination devices.
      *
      * @param topology topology descriptor
      * @param src      source device
@@ -71,7 +70,8 @@
 
 
     /**
-     * Indicates whether the specified connection point allows broadcast.
+     * Indicates whether the specified connection point belong to the
+     * broadcast tree.
      *
      * @param topology     topology descriptor
      * @param connectPoint connection point
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/DefaultTopologyDescription.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/DefaultTopologyDescription.java
new file mode 100644
index 0000000..773762a
--- /dev/null
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/DefaultTopologyDescription.java
@@ -0,0 +1,80 @@
+package org.onlab.onos.net.trivial.impl;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import org.onlab.graph.Graph;
+import org.onlab.graph.GraphPathSearch;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.topology.ClusterId;
+import org.onlab.onos.net.topology.TopoEdge;
+import org.onlab.onos.net.topology.TopoVertex;
+import org.onlab.onos.net.topology.TopologyCluster;
+import org.onlab.onos.net.topology.TopologyDescription;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Default implementation of an immutable topology data carrier.
+ */
+public class DefaultTopologyDescription implements TopologyDescription {
+
+    private final long nanos;
+    private final Graph<TopoVertex, TopoEdge> graph;
+    private final Map<DeviceId, GraphPathSearch.Result<TopoVertex, TopoEdge>> results;
+    private final Map<ClusterId, TopologyCluster> clusters;
+    private final Multimap<ClusterId, DeviceId> clusterDevices;
+    private final Multimap<ClusterId, Link> clusterLinks;
+    private final Map<DeviceId, TopologyCluster> deviceClusters;
+
+    public DefaultTopologyDescription(long nanos, Graph<TopoVertex, TopoEdge> graph,
+                                      Map<DeviceId, GraphPathSearch.Result<TopoVertex, TopoEdge>> results,
+                                      Map<ClusterId, TopologyCluster> clusters,
+                                      Multimap<ClusterId, DeviceId> clusterDevices,
+                                      Multimap<ClusterId, Link> clusterLinks,
+                                      Map<DeviceId, TopologyCluster> deviceClusters) {
+        this.nanos = nanos;
+        this.graph = graph;
+        this.results = results;
+        this.clusters = clusters;
+        this.clusterDevices = clusterDevices;
+        this.clusterLinks = clusterLinks;
+        this.deviceClusters = deviceClusters;
+    }
+
+    @Override
+    public long timestamp() {
+        return nanos;
+    }
+
+    @Override
+    public Graph<TopoVertex, TopoEdge> graph() {
+        return graph;
+    }
+
+    @Override
+    public GraphPathSearch.Result<TopoVertex, TopoEdge> pathResults(DeviceId srcDeviceId) {
+        return results.get(srcDeviceId);
+    }
+
+    @Override
+    public Set<TopologyCluster> clusters() {
+        return ImmutableSet.copyOf(clusters.values());
+    }
+
+    @Override
+    public Set<DeviceId> clusterDevices(TopologyCluster cluster) {
+        return null; // clusterDevices.get(cluster.id());
+    }
+
+    @Override
+    public Set<Link> clusterLinks(TopologyCluster cluster) {
+        return null; // clusterLinks.get(cluster.id());
+    }
+
+    @Override
+    public TopologyCluster clusterFor(DeviceId deviceId) {
+        return deviceClusters.get(deviceId);
+    }
+}
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManager.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManager.java
index 29c119d..87a548e 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManager.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManager.java
@@ -150,7 +150,7 @@
     private class InternalDeviceProviderService extends AbstractProviderService<DeviceProvider>
             implements DeviceProviderService {
 
-        public InternalDeviceProviderService(DeviceProvider provider) {
+        InternalDeviceProviderService(DeviceProvider provider) {
             super(provider);
         }
 
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleHostManager.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleHostManager.java
index c9aa71b..17849b1 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleHostManager.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleHostManager.java
@@ -59,7 +59,7 @@
     private class InternalHostProviderService extends AbstractProviderService<HostProvider>
             implements HostProviderService {
 
-        public InternalHostProviderService(HostProvider provider) {
+        InternalHostProviderService(HostProvider provider) {
             super(provider);
         }
 
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleLinkManager.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleLinkManager.java
index cdedae4..88d0663 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleLinkManager.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleLinkManager.java
@@ -149,7 +149,7 @@
     private class InternalLinkProviderService extends AbstractProviderService<LinkProvider>
     implements LinkProviderService {
 
-        public InternalLinkProviderService(LinkProvider provider) {
+        InternalLinkProviderService(LinkProvider provider) {
             super(provider);
         }
 
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleTopologyManager.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleTopologyManager.java
new file mode 100644
index 0000000..1ea0638
--- /dev/null
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleTopologyManager.java
@@ -0,0 +1,153 @@
+package org.onlab.onos.net.trivial.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.graph.Graph;
+import org.onlab.onos.event.AbstractListenerRegistry;
+import org.onlab.onos.event.Event;
+import org.onlab.onos.event.EventDeliveryService;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.Path;
+import org.onlab.onos.net.provider.AbstractProviderRegistry;
+import org.onlab.onos.net.provider.AbstractProviderService;
+import org.onlab.onos.net.topology.LinkWeight;
+import org.onlab.onos.net.topology.TopoEdge;
+import org.onlab.onos.net.topology.TopoVertex;
+import org.onlab.onos.net.topology.Topology;
+import org.onlab.onos.net.topology.TopologyCluster;
+import org.onlab.onos.net.topology.TopologyDescription;
+import org.onlab.onos.net.topology.TopologyEvent;
+import org.onlab.onos.net.topology.TopologyListener;
+import org.onlab.onos.net.topology.TopologyProvider;
+import org.onlab.onos.net.topology.TopologyProviderRegistry;
+import org.onlab.onos.net.topology.TopologyProviderService;
+import org.onlab.onos.net.topology.TopologyService;
+import org.slf4j.Logger;
+
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provides basic implementation of the topology SB &amp; NB APIs.
+ */
+@Component(immediate = true)
+@Service
+public class SimpleTopologyManager
+        extends AbstractProviderRegistry<TopologyProvider, TopologyProviderService>
+        implements TopologyService, TopologyProviderRegistry {
+
+    public static final String TOPOLOGY_NULL = "Topology cannot be null";
+    private static final String DEVICE_ID_NULL = "Device ID cannot be null";
+    public static final String CONNECTION_POINT_NULL = "Connection point cannot be null";
+
+    private final Logger log = getLogger(getClass());
+
+    private final AbstractListenerRegistry<TopologyEvent, TopologyListener>
+            listenerRegistry = new AbstractListenerRegistry<>();
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    private EventDeliveryService eventDispatcher;
+
+
+    @Activate
+    public void activate() {
+        eventDispatcher.addSink(TopologyEvent.class, listenerRegistry);
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        eventDispatcher.removeSink(TopologyEvent.class);
+        log.info("Stopped");
+    }
+
+    @Override
+    protected TopologyProviderService createProviderService(TopologyProvider provider) {
+        return new InternalTopologyProviderService(provider);
+    }
+
+    @Override
+    public Topology currentTopology() {
+        return null;
+    }
+
+    @Override
+    public Set<TopologyCluster> getClusters(Topology topology) {
+        checkNotNull(topology, TOPOLOGY_NULL);
+        return null;
+    }
+
+    @Override
+    public Graph<TopoVertex, TopoEdge> getGraph(Topology topology) {
+        checkNotNull(topology, TOPOLOGY_NULL);
+        return null;
+    }
+
+    @Override
+    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
+        checkNotNull(topology, TOPOLOGY_NULL);
+        checkNotNull(src, DEVICE_ID_NULL);
+        checkNotNull(dst, DEVICE_ID_NULL);
+        return null;
+    }
+
+    @Override
+    public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight) {
+        checkNotNull(topology, TOPOLOGY_NULL);
+        checkNotNull(src, DEVICE_ID_NULL);
+        checkNotNull(dst, DEVICE_ID_NULL);
+        checkNotNull(weight, "Link weight cannot be null");
+        return null;
+    }
+
+    @Override
+    public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) {
+        checkNotNull(topology, TOPOLOGY_NULL);
+        checkNotNull(connectPoint, CONNECTION_POINT_NULL);
+        return false;
+    }
+
+    @Override
+    public boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint) {
+        checkNotNull(topology, TOPOLOGY_NULL);
+        checkNotNull(connectPoint, CONNECTION_POINT_NULL);
+        return false;
+    }
+
+    @Override
+    public void addListener(TopologyListener listener) {
+        listenerRegistry.addListener(listener);
+    }
+
+    @Override
+    public void removeListener(TopologyListener listener) {
+        listenerRegistry.removeListener(listener);
+    }
+
+    // Personalized host provider service issued to the supplied provider.
+    private class InternalTopologyProviderService
+            extends AbstractProviderService<TopologyProvider>
+            implements TopologyProviderService {
+
+        InternalTopologyProviderService(TopologyProvider provider) {
+            super(provider);
+        }
+
+        @Override
+        public void topologyChanged(TopologyDescription topoDescription,
+                                    List<Event> reasons) {
+            checkNotNull(topoDescription, "Topology description cannot be null");
+            log.info("Topology changed due to: {}",
+                     reasons == null ? "initial compute" : reasons);
+        }
+    }
+
+}
diff --git a/src/main/javadoc/overview.html b/src/main/javadoc/overview.html
new file mode 100644
index 0000000..a7a349b
--- /dev/null
+++ b/src/main/javadoc/overview.html
@@ -0,0 +1,9 @@
+<html>
+<body>
+<img src="doc-files/onos-tiers.png" alt="ONOS architecture tiers"><br>
+ONOS architecture is strictly segmented into protocol-agnostic system core and
+protocol-aware providers tiers.
+
+<em>More information to come later...</em>
+
+</body>
\ No newline at end of file