[ONOS-4530] Allow to specify appId when insert FlowRule through REST

- Augment FlowRuleCodec to encode FlowRule
- Add unit test for encode method of FlowRuleCodec
- Add getFlowByAppId and removeFlowByAppId methods in FlowsWebResource
- Add more unit tests for FlowWebResource
- Add FlowRules.json swagger doc
- Rename Flows.json to FlowEntries.json, correct FlowEntries.json

Change-Id: Ic3ec390c13a349e51ae4208adbc478564b6724ba
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
index 9c5e3fd..11b7eb6 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
@@ -17,6 +17,8 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.packet.EthType;
@@ -29,12 +31,14 @@
 import org.onosproject.codec.JsonCodec;
 import org.onosproject.core.CoreService;
 import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.GridType;
 import org.onosproject.net.Lambda;
 import org.onosproject.net.OchSignal;
 import org.onosproject.net.OchSignalType;
 import org.onosproject.net.OduSignalType;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowRule;
 import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.criteria.Criterion;
 import org.onosproject.net.flow.criteria.EthCriterion;
@@ -75,6 +79,7 @@
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import static org.easymock.EasyMock.anyShort;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
@@ -105,6 +110,7 @@
 
         expect(mockCoreService.registerApplication(FlowRuleCodec.REST_APP_ID))
                 .andReturn(APP_ID).anyTimes();
+        expect(mockCoreService.getAppId(anyShort())).andReturn(APP_ID).anyTimes();
         replay(mockCoreService);
         context.registerService(CoreService.class, mockCoreService);
     }
@@ -166,6 +172,118 @@
     SortedMap<String, Instruction> instructions = new TreeMap<>();
 
     /**
+     * Checks that a simple rule encodes properly.
+     */
+    @Test
+    public void testFlowRuleEncode() {
+
+        DeviceId deviceId = DeviceId.deviceId("of:000000000000000a");
+        FlowRule permFlowRule = DefaultFlowRule.builder()
+                                                    .withCookie(1)
+                                                    .forTable(1)
+                                                    .withPriority(1)
+                                                    .makePermanent()
+                                                    .forDevice(deviceId).build();
+
+        FlowRule tempFlowRule =  DefaultFlowRule.builder()
+                                                .withCookie(1)
+                                                .forTable(1)
+                                                .withPriority(1)
+                                                .makeTemporary(1000)
+                                                .forDevice(deviceId).build();
+
+        ObjectNode permFlowRuleJson = flowRuleCodec.encode(permFlowRule, context);
+        ObjectNode tempFlowRuleJson = flowRuleCodec.encode(tempFlowRule, context);
+
+        assertThat(permFlowRuleJson, FlowRuleJsonMatcher.matchesFlowRule(permFlowRule));
+        assertThat(tempFlowRuleJson, FlowRuleJsonMatcher.matchesFlowRule(tempFlowRule));
+    }
+
+    private static final class FlowRuleJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+        private final FlowRule flowRule;
+
+        private FlowRuleJsonMatcher(FlowRule flowRule) {
+            this.flowRule = flowRule;
+        }
+
+        @Override
+        protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+
+            // check id
+            long jsonId = jsonNode.get("id").asLong();
+            long id = flowRule.id().id();
+            if (jsonId != id) {
+                description.appendText("flow rule id was " + jsonId);
+                return false;
+            }
+
+            // TODO: need to check application ID
+
+            // check tableId
+            int jsonTableId = jsonNode.get("tableId").asInt();
+            int tableId = flowRule.tableId();
+            if (jsonTableId != tableId) {
+                description.appendText("table id was " + jsonId);
+                return false;
+            }
+
+            // check priority
+            int jsonPriority = jsonNode.get("priority").asInt();
+            int priority = flowRule.priority();
+            if (jsonPriority != priority) {
+                description.appendText("priority was " + jsonPriority);
+                return false;
+            }
+
+            // check timeout
+            int jsonTimeout = jsonNode.get("timeout").asInt();
+            int timeout = flowRule.timeout();
+            if (jsonTimeout != timeout) {
+                description.appendText("timeout was " + jsonTimeout);
+                return false;
+            }
+
+            // check isPermanent
+            boolean jsonIsPermanent = jsonNode.get("isPermanent").asBoolean();
+            boolean isPermanent = flowRule.isPermanent();
+            if (jsonIsPermanent != isPermanent) {
+                description.appendText("isPermanent was " + jsonIsPermanent);
+                return false;
+            }
+
+            // check deviceId
+            String jsonDeviceId = jsonNode.get("deviceId").asText();
+            String deviceId = flowRule.deviceId().toString();
+            if (!jsonDeviceId.equals(deviceId)) {
+                description.appendText("deviceId was " + jsonDeviceId);
+                return false;
+            }
+
+            // TODO: need to check traffic treatment
+
+            // TODO: need to check selector
+
+            return true;
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText(flowRule.toString());
+        }
+
+        /**
+         * Factory to allocate a flow rule matcher.
+         *
+         * @param flowRule flow rule object we are looking for
+         * @return matcher
+         */
+        public static FlowRuleJsonMatcher matchesFlowRule(FlowRule flowRule) {
+            return new FlowRuleJsonMatcher(flowRule);
+        }
+    }
+
+    /**
      * Looks up an instruction in the instruction map based on type and subtype.
      *
      * @param type type string