[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/main/java/org/onosproject/codec/impl/FlowRuleCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/FlowRuleCodec.java
index e36fe89f..1a41e5c 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/FlowRuleCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/FlowRuleCodec.java
@@ -19,6 +19,7 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.flow.DefaultFlowRule;
@@ -26,6 +27,7 @@
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onlab.util.Tools.nullIsIllegal;
 
 /**
@@ -36,14 +38,46 @@
     private static final String PRIORITY = "priority";
     private static final String TIMEOUT = "timeout";
     private static final String IS_PERMANENT = "isPermanent";
+    private static final String APP_ID = "appId";
     private static final String TABLE_ID = "tableId";
     private static final String DEVICE_ID = "deviceId";
     private static final String TREATMENT = "treatment";
     private static final String SELECTOR = "selector";
     private static final String MISSING_MEMBER_MESSAGE =
-            " member is required in FlowRule";
+                                " member is required in FlowRule";
     public static final String REST_APP_ID = "org.onosproject.rest";
 
+    @Override
+    public ObjectNode encode(FlowRule flowRule, CodecContext context) {
+        checkNotNull(flowRule, "Flow rule cannot be null");
+
+        CoreService service = context.getService(CoreService.class);
+        ApplicationId appId = service.getAppId(flowRule.appId());
+        String strAppId = (appId == null) ? "<none>" : appId.name();
+
+        final ObjectNode result = context.mapper().createObjectNode()
+                .put("id", Long.toString(flowRule.id().value()))
+                .put("tableId", flowRule.tableId())
+                .put("appId", strAppId)
+                .put("priority", flowRule.priority())
+                .put("timeout", flowRule.timeout())
+                .put("isPermanent", flowRule.isPermanent())
+                .put("deviceId", flowRule.deviceId().toString());
+
+        if (flowRule.treatment() != null) {
+            final JsonCodec<TrafficTreatment> treatmentCodec =
+                    context.codec(TrafficTreatment.class);
+            result.set("treatment", treatmentCodec.encode(flowRule.treatment(), context));
+        }
+
+        if (flowRule.selector() != null) {
+            final JsonCodec<TrafficSelector> selectorCodec =
+                    context.codec(TrafficSelector.class);
+            result.set("selector", selectorCodec.encode(flowRule.selector(), context));
+        }
+
+        return result;
+    }
 
     @Override
     public FlowRule decode(ObjectNode json, CodecContext context) {
@@ -54,8 +88,9 @@
         FlowRule.Builder resultBuilder = new DefaultFlowRule.Builder();
 
         CoreService coreService = context.getService(CoreService.class);
-        resultBuilder.fromApp(coreService
-                .registerApplication(REST_APP_ID));
+        JsonNode appIdJson = json.get(APP_ID);
+        String appId = appIdJson != null ? appIdJson.asText() : REST_APP_ID;
+        resultBuilder.fromApp(coreService.registerApplication(appId));
 
         int priority = nullIsIllegal(json.get(PRIORITY),
                 PRIORITY + MISSING_MEMBER_MESSAGE).asInt();