Add information about number of routes advertised by FPM peers in FPM CLI

Change-Id: I1fb73e1c98d0cea34d0aa26a62bcd5dcc71199ce
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmInfoService.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmInfoService.java
index 8fe35bb..a0fdf14 100644
--- a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmInfoService.java
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmInfoService.java
@@ -16,7 +16,6 @@
 
 package org.onosproject.routing.fpm;
 
-import java.util.Collection;
 import java.util.Map;
 
 /**
@@ -27,7 +26,7 @@
     /**
      * Returns the FPM peers that are currently connected.
      *
-     * @return a map of FPM peer to connection time.
+     * @return a map of FPM peer with related information
      */
-    Map<FpmPeer, Collection<FpmConnectionInfo>> peers();
+    Map<FpmPeer, FpmPeerInfo> peers();
 }
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmManager.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmManager.java
index cd1ed78..01321c1 100644
--- a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmManager.java
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmManager.java
@@ -16,7 +16,6 @@
 
 package org.onosproject.routing.fpm;
 
-import com.google.common.collect.ImmutableMap;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -62,6 +61,7 @@
 
 import java.net.InetSocketAddress;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -69,6 +69,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 
 import static java.util.concurrent.Executors.newCachedThreadPool;
 import static org.onlab.util.Tools.groupedThreads;
@@ -292,11 +293,17 @@
         }
     }
 
+    private FpmPeerInfo toFpmInfo(FpmPeer peer, Collection<FpmConnectionInfo> connections) {
+        return new FpmPeerInfo(connections,
+                fpmRoutes.getOrDefault(peer, Collections.emptyMap()).size());
+    }
+
     @Override
-    public Map<FpmPeer, Collection<FpmConnectionInfo>> peers() {
-        return ImmutableMap.<FpmPeer, Collection<FpmConnectionInfo>>builder()
-                .putAll(peers.asJavaMap())
-                .build();
+    public Map<FpmPeer, FpmPeerInfo> peers() {
+        return peers.asJavaMap().entrySet().stream()
+                .collect(Collectors.toMap(
+                        e -> e.getKey(),
+                        e -> toFpmInfo(e.getKey(), e.getValue())));
     }
 
     private class InternalFpmListener implements FpmListener {
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmPeerInfo.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmPeerInfo.java
new file mode 100644
index 0000000..465622e
--- /dev/null
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/FpmPeerInfo.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017-present 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.routing.fpm;
+
+import java.util.Collection;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Information about an FPM peer.
+ */
+public class FpmPeerInfo {
+
+    private final Collection<FpmConnectionInfo> connections;
+    private final int routes;
+
+    /**
+     * Class constructor.
+     *
+     * @param connections connection information for the peer
+     * @param routes number of routes the peer has sent to this node
+     */
+    public FpmPeerInfo(Collection<FpmConnectionInfo> connections, int routes) {
+        this.connections = checkNotNull(connections);
+        this.routes = routes;
+    }
+
+    /**
+     * Returns connection information for the peer.
+     *
+     * @return collection of connection information
+     */
+    public Collection<FpmConnectionInfo> connections() {
+        return connections;
+    }
+
+    /**
+     * Returns number of routes sent to this node.
+     *
+     * @return number of routes
+     */
+    public int routes() {
+        return routes;
+    }
+}
diff --git a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/cli/FpmConnectionsList.java b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/cli/FpmConnectionsList.java
index 8516ed2..1daef96 100644
--- a/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/cli/FpmConnectionsList.java
+++ b/apps/routing/fpm/src/main/java/org/onosproject/routing/fpm/cli/FpmConnectionsList.java
@@ -21,10 +21,12 @@
 import org.onlab.util.Tools;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.cluster.ClusterService;
-import org.onosproject.routing.fpm.FpmConnectionInfo;
+import org.onosproject.routing.fpm.FpmPeerInfo;
 import org.onosproject.routing.fpm.FpmInfoService;
+import org.onosproject.routing.fpm.FpmPeer;
 
 import java.util.Comparator;
+import java.util.Map;
 
 /**
  * Displays the current FPM connections.
@@ -33,19 +35,27 @@
         description = "Displays the current FPM connections")
 public class FpmConnectionsList extends AbstractShellCommand {
 
-    private static final String FORMAT = "peer %s:%s connected to %s since %s %s";
+    private static final String FORMAT = "peer %s:%s connected to %s since %s %s (%d routes locally)";
 
     @Override
     protected void execute() {
         FpmInfoService fpmInfo = get(FpmInfoService.class);
+
+        fpmInfo.peers().entrySet().stream()
+                .sorted(Comparator.<Map.Entry<FpmPeer, FpmPeerInfo>, IpAddress>comparing(e -> e.getKey().address())
+                        .thenComparing(e -> e.getKey().port()))
+                .map(Map.Entry::getValue)
+                .forEach(this::print);
+    }
+
+    private void print(FpmPeerInfo info) {
         ClusterService clusterService = get(ClusterService.class);
 
-        fpmInfo.peers().values().stream()
-                .flatMap(v -> v.stream())
-                .sorted(Comparator.<FpmConnectionInfo, IpAddress>comparing(i -> i.peer().address())
-                        .thenComparing(i -> i.peer().port()))
-                .forEach(info -> print(FORMAT, info.peer().address(), info.peer().port(),
-                        info.connectedTo(), Tools.timeAgo(info.connectTime()),
-                        info.connectedTo().equals(clusterService.getLocalNode().id()) ? "*" : ""));
+        info.connections().forEach(cinfo ->
+            print(FORMAT, cinfo.peer().address(), cinfo.peer().port(),
+                    cinfo.connectedTo(), Tools.timeAgo(cinfo.connectTime()),
+                    cinfo.connectedTo().equals(clusterService.getLocalNode().id()) ? "*" : "",
+                    info.routes())
+        );
     }
 }