Introduced a builder for flowrules and deprecated the old flowrule constructors.

Change-Id: I4bf6e102c67c2effd0d8b65538fcf3a8a1db69e1
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
index 4b9057f..63baa68 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
@@ -23,6 +23,8 @@
 import java.util.Objects;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 public class DefaultFlowRule implements FlowRule {
 
@@ -34,15 +36,17 @@
 
     private final FlowId id;
 
-    private final short appId;
+    private final Short appId;
 
     private final int timeout;
     private final boolean permanent;
     private final GroupId groupId;
 
     private final Type type;
+    private final Integer tableId;
 
 
+    @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
             TrafficTreatment treatment, int priority, long flowId,
             int timeout, boolean permanent) {
@@ -58,8 +62,10 @@
         this.groupId = new DefaultGroupId((short) ((flowId >>> 32) & 0xFFFF));
         this.id = FlowId.valueOf(flowId);
         this.type = Type.DEFAULT;
+        this.tableId = 0;
     }
 
+    @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
                            TrafficTreatment treatment, int priority, long flowId,
                            int timeout, boolean permanent, Type tableType) {
@@ -75,8 +81,11 @@
         this.groupId = new DefaultGroupId((short) ((flowId >>> 32) & 0xFFFF));
         this.id = FlowId.valueOf(flowId);
         this.type = tableType;
+        this.tableId = 0;
+
     }
 
+    @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
                            TrafficTreatment treatment, int priority, ApplicationId appId,
                            int timeout, boolean permanent) {
@@ -84,6 +93,7 @@
                 timeout, permanent);
     }
 
+    @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
                            TrafficTreatment treatment, int priority, ApplicationId appId,
                            int timeout, boolean permanent, Type type) {
@@ -102,6 +112,7 @@
         this.permanent = permanent;
         this.created = System.currentTimeMillis();
         this.type = type;
+        this.tableId = 0;
 
         /*
          * id consists of the following.
@@ -112,6 +123,7 @@
 
     }
 
+    @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
                            TrafficTreatment treatment, int priority, ApplicationId appId,
                            GroupId groupId, int timeout, boolean permanent) {
@@ -130,6 +142,7 @@
         this.permanent = permanent;
         this.created = System.currentTimeMillis();
         this.type = Type.DEFAULT;
+        this.tableId = 0;
 
         /*
          * id consists of the following.
@@ -151,6 +164,31 @@
         this.permanent = rule.isPermanent();
         this.created = System.currentTimeMillis();
         this.type = rule.type();
+        this.tableId = rule.tableId();
+
+    }
+
+    private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
+                            TrafficTreatment treatment, Integer priority,
+                            FlowId flowId, Boolean permanent, Integer timeout,
+                            Integer tableId) {
+
+        this.deviceId = deviceId;
+        this.selector = selector;
+        this.treatment = treatment;
+        this.priority = priority;
+        this.appId = (short) (flowId.value() >>> 48);
+        this.id = flowId;
+        this.permanent = permanent;
+        this.timeout = timeout;
+        this.tableId = tableId;
+        this.created = System.currentTimeMillis();
+
+
+        //FIXME: fields below will be removed.
+        this.groupId = null;
+        this.type = null;
+
 
     }
 
@@ -197,7 +235,7 @@
      * @see java.lang.Object#equals(java.lang.Object)
      */
     public int hashCode() {
-        return Objects.hash(deviceId, selector, priority, type);
+        return Objects.hash(deviceId, selector, priority, type, tableId);
     }
 
     public int hash() {
@@ -220,6 +258,7 @@
             return Objects.equals(deviceId, that.deviceId) &&
                     Objects.equals(priority, that.priority) &&
                     Objects.equals(selector, that.selector) &&
+                    Objects.equals(tableId, that.tableId) &&
                     Objects.equals(type, that.type);
 
         }
@@ -254,4 +293,107 @@
         return type;
     }
 
+    @Override
+    public int tableId() {
+        return tableId;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    private static final class Builder implements FlowRule.Builder {
+
+        private FlowId flowId;
+        private Integer priority;
+        private DeviceId deviceId;
+        private Integer tableId = 0;
+        private TrafficSelector selector;
+        private TrafficTreatment treatment;
+        private Integer timeout;
+        private Boolean permanent;
+
+        @Override
+        public FlowRule.Builder withCookie(long cookie) {
+            this.flowId = FlowId.valueOf(cookie);
+            return this;
+        }
+
+        @Override
+        public FlowRule.Builder fromApp(ApplicationId appId) {
+            this.flowId = computeFlowId(appId);
+            return this;
+        }
+
+        @Override
+        public FlowRule.Builder withPriority(int priority) {
+            this.priority = priority;
+            return this;
+        }
+
+        @Override
+        public FlowRule.Builder forDevice(DeviceId deviceId) {
+            this.deviceId = deviceId;
+            return this;
+        }
+
+        @Override
+        public FlowRule.Builder forTable(int tableId) {
+            this.tableId = tableId;
+            return this;
+        }
+
+        @Override
+        public FlowRule.Builder withSelector(TrafficSelector selector) {
+            this.selector = selector;
+            return this;
+        }
+
+        @Override
+        public FlowRule.Builder withTreatment(TrafficTreatment treatment) {
+            this.treatment = treatment;
+            return this;
+        }
+
+        @Override
+        public FlowRule.Builder makePermanent() {
+            this.timeout = 0;
+            this.permanent = true;
+            return this;
+        }
+
+        @Override
+        public FlowRule.Builder makeTemporary(int timeout) {
+            this.permanent = false;
+            this.timeout = timeout;
+            return this;
+        }
+
+        @Override
+        public FlowRule build() {
+            checkNotNull(flowId != null, "Either an application" +
+                    " id or a cookie must be supplied");
+            checkNotNull(selector != null, "Traffic selector cannot be null");
+            checkNotNull(timeout != null || permanent != null, "Must either have " +
+                    "a timeout or be permanent");
+            checkNotNull(deviceId != null, "Must refer to a device");
+            checkNotNull(priority != null, "Priority cannot be null");
+            checkArgument(priority < MIN_PRIORITY, "Priority cannot be less than " +
+                    MIN_PRIORITY);
+
+            return new DefaultFlowRule(deviceId, selector, treatment, priority,
+                                       flowId, permanent, timeout, tableId);
+        }
+
+        private FlowId computeFlowId(ApplicationId appId) {
+            return FlowId.valueOf((((long) appId.id()) << 48)
+                                   | (hash() & 0xffffffffL));
+        }
+
+        private int hash() {
+            return Objects.hash(deviceId, selector, treatment, tableId);
+        }
+
+    }
+
 }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
index 0fb7658..a126f18 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.net.flow;
 
+import org.onosproject.core.ApplicationId;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.DeviceId;
 
@@ -32,6 +33,7 @@
      * needs to be put for multi-table support switch.
      * For single table switch, Default is used.
      */
+    @Deprecated
     public static enum Type {
         /* Default type - used in flow rule for single table switch
          * NOTE: this setting should not be used as Table 0 in a multi-table pipeline*/
@@ -59,7 +61,6 @@
         FIRST,
     }
 
-    //TODO: build cookie value
     /**
      * Returns the ID of this flow.
      *
@@ -130,6 +131,105 @@
      *
      * @return flow rule type
      */
+    @Deprecated
     Type type();
 
+    /**
+     * Returns the table id for this rule.
+     *
+     * @return an integer.
+     */
+    int tableId();
+
+    /**
+     * A flowrule builder.
+     */
+    public interface Builder {
+
+        /**
+         * Assigns a cookie value to this flowrule. Mutually exclusive with the
+         * fromApp method. This method is intended to take a cookie value from
+         * the dataplane and not from the application.
+         *
+         * @param cookie a long value
+         * @return this
+         */
+        Builder withCookie(long cookie);
+
+        /**
+         * Assigns the application that built this flow rule to this object.
+         * The short value of the appId will be used as a basis for the
+         * cookie value computation. It is expected that application use this
+         * call to set their application id.
+         *
+         * @param appId an application id
+         * @return this
+         */
+        Builder fromApp(ApplicationId appId);
+
+        /**
+         * Sets the priority for this flow rule.
+         *
+         * @param priority an integer
+         * @return this
+         */
+        Builder withPriority(int priority);
+
+        /**
+         * Sets the deviceId for this flow rule.
+         *
+         * @param deviceId a device id
+         * @return this
+         */
+        Builder forDevice(DeviceId deviceId);
+
+        /**
+         * Sets the table id for this flow rule. Default value is 0.
+         *
+         * @param tableId an integer
+         * @return this
+         */
+        Builder forTable(int tableId);
+
+        /**
+         * Sets the selector (or match field) for this flow rule.
+         *
+         * @param selector a traffic selector
+         * @return this
+         */
+        Builder withSelector(TrafficSelector selector);
+
+        /**
+         * Sets the traffic treatment for this flow rule.
+         *
+         * @param treatment a traffic treatment
+         * @return this
+         */
+        Builder withTreatment(TrafficTreatment treatment);
+
+        /**
+         * Makes this rule permanent on the dataplane.
+         *
+         * @return this
+         */
+        Builder makePermanent();
+
+        /**
+         * Makes this rule temporary and timeout after the specified amount
+         * of time.
+         *
+         * @param timeout an integer
+         * @return this
+         */
+        Builder makeTemporary(int timeout);
+
+        /**
+         * Builds a flow rule object.
+         *
+         * @return a flow rule.
+         */
+        FlowRule build();
+
+    }
+
 }
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
index 0f3170d..7457274 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
@@ -411,6 +411,11 @@
         public Type type() {
             return type;
         }
+
+        @Override
+        public int tableId() {
+            return 0;
+        }
     }
 
     public static class MockIntent extends Intent {
diff --git a/web/api/src/test/java/org/onosproject/rest/FlowsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/FlowsResourceTest.java
index 1de43ba..8e70bd5 100644
--- a/web/api/src/test/java/org/onosproject/rest/FlowsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/FlowsResourceTest.java
@@ -190,6 +190,11 @@
         public Type type() {
             return Type.DEFAULT;
         }
+
+        @Override
+        public int tableId() {
+            return 0;
+        }
     }
 
     /**