Added new REST API for ONOS to get group stats of specfic group, Added CLI command 'show switch <dpid> group <groupId>' to stats of specified group
diff --git a/cli/cli/desc/version200/policy.py b/cli/cli/desc/version200/policy.py
index 57c29ae..eac0209 100644
--- a/cli/cli/desc/version200/policy.py
+++ b/cli/cli/desc/version200/policy.py
@@ -254,7 +254,7 @@
                                 'proc' : 'create-policy',
                             },
                          ),
-        'completion'   : 'tunnel-id-completion',
+        'completion'   : 'tunnelid-completion',
         'field'        : 'tunnel-id',
         'type'         : 'identifier',
         'syntax-help'  : 'Enter tunnel id',
diff --git a/cli/cli/desc/version200/switch.py b/cli/cli/desc/version200/switch.py
index 7857329..a78b184 100755
--- a/cli/cli/desc/version200/switch.py
+++ b/cli/cli/desc/version200/switch.py
@@ -211,13 +211,6 @@
                         'short-help' : 'Show requested item by querying switch',
                         'doc'        : 'switch|realtime-+',
                     },
-                    #{
-                    #    'field'    : 'detail',
-                    #    'optional' : True,
-                    #    'type'     : 'enum',
-                    #    'values'   : ('details','brief'),
-                    #    'doc'      : 'format|+',
-                    #},
                 ),
                 (
                     {
@@ -261,18 +254,27 @@
                         'format'     : 'realtime_%(realtimestats)s_%(tabletype)s_flow',
                         'doc'      : 'format|+',
                     },
-                  #{
-                  #      'field'    : 'tableflow',
-                  #   'type'     : 'enum',
-                  #      'values'     : ('flow',
-                  #                      ),
-                  #      'action'     : 'display-rest',
-                  #      'url'        : 'realtimestats/%(realtimestats)s/%(tabletype)s/%(tableflow)s/%(dpid)s/',
-                  #      'rest-type'  : 'dict-of-list-of-switch',
-                  #      'format'     : 'realtime_%(realtimestats)s_%(tabletype)s_flow',
-                  #      'short-help' : 'Show requested item by querying switch',
-                  #      'doc'        : 'switch|realtime-+',
-                  #  },
+                ),
+                (
+                    {
+                        'field'      : 'realtimestats',
+                        'type'       : 'enum',
+                        'values'     : 'group',
+                    },
+                    {
+                        'field'    : 'groupId',
+                        #'data'     : {
+                        #              'dpid'     : '$dpid',
+                        #              },
+                        #'type'     : 'groupId',
+                        'completion' : 'group-id-completion',
+                        #'sort'       : ['mplsLabel','priority',],
+                        'action'     : 'display-rest',
+                        'url'        : 'realtimestats/%(realtimestats)s/%(groupId)s/%(dpid)s/',
+                        'rest-type'  : 'dict-of-list-of-switch',
+                        'format'     : 'realtime_group',
+                        'doc'      : 'format|+',
+                    },
                 ),
             )
         }
@@ -1189,3 +1191,23 @@
     },
 }
 """
+
+def group_id_completion(prefix, data, completions):
+    dpid = data.get('dpid')
+    #print dpid
+    query_url = "http://127.0.0.1:8000/rest/v1/realtimestats/group/%s/" %(dpid)
+    result = command.sdnsh.store.rest_simple_request(query_url)
+    entries = json.loads(result)
+    entries = entries[dpid]
+    #print "result", entries
+    for entry in entries:
+        #print entry['groupId']
+        if str(entry['groupId']).startswith(prefix):
+            completions[str(entry['groupId'])+' '] = entry['groupId']
+    return
+
+command.add_completion('group-id-completion', group_id_completion,
+                       {'kwargs': { 'prefix'       : '$text',
+                                    'data'         : '$data',
+                                    'completions'  : '$completions',
+                                    }})
diff --git a/cli/sdncon/rest/views.py b/cli/sdncon/rest/views.py
index 41b0acb..66dc75a 100755
--- a/cli/sdncon/rest/views.py
+++ b/cli/sdncon/rest/views.py
@@ -416,6 +416,21 @@
     return get_sdnplatform_response(url)
 
 @safe_rest_view
+def do_realtimegroupstats(request, groupId, dpid ):
+    """
+    This returns realtime group statistics for specified groupId
+    for a dpid by calling the localhost sdnplatform
+    """
+    #raise RestInvalidMethodException()
+    if request.method != 'GET':
+        raise RestInvalidMethodException()
+    #url = controller_url('core', 'switch', dpid, stattype, 'json')
+    #import error
+    #raise error.ArgumentValidationError('\n\n\n %s' % (groupId))
+    url = "http://localhost:8080/wm/floodlight/core/switch/%s/groupStats/%s/json" % (dpid, groupId)
+    return get_sdnplatform_response(url)
+
+@safe_rest_view
 def do_tablerealtimestats(request, tabletype, dpid):
     """
     This returns realtime statistics per table (flows (only)
diff --git a/cli/sdncon/urls.py b/cli/sdncon/urls.py
index 211f3d0..8478eab 100755
--- a/cli/sdncon/urls.py
+++ b/cli/sdncon/urls.py
@@ -62,6 +62,7 @@
     (r'^rest/v1/realtimestats/counter/(?P<stattype>[A-Za-z0-9_:.\-]+)/?$', 'sdncon.rest.views.do_sdnplatform_realtimestats'),
     (r'^rest/v1/realtimestats/counter/(?P<dpid>[A-Za-z0-9_:.\-]+)/(?P<stattype>[A-Za-z]+)/?$', 'sdncon.rest.views.do_sdnplatform_realtimestats'),
     (r'^rest/v1/realtimestats/table/(?P<tabletype>[A-Za-z]+)/flow/(?P<dpid>[A-Za-z0-9_:./\-]+)/?$', 'sdncon.rest.views.do_tablerealtimestats'),
+    (r'^rest/v1/realtimestats/group/(?P<groupId>[0-9]+)/(?P<dpid>[A-Za-z0-9_:./\-]+)/?$', 'sdncon.rest.views.do_realtimegroupstats'),
     (r'^rest/v1/realtimestats/(?P<stattype>[A-Za-z]+)/(?P<dpid>[A-Za-z0-9_:./\-]+)/?$', 'sdncon.rest.views.do_realtimestats'),
     (r'^rest/v1/controller/stats/(?P<stattype>[A-Za-z]+)/?$', 'sdncon.rest.views.do_controller_stats'),
     (r'^rest/v1/controller/storage/tables/?$', 'sdncon.rest.views.do_controller_storage_table_list'),
diff --git a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
index 8608b20..a6879f8 100644
--- a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
@@ -43,6 +43,8 @@
         router.attach("/switch/{switchId}/role/json", SwitchRoleResource.class);
         router.attach("/switch/all/{statType}/json", AllSwitchStatisticsResource.class);
         router.attach("/switch/{switchId}/{statType}/json", SwitchStatisticsResource.class);
+        //TODO replace {statsType} by groupStats
+        router.attach("/switch/{switchId}/{statType}/{groupId}/json", SwitchStatisticsResource.class);
         router.attach("/switch/{switchId}/table/{tableType}/{statType}/json", SwitchStatisticsResource.class);
         router.attach("/controller/switches/json", ControllerSwitchesResource.class);
         router.attach("/memory/json", ControllerMemoryResource.class);
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
index 56d5355..2334edf 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
@@ -41,6 +41,7 @@
 import org.projectfloodlight.openflow.protocol.OFStatsReply;
 import org.projectfloodlight.openflow.protocol.OFStatsRequest;
 import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.types.OFGroup;
 import org.projectfloodlight.openflow.types.OFPort;
 import org.projectfloodlight.openflow.types.TableId;
 import org.projectfloodlight.openflow.util.HexString;
@@ -138,7 +139,7 @@
             }
             else if (statType == OFStatsType.GROUP){
                 log.debug("Switch Group Stats: req sent for all "
-                        + "ports in switch {}", sw.getStringId());
+                        + "groups in switch {}", sw.getStringId());
                 req = sw.getFactory().buildGroupStatsRequest().setXid
                         (sw.getNextTransactionId()).build();
                 List<OFGroupStatsEntryMod> groupStats = new ArrayList<OFGroupStatsEntryMod>();
@@ -158,7 +159,7 @@
             }
             else if (statType == OFStatsType.GROUP_DESC){
                 log.debug("Switch Group Desc Stats: req sent for all "
-                        + "ports in switch {}", sw.getStringId());
+                        + "groups in switch {}", sw.getStringId());
                 List<OFGroupDescStatsEntryMod> GroupDescStats= new ArrayList<OFGroupDescStatsEntryMod>();
                 req = sw.getFactory().buildGroupDescStatsRequest().setXid
                         (sw.getNextTransactionId()).build();
@@ -211,6 +212,43 @@
     protected Object getSwitchStatistics(String switchId, OFStatsType statType) {
         return getSwitchStatistics(HexString.toLong(switchId), statType);
     }
+    
+    protected Object getSwitchGroupStats(String switchId, OFStatsType statType, Integer groupId) {
+        
+        IFloodlightProviderService floodlightProvider =
+                (IFloodlightProviderService) getContext().getAttributes().
+                get(IFloodlightProviderService.class.getCanonicalName());
+        IOFSwitch sw = floodlightProvider.getSwitches().get(HexString.toLong(switchId));
+        Future<List<OFStatsReply>> future;
+        List<OFStatsReply> values = null;
+        if (sw != null){
+            log.debug("Switch Group Stats: req sent for groupId {} "
+                    + "in switch {}",groupId, sw.getStringId());
+            OFStatsRequest<?> req = null;
+            req = sw.getFactory().buildGroupStatsRequest().setXid
+                    (sw.getNextTransactionId()).setGroup(OFGroup.of(groupId)).build();
+            List<OFGroupStatsEntryMod> groupStats = new ArrayList<OFGroupStatsEntryMod>();
+            try {
+                future = sw.getStatistics(req);
+                values = future.get(10, TimeUnit.SECONDS);
+                if(values.isEmpty()){
+                    log.warn("group with groupId {} not found", groupId);
+                    return null;
+                }
+                for (OFGroupStatsEntry entry : ((OFGroupStatsReply)values.get(0)).getEntries()) {
+                    OFGroupStatsEntryMod entryMod = new OFGroupStatsEntryMod(entry);
+                    groupStats.add(entryMod);
+                }
+                log.debug("Switch Group Stats Entries from switch {} are {}",
+                        sw.getStringId(), groupStats);
+            } catch (Exception e) {
+                log.error("Failure retrieving statistics from switch " + sw, e);
+            }
+            return groupStats;
+            
+        }
+        return null;
+    }
     //TODO: Java doc
     protected List<?> getSwitchStatisticsForTable(long switchId,
             OFStatsType statType, String tableType) {
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
index ce2221e..8976100 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
@@ -42,6 +42,7 @@
 
         String switchId = (String) getRequestAttributes().get("switchId");
         String statType = (String) getRequestAttributes().get("statType");
+        String groupId = (String) getRequestAttributes().get("groupId");
         String tableType = null;
         if(getRequestAttributes().containsKey("tableType")){
             tableType = (String) getRequestAttributes().get("tableType");
@@ -70,7 +71,12 @@
         }else if (statType.equals("groupDesc")) {
             values = getSwitchStatistics(switchId, OFStatsType.GROUP_DESC);
         }else if (statType.equals("groupStats")) {
-            values = getSwitchStatistics(switchId, OFStatsType.GROUP);
+            if (groupId != null){
+                values = getSwitchGroupStats(switchId, OFStatsType.GROUP, (Integer.valueOf(groupId)));
+            }
+            else{
+                values = getSwitchStatistics(switchId, OFStatsType.GROUP);
+            }
         }
 
         result.put(switchId, values);