Added CLI command to print summary of the intents:
"intents -s" or "intents --summary"

Change-Id: If6ec11b1425cb2a4c93fdd910808065419af14b5
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java
index e18cc5e..0a6fe41 100644
--- a/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java
+++ b/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java
@@ -45,14 +45,32 @@
          description = "Lists the inventory of intents and their states")
 public class IntentsListCommand extends AbstractShellCommand {
 
-    @Option(name = "-i", aliases = "--installable", description = "Output Installable Intents",
+    @Option(name = "-i", aliases = "--installable",
+            description = "Output Installable Intents",
             required = false, multiValued = false)
     private boolean showInstallable = false;
 
+    @Option(name = "-s", aliases = "--summary",
+            description = "Intents summary",
+            required = false, multiValued = false)
+    private boolean intentsSummary = false;
 
     @Override
     protected void execute() {
         IntentService service = get(IntentService.class);
+
+        if (intentsSummary) {
+            IntentSummaries intentSummaries = new IntentSummaries();
+            intentSummaries.collectIntentSummary(service,
+                                                 service.getIntents());
+            if (outputJson()) {
+                print("%s", intentSummaries.json());
+            } else {
+                intentSummaries.printSummary();
+            }
+            return;
+        }
+
         if (outputJson()) {
             print("%s", json(service, service.getIntents()));
         } else {
@@ -66,6 +84,230 @@
         }
     }
 
+    /**
+     * Internal local class to keep track of all intent summaries.
+     */
+    private class IntentSummaries {
+        private IntentSummary summaryAll;
+        private IntentSummary summaryConnectivity;
+        private IntentSummary summaryPointToPoint;
+        private IntentSummary summaryMultiPointToSinglePoint;
+        private IntentSummary summarySinglePointToMultiPoint;
+        private IntentSummary summaryPath;
+        private IntentSummary summaryLinkCollection;
+        private IntentSummary summaryUnknownType;
+
+        /**
+         * Initializes the internal state.
+         */
+        private void init() {
+            summaryAll = new IntentSummary("All");
+            summaryConnectivity = new IntentSummary("Connectivity");
+            summaryPointToPoint = new IntentSummary("PointToPoint");
+            summaryMultiPointToSinglePoint =
+                new IntentSummary("MultiPointToSinglePoint");
+            summarySinglePointToMultiPoint =
+                new IntentSummary("SinglePointToMultiPoint");
+            summaryPath = new IntentSummary("Path");
+            summaryLinkCollection = new IntentSummary("LinkCollection");
+            summaryUnknownType = new IntentSummary("UnknownType");
+        }
+
+        /**
+         * Collects summary of all intents.
+         *
+         * @param service the Intent Service to use
+         * @param intents the intents
+         */
+        private void collectIntentSummary(IntentService service,
+                                          Iterable<Intent> intents) {
+            init();
+
+            // Collect the summary for each intent type intents
+            for (Intent intent : intents) {
+                IntentState intentState = service.getIntentState(intent.id());
+
+                // Update the summary for all Intents
+                summaryAll.update(intentState);
+
+                if (intent instanceof ConnectivityIntent) {
+                    summaryConnectivity.update(intentState);
+                    // NOTE: ConnectivityIntent is a base type Intent
+                    // continue;
+                }
+                if (intent instanceof PointToPointIntent) {
+                    summaryPointToPoint.update(intentState);
+                    continue;
+                }
+                if (intent instanceof MultiPointToSinglePointIntent) {
+                    summaryMultiPointToSinglePoint.update(intentState);
+                    continue;
+                }
+                if (intent instanceof SinglePointToMultiPointIntent) {
+                    summarySinglePointToMultiPoint.update(intentState);
+                    continue;
+                }
+                if (intent instanceof PathIntent) {
+                    summaryPath.update(intentState);
+                    continue;
+                }
+                if (intent instanceof LinkCollectionIntent) {
+                    summaryLinkCollection.update(intentState);
+                    continue;
+                }
+
+                summaryUnknownType.update(intentState);
+            }
+        }
+
+        /**
+         * Gets JSON representation of all Intents summary.
+         *
+         * @return JSON representation of all Intents summary
+         */
+        ObjectNode json() {
+            ObjectMapper mapper = new ObjectMapper();
+            ObjectNode result = mapper.createObjectNode();
+            result.put("connectivity", summaryConnectivity.json(mapper));
+            result.put("pointToPoint", summaryPointToPoint.json(mapper));
+            result.put("multiPointToSinglePoint",
+                       summaryMultiPointToSinglePoint.json(mapper));
+            result.put("singlePointToMultiPoint",
+                       summarySinglePointToMultiPoint.json(mapper));
+            result.put("path", summaryPath.json(mapper));
+            result.put("linkCollection", summaryLinkCollection.json(mapper));
+            result.put("unknownType", summaryUnknownType.json(mapper));
+            result.put("all", summaryAll.json(mapper));
+            return result;
+        }
+
+        /**
+         * Prints summary of the intents.
+         */
+        private void printSummary() {
+            summaryConnectivity.printState();
+            summaryPointToPoint.printState();
+            summaryMultiPointToSinglePoint.printState();
+            summarySinglePointToMultiPoint.printState();
+            summaryPath.printState();
+            summaryLinkCollection.printState();
+            summaryUnknownType.printState();
+            summaryAll.printState();
+        }
+
+        /**
+         * Internal local class to keep track of a single type Intent summary.
+         */
+        private class IntentSummary {
+            private final String intentType;
+            private int total = 0;
+            private int submitted = 0;
+            private int compiling = 0;
+            private int installing = 0;
+            private int installed = 0;
+            private int recompiling = 0;
+            private int withdrawing = 0;
+            private int withdrawn = 0;
+            private int failed = 0;
+            private int unknownState = 0;
+
+            private static final String FORMAT_SUMMARY_LINE1 =
+                "%-23s    total=        %7d   installed=   %7d";
+            private static final String FORMAT_SUMMARY_LINE2 =
+                "%-23s    withdrawn=    %7d   failed=      %7d";
+            private static final String FORMAT_SUMMARY_LINE3 =
+                "%-23s    submitted=    %7d   compiling=   %7d";
+            private static final String FORMAT_SUMMARY_LINE4 =
+                "%-23s    installing=   %7d   recompiling= %7d";
+            private static final String FORMAT_SUMMARY_LINE5 =
+                "%-23s    withdrawing=  %7d";
+            private static final String FORMAT_SUMMARY_LINE6 =
+                "%-23s    unknownState= %7d";
+
+            /**
+             * Constructor.
+             *
+             * @param intentType the scring describing the Intent type
+             */
+            IntentSummary(String intentType) {
+                this.intentType = intentType;
+            }
+
+            /**
+             * Updates the Intent Summary.
+             *
+             * @param intentState the state of the Intent
+             */
+            void update(IntentState intentState) {
+                total++;
+                switch (intentState) {
+                case SUBMITTED:
+                    submitted++;
+                    break;
+                case COMPILING:
+                    compiling++;
+                    break;
+                case INSTALLING:
+                    installing++;
+                    break;
+                case INSTALLED:
+                    installed++;
+                    break;
+                case RECOMPILING:
+                    recompiling++;
+                    break;
+                case WITHDRAWING:
+                    withdrawing++;
+                    break;
+                case WITHDRAWN:
+                    withdrawn++;
+                    break;
+                case FAILED:
+                    failed++;
+                    break;
+                default:
+                    unknownState++;
+                    break;
+                }
+            }
+
+            /**
+             * Prints the Intent Summary.
+             */
+            void printState() {
+                print(FORMAT_SUMMARY_LINE1, intentType, total, installed);
+                print(FORMAT_SUMMARY_LINE2, intentType, withdrawn, failed);
+                print(FORMAT_SUMMARY_LINE3, intentType, submitted, compiling);
+                print(FORMAT_SUMMARY_LINE4, intentType, installing, recompiling);
+                print(FORMAT_SUMMARY_LINE5, intentType, withdrawing);
+                if (unknownState != 0) {
+                    print(FORMAT_SUMMARY_LINE6, intentType, unknownState);
+                }
+            }
+
+            /**
+             * Gets the JSON representation of the Intent Summary.
+             *
+             * @return the JSON representation of the Intent Summary
+             */
+            JsonNode json(ObjectMapper mapper) {
+                ObjectNode result = mapper.createObjectNode()
+                    .put("total", total)
+                    .put("installed", installed)
+                    .put("failed", failed)
+                    .put("submitted", submitted)
+                    .put("compiling", compiling)
+                    .put("installing", installing)
+                    .put("recompiling", recompiling)
+                    .put("withdrawing", withdrawing)
+                    .put("withdrawn", withdrawn)
+                    .put("unknownState", unknownState);
+
+                return result;
+            }
+        }
+    }
+
     private void printDetails(IntentService service, Intent intent) {
         if (intent.resources() != null && !intent.resources().isEmpty()) {
             print("    resources=%s", intent.resources());
@@ -188,5 +430,4 @@
         }
         return result;
     }
-
 }