[ONOS-3603] Implement REST API for Group query, insert, delete

* Implement decoding feature for GroupBucketCodec and GroupCodec
* Implement GroupsWebResource
* Add unit test for GroupBucketCodec and GroupCodec
* Add unit test for GroupsWebResource
* Add group insertion json example
* Add Swagger doc

Change-Id: Ie58cba2e1af996c7b8652a55d9ef0c27207beafc
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 409f8eb..ffaefd6 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
@@ -15,21 +15,37 @@
  */
 package org.onosproject.codec.impl;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
 import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.CoreService;
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.net.NetTestTools;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.group.DefaultGroup;
 import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.Group;
 import org.onosproject.net.group.GroupBucket;
 import org.onosproject.net.group.GroupBuckets;
 import org.onosproject.net.group.GroupDescription;
 
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.io.InputStream;
 
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
 import static org.onosproject.codec.impl.GroupJsonMatcher.matchesGroup;
+import static org.onosproject.net.NetTestTools.APP_ID;
 
 /**
  * Group codec unit tests.
@@ -37,8 +53,28 @@
 
 public class GroupCodecTest {
 
+    MockCodecContext context;
+    JsonCodec<Group> groupCodec;
+    final CoreService mockCoreService = createMock(CoreService.class);
+
+    /**
+     * Sets up for each test.  Creates a context and fetches the flow rule
+     * codec.
+     */
+    @Before
+    public void setUp() {
+        context = new MockCodecContext();
+        groupCodec = context.codec(Group.class);
+        assertThat(groupCodec, notNullValue());
+
+        expect(mockCoreService.registerApplication(GroupCodec.REST_APP_ID))
+                .andReturn(APP_ID).anyTimes();
+        replay(mockCoreService);
+        context.registerService(CoreService.class, mockCoreService);
+    }
+
     @Test
-    public void codecTest() {
+    public void codecEncodeTest() {
         GroupBucket bucket1 = DefaultGroupBucket
                 .createSelectGroupBucket(DefaultTrafficTreatment.emptyTreatment());
         GroupBucket bucket2 = DefaultGroupBucket
@@ -58,4 +94,48 @@
 
         assertThat(groupJson, matchesGroup(group));
     }
+
+    @Test
+    public void codecDecodeTest() throws IOException {
+        Group group = getGroup("simple-group.json");
+        checkCommonData(group);
+
+        assertThat(group.buckets().buckets().size(), is(1));
+        GroupBucket groupBucket = group.buckets().buckets().get(0);
+        assertThat(groupBucket.type().toString(), is("ALL"));
+        assertThat(groupBucket.treatment().allInstructions().size(), is(1));
+        Instruction instruction1 = groupBucket.treatment().allInstructions().get(0);
+        assertThat(instruction1.type(), is(Instruction.Type.OUTPUT));
+        assertThat(((Instructions.OutputInstruction) instruction1).port(), is(PortNumber.portNumber(2)));
+    }
+
+    /**
+     * Checks that the data shared by all the resource is correct for a given group.
+     *
+     * @param group group to check
+     */
+    private void checkCommonData(Group group) {
+        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.id().id(), is(1));
+    }
+
+    /**
+     * Reads in a group from the given resource and decodes it.
+     *
+     * @param resourceName resource to use to read the JSON for the rule
+     * @return decoded group
+     * @throws IOException if processing the resource fails
+     */
+    private Group getGroup(String resourceName) throws IOException {
+        InputStream jsonStream = GroupCodecTest.class
+                .getResourceAsStream(resourceName);
+        JsonNode json = context.mapper().readTree(jsonStream);
+        assertThat(json, notNullValue());
+        Group group = groupCodec.decode((ObjectNode) json, context);
+        assertThat(group, notNullValue());
+        return group;
+    }
 }