Fix GroupKey interpretation in REST

Input string from REST should not be converted into byte array directly.
Before: "1" -> ascii 49 -> 0x31
After: "0x01" -> 0x01
GroupKey is a byte array with arbitrary length and represented by hex string

Change-Id: If27101f0e5522212c7e434fab58b66e67e9676d7
diff --git a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupKey.java b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupKey.java
index 10c6ad1..a6d725b 100644
--- a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupKey.java
+++ b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupKey.java
@@ -23,7 +23,6 @@
  * Default implementation of group key interface.
  */
 public class DefaultGroupKey implements GroupKey {
-
     private final byte[] key;
     protected static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
 
@@ -66,7 +65,6 @@
             hexChars[j * 2] = HEX_ARRAY[v >>> 4];
             hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
         }
-        return "GroupKey:0x" + new String(hexChars);
+        return "0x" + new String(hexChars);
     }
-
 }
\ No newline at end of file
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/GroupCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/GroupCodec.java
index 60ef0cf..10ddd4d 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/GroupCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/GroupCodec.java
@@ -18,6 +18,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.util.HexString;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.codec.JsonCodec;
 import org.onosproject.core.ApplicationId;
@@ -118,7 +119,11 @@
         // parse group key (appCookie)
         String groupKeyStr = nullIsIllegal(json.get(APP_COOKIE),
                 APP_COOKIE + MISSING_MEMBER_MESSAGE).asText();
-        GroupKey groupKey = new DefaultGroupKey(groupKeyStr.getBytes());
+        if (!groupKeyStr.startsWith("0x")) {
+            throw new IllegalArgumentException("APP_COOKIE must be a hex string starts with 0x");
+        }
+        GroupKey groupKey = new DefaultGroupKey(HexString.fromHexString(
+                groupKeyStr.split("0x")[1], ""));
 
         // parse device id
         DeviceId deviceId = DeviceId.deviceId(nullIsIllegal(json.get(DEVICE_ID),
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java
index 2a3b7d4..93473a5 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java
@@ -44,6 +44,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.equalTo;
 import static org.onosproject.codec.impl.GroupJsonMatcher.matchesGroup;
 import static org.onosproject.net.NetTestTools.APP_ID;
 
@@ -109,6 +110,11 @@
         assertThat(((Instructions.OutputInstruction) instruction1).port(), is(PortNumber.portNumber(2)));
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void invalidGroupTest() throws IOException {
+        Group group = getGroup("invalid-group.json");
+    }
+
     /**
      * Checks that the data shared by all the resource is correct for a given group.
      *
@@ -118,7 +124,8 @@
         assertThat(group.appId(), is(APP_ID));
         assertThat(group.deviceId().toString(), is("of:0000000000000001"));
         assertThat(group.type().toString(), is("ALL"));
-        assertThat(group.appCookie().key(), is("1".getBytes()));
+        assertThat(group.appCookie().key(),
+                equalTo(new byte[]{(byte) 0x12, (byte) 0x34, (byte) 0xAB, (byte) 0xCD}));
         assertThat(group.id().id(), is(1));
     }
 
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/invalid-group.json b/core/common/src/test/resources/org/onosproject/codec/impl/invalid-group.json
new file mode 100644
index 0000000..c6758cf
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/invalid-group.json
@@ -0,0 +1,18 @@
+{
+  "type": "ALL",
+  "deviceId": "of:0000000000000001",
+  "appCookie": "1234abCD",
+  "groupId": "1",
+  "buckets": [
+    {
+      "treatment": {
+        "instructions": [
+          {
+            "type": "OUTPUT",
+            "port": 2
+          }
+        ]
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/simple-group.json b/core/common/src/test/resources/org/onosproject/codec/impl/simple-group.json
index 675f244..865ae23 100644
--- a/core/common/src/test/resources/org/onosproject/codec/impl/simple-group.json
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/simple-group.json
@@ -1,7 +1,7 @@
 {
   "type": "ALL",
   "deviceId": "of:0000000000000001",
-  "appCookie": "1",
+  "appCookie": "0x1234abCD",
   "groupId": "1",
   "buckets": [
     {
diff --git a/web/api/src/main/resources/definitions/Group.json b/web/api/src/main/resources/definitions/Group.json
index 8a689a3..53d226e 100644
--- a/web/api/src/main/resources/definitions/Group.json
+++ b/web/api/src/main/resources/definitions/Group.json
@@ -67,7 +67,7 @@
     "appCookie": {
       "type": "string",
       "description": "application cookie",
-      "example": "1"
+      "example": "0x1234abcd"
     },
     "buckets": {
       "type": "array",
diff --git a/web/api/src/main/resources/definitions/Groups.json b/web/api/src/main/resources/definitions/Groups.json
index 3f9acca..22f36fb 100644
--- a/web/api/src/main/resources/definitions/Groups.json
+++ b/web/api/src/main/resources/definitions/Groups.json
@@ -67,11 +67,6 @@
             "description": "types of the group",
             "example": "ALL"
           },
-          "deviceId": {
-            "type": "string",
-            "description": "device identifier",
-            "example": "of:0000000000000003"
-          },
           "appId": {
             "type": "string",
             "description": "application identifier",
@@ -80,7 +75,7 @@
           "appCookie": {
             "type": "string",
             "description": "application cookie",
-            "example": "1"
+            "example": "0x1234abcd"
           },
           "buckets": {
             "type": "array",
diff --git a/web/api/src/main/resources/definitions/GroupsPost.json b/web/api/src/main/resources/definitions/GroupsPost.json
index f096201..7ea7b50 100644
--- a/web/api/src/main/resources/definitions/GroupsPost.json
+++ b/web/api/src/main/resources/definitions/GroupsPost.json
@@ -19,7 +19,8 @@
     },
     "appCookie": {
       "type": "string",
-      "example": "1"
+      "description": "application cookie. Arbitrary length byte array represented in hex string",
+      "example": "0x1234abcd"
     },
     "groupId": {
       "type": "string",
diff --git a/web/api/src/test/resources/org/onosproject/rest/resources/post-group.json b/web/api/src/test/resources/org/onosproject/rest/resources/post-group.json
index 675f244..f062bf9 100644
--- a/web/api/src/test/resources/org/onosproject/rest/resources/post-group.json
+++ b/web/api/src/test/resources/org/onosproject/rest/resources/post-group.json
@@ -1,7 +1,7 @@
 {
   "type": "ALL",
   "deviceId": "of:0000000000000001",
-  "appCookie": "1",
+  "appCookie": "0x1",
   "groupId": "1",
   "buckets": [
     {