First shot at Broadcom OFDPA 1.0 pipeline
Requires changes to the group description to accept groupId from callers.

Change-Id: Ic21dfe8ae7c246b7d3a6b00e8e5c986e1dc21fa0
diff --git a/core/api/src/main/java/org/onosproject/core/GroupId.java b/core/api/src/main/java/org/onosproject/core/GroupId.java
index 367e4e3..739fc7f 100644
--- a/core/api/src/main/java/org/onosproject/core/GroupId.java
+++ b/core/api/src/main/java/org/onosproject/core/GroupId.java
@@ -21,11 +21,11 @@
 public interface GroupId {
 
     /**
-     * Returns a group ID as short value.
+     * Returns a group ID as an integer value.
      * The method is not intended for use by application developers.
      * Return data type may change in the future release.
      *
-     * @return a group ID as short value
+     * @return a group ID as integer value
      */
     int id();
 }
diff --git a/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveError.java b/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveError.java
index 192b206..d23af76 100644
--- a/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveError.java
+++ b/core/api/src/main/java/org/onosproject/net/flowobjective/ObjectiveError.java
@@ -36,7 +36,7 @@
     GROUPINSTALLATIONFAILED,
 
     /**
-     * The group was reported as installed but is not missing.
+     * The group was reported as installed but is missing.
      */
     GROUPMISSING,
 
@@ -46,6 +46,11 @@
     DEVICEMISSING,
 
     /**
+     * Incorrect Objective parameters passed in by the caller.
+     */
+    BADPARAMS,
+
+    /**
      * An unknown error occurred.
      */
     UNKNOWN
diff --git a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
index 3ffb2c2..5ea2d2e 100644
--- a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
@@ -32,11 +32,17 @@
     private final GroupKey appCookie;
     private final ApplicationId appId;
     private final DeviceId deviceId;
+    private final Integer givenGroupId;
 
     /**
      * Constructor to be used by north bound applications.
      * NOTE: The caller of this subsystem MUST ensure the appCookie
-     * provided in this API is immutable
+     * provided in this API is immutable.
+     * NOTE: The caller may choose to pass in 'null' for the groupId. This is
+     * the typical case, where the caller allows the group subsystem to choose
+     * the groupId in a globally unique way. If the caller passes in the groupId,
+     * the caller MUST ensure that the id is globally unique (not just unique
+     * per device).
      *
      * @param deviceId device identifier
      * @param type type of the group
@@ -49,11 +55,13 @@
                                    GroupDescription.Type type,
                                    GroupBuckets buckets,
                                    GroupKey appCookie,
+                                   Integer groupId,
                                    ApplicationId appId) {
         this.type = checkNotNull(type);
         this.deviceId = checkNotNull(deviceId);
         this.buckets = checkNotNull(buckets);
         this.appCookie = appCookie;
+        this.givenGroupId = groupId;
         this.appId = appId;
     }
 
@@ -70,6 +78,7 @@
         this.buckets = groupDesc.buckets();
         this.appCookie = groupDesc.appCookie();
         this.appId = groupDesc.appId();
+        this.givenGroupId = groupDesc.givenGroupId();
     }
 
     /**
@@ -85,7 +94,7 @@
     public DefaultGroupDescription(DeviceId deviceId,
                                    GroupDescription.Type type,
                                    GroupBuckets buckets) {
-        this(deviceId, type, buckets, null, null);
+        this(deviceId, type, buckets, null, null, null);
     }
 
     /**
@@ -138,6 +147,17 @@
         return this.buckets;
     }
 
+    /**
+     * Returns groupId passed in by application.
+     *
+     * @return Integer group Id passed in by caller. May be null if caller passed
+     *                 in null during GroupDescription creation.
+     */
+    @Override
+    public Integer givenGroupId() {
+        return this.givenGroupId;
+    }
+
     @Override
     /*
      * The deviceId, type and buckets are used for hash.
@@ -177,6 +197,7 @@
                 .add("type", type)
                 .add("buckets", buckets)
                 .add("appId", appId)
+                .add("givenGroupId", givenGroupId)
                 .toString();
     }
 }
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupDescription.java b/core/api/src/main/java/org/onosproject/net/group/GroupDescription.java
index 74dcb16..4a939bd 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupDescription.java
@@ -75,6 +75,14 @@
     public GroupKey appCookie();
 
     /**
+     * Returns groupId passed in by caller.
+     *
+     * @return Integer group id passed in by caller. May be null if caller
+     *                 passed in null to let groupService determin the group id.
+     */
+    public Integer givenGroupId();
+
+    /**
      * Returns group buckets of a group.
      *
      * @return GroupBuckets immutable list of group bucket
diff --git a/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java b/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
index fa3e987..9a0ae89 100644
--- a/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
@@ -177,6 +177,7 @@
                                                                     Group.Type.SELECT,
                                                                     groupBuckets,
                                                                     key,
+                                                                    null,
                                                                     appId);
         groupService.addGroup(newGroupDesc);
         internalProvider.validate(DID, null);
@@ -397,6 +398,7 @@
                 Group.Type.SELECT,
                 groupBuckets,
                 key,
+                null,
                 appId);
         groupService.addGroup(newGroupDesc);
 
diff --git a/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java b/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
index 5c92ef6..8a31de1 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
@@ -430,8 +430,13 @@
             return;
         }
 
-        // Get a new group identifier
-        GroupId id = new DefaultGroupId(getFreeGroupIdValue(groupDesc.deviceId()));
+        GroupId id = null;
+        if (groupDesc.givenGroupId() == null) {
+            // Get a new group identifier
+            id = new DefaultGroupId(getFreeGroupIdValue(groupDesc.deviceId()));
+        } else {
+            id = new DefaultGroupId(groupDesc.givenGroupId());
+        }
         // Create a group entry object
         StoredGroupEntry group = new DefaultGroup(id, groupDesc);
         // Insert the newly created group entry into key and id maps
@@ -513,6 +518,7 @@
                     oldGroup.type(),
                     updatedBuckets,
                     newCookie,
+                    oldGroup.givenGroupId(),
                     oldGroup.appId());
             StoredGroupEntry newGroup = new DefaultGroup(oldGroup.id(),
                                                          updatedGroupDesc);
@@ -718,6 +724,7 @@
                             group.type(),
                             group.buckets(),
                             group.appCookie(),
+                            group.givenGroupId(),
                             group.appId());
                     storeGroupDescriptionInternal(tmp);
                     getPendingGroupKeyTable().
diff --git a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleGroupStore.java b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleGroupStore.java
index f25a707..5e6c084 100644
--- a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleGroupStore.java
+++ b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleGroupStore.java
@@ -275,8 +275,13 @@
             return;
         }
 
-        // Get a new group identifier
-        GroupId id = new DefaultGroupId(getFreeGroupIdValue(groupDesc.deviceId()));
+        GroupId id = null;
+        if (groupDesc.givenGroupId() == null) {
+            // Get a new group identifier
+            id = new DefaultGroupId(getFreeGroupIdValue(groupDesc.deviceId()));
+        } else {
+            id = new DefaultGroupId(groupDesc.givenGroupId());
+        }
         // Create a group entry object
         StoredGroupEntry group = new DefaultGroup(id, groupDesc);
         // Insert the newly created group entry into concurrent key and id maps
@@ -324,6 +329,7 @@
                                                         oldGroup.type(),
                                                         updatedBuckets,
                                                         newCookie,
+                                                        oldGroup.givenGroupId(),
                                                         oldGroup.appId());
             StoredGroupEntry newGroup = new DefaultGroup(oldGroup.id(),
                                                      updatedGroupDesc);
@@ -494,6 +500,7 @@
                                                                        group.type(),
                                                                        group.buckets(),
                                                                        group.appCookie(),
+                                                                       group.givenGroupId(),
                                                                        group.appId());
                     storeGroupDescriptionInternal(tmp);
                 }
diff --git a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleGroupStoreTest.java b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleGroupStoreTest.java
index 9223996..3cf2af3 100644
--- a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleGroupStoreTest.java
+++ b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleGroupStoreTest.java
@@ -224,6 +224,7 @@
                                                  Group.Type.SELECT,
                                                  groupBuckets,
                                                  key,
+                                                 null,
                                                  appId);
         InternalGroupStoreDelegate checkStoreGroupDelegate =
                 new InternalGroupStoreDelegate(key,
@@ -424,6 +425,7 @@
                 Group.Type.SELECT,
                 groupBuckets,
                 key,
+                null,
                 appId);
         InternalGroupStoreDelegate checkStoreGroupDelegate =
                 new InternalGroupStoreDelegate(key,