IDs for MatchAction objects using block allocation

Modified MatchActionId and MatchActionOperationsId to
use longs as IDs and to use ID block allocation to
create them.

Change-Id: I757b353a94a498f624df345cbc16975714db15b3
diff --git a/src/main/java/net/onrc/onos/core/matchaction/MatchAction.java b/src/main/java/net/onrc/onos/core/matchaction/MatchAction.java
index 24790b8..5f7d9fb 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/MatchAction.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/MatchAction.java
@@ -24,8 +24,23 @@
      * @param match the Match object as match condition on the port
      * @param actions the list of Action objects as actions on the switch
      */
+    public MatchAction(MatchActionId id, SwitchPort port, Match match, List<Action> actions) {
+        this.id = id;
+        this.port = port;
+        this.match = match;
+        this.actions = actions;
+    }
+
+    /**
+     * Constructor. TEMPORARY
+     *
+     * @param id ID for this MatchAction object
+     * @param port switch port to apply changes to
+     * @param match the Match object as match condition on the port
+     * @param actions the list of Action objects as actions on the switch
+     */
     public MatchAction(String id, SwitchPort port, Match match, List<Action> actions) {
-        this.id = new MatchActionId(id);
+        this.id = null;
         this.port = port;
         this.match = match;
         this.actions = actions;
diff --git a/src/main/java/net/onrc/onos/core/matchaction/MatchActionId.java b/src/main/java/net/onrc/onos/core/matchaction/MatchActionId.java
index b520439..3dcb64c 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/MatchActionId.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/MatchActionId.java
@@ -2,36 +2,38 @@
 
 import net.onrc.onos.api.batchoperation.BatchOperationTarget;
 
+import java.util.Objects;
+
 /**
  * A unique identifier for a MatchAction.  Objects of this class are immutable.
  */
 public final class MatchActionId implements BatchOperationTarget {
-    private final String value;
+    private final long value;
 
     /**
      * Creates a new Match Action Identifier based on the given id string.
      *
      * @param id unique id string
      */
-    public MatchActionId(String id) {
+    public MatchActionId(long id) {
         value = id;
     }
 
     @Override
     public String toString() {
-        return value;
+        return Long.toString(value);
     }
 
     @Override
     public int hashCode() {
-        return value.hashCode();
+        return Objects.hashCode(value);
     }
 
     @Override
     public boolean equals(Object obj) {
         if (obj instanceof MatchActionId) {
-            MatchActionId other = (MatchActionId) obj;
-            return (value.equals(other.value));
+            final MatchActionId that = (MatchActionId) obj;
+            return this.value == that.value;
         }
         return false;
     }
diff --git a/src/main/java/net/onrc/onos/core/matchaction/MatchActionIdGenerator.java b/src/main/java/net/onrc/onos/core/matchaction/MatchActionIdGenerator.java
new file mode 100644
index 0000000..4f36d7c
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/matchaction/MatchActionIdGenerator.java
@@ -0,0 +1,10 @@
+package net.onrc.onos.core.matchaction;
+/**
+  * A generator of MatchActionId.
+  */
+public interface MatchActionIdGenerator {
+    /**
+      * Generates a globally unique MatchActionId instance.
+      */
+    MatchActionId getNewId();
+}
diff --git a/src/main/java/net/onrc/onos/core/matchaction/MatchActionIdGeneratorWithIdBlockAllocator.java b/src/main/java/net/onrc/onos/core/matchaction/MatchActionIdGeneratorWithIdBlockAllocator.java
new file mode 100644
index 0000000..2c92ff7
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/matchaction/MatchActionIdGeneratorWithIdBlockAllocator.java
@@ -0,0 +1,37 @@
+package net.onrc.onos.core.matchaction;
+
+import net.onrc.onos.core.util.IdBlock;
+import net.onrc.onos.core.util.IdBlockAllocator;
+import net.onrc.onos.core.util.UnavailableIdException;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Generates a global unique MatchActionIdId.
+ */
+public class MatchActionIdGeneratorWithIdBlockAllocator
+        implements MatchActionIdGenerator {
+
+        private final IdBlockAllocator allocator;
+        private IdBlock idBlock;
+
+        /**
+          * Creates a FlowId generator instance using specified ID block allocator.
+          *
+          * @param allocator the ID block allocator to be used
+          */
+        public MatchActionIdGeneratorWithIdBlockAllocator(IdBlockAllocator allocator) {
+            this.allocator = checkNotNull(allocator);
+            this.idBlock = allocator.allocateUniqueIdBlock();
+        }
+
+        @Override
+        public synchronized MatchActionId getNewId() {
+            try {
+                return new MatchActionId(idBlock.getNextId());
+            } catch (UnavailableIdException e) {
+                idBlock = allocator.allocateUniqueIdBlock();
+                return new MatchActionId(idBlock.getNextId());
+            }
+        }
+}
diff --git a/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperations.java b/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperations.java
index a17d0f2..c865203 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperations.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperations.java
@@ -28,22 +28,11 @@
      *
      * @param newId match action operations identifier for this instance
      */
-    private MatchActionOperations(final MatchActionOperationsId newId) {
+    public MatchActionOperations(final MatchActionOperationsId newId) {
         id = checkNotNull(newId);
     }
 
     /**
-     * Creates a MatchActionOperations object from an id.
-     *
-     * @param newId match action operations identifier to use for the new object
-     * @return Match Action Operations object
-     */
-    public static MatchActionOperations createMatchActionsOperations(
-            final MatchActionOperationsId newId) {
-        return new MatchActionOperations(newId);
-    }
-
-    /**
      * Gets the identifier for the Match Action Operations object.
      *
      * @return identifier for the Opertions object
diff --git a/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsId.java b/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsId.java
index 7c9d1db..e346732 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsId.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsId.java
@@ -1,6 +1,6 @@
 package net.onrc.onos.core.matchaction;
 
-import java.util.UUID;
+import java.util.Objects;
 
 /**
  * Identifier for a MatchActionOperations object.  This is an immutable class
@@ -9,15 +9,13 @@
  */
 public final class MatchActionOperationsId {
 
-    private static final String OPERATIONS_ID_PREFIX = "MatchActionOperationsId-";
-    private final String id;
+    private final long id;
 
     /**
-     * Constructs an Operations identifier and allocates a unique identifier
-     * for it.
+     * Constructs an Operations identifier and from a unique identifier.
      */
-    private MatchActionOperationsId() {
-        id = OPERATIONS_ID_PREFIX + UUID.randomUUID();
+    public MatchActionOperationsId(final long newId) {
+        id = newId;
     }
 
     /**
@@ -25,7 +23,7 @@
      *
      * @return Operations object identifier as a string
      */
-    public String getId() {
+    public long getId() {
         return id;
     }
 
@@ -39,24 +37,13 @@
             return false;
         }
 
-        final MatchActionOperationsId otherMatchActionOperationsId =
-                (MatchActionOperationsId) other;
+        final MatchActionOperationsId that = (MatchActionOperationsId) other;
 
-        return otherMatchActionOperationsId.getId().equals(getId());
+        return this.getId() == that.getId();
     }
 
     @Override
     public int hashCode() {
-        return id.hashCode();
+        return Objects.hashCode(id);
     }
-
-    /**
-     * Creates a new Id for a MatchActionOperation.
-     *
-     * @return new Id for a MatchActionOperation
-     */
-    public static MatchActionOperationsId createNewOperationsId() {
-        return new MatchActionOperationsId();
-    }
-
 }
diff --git a/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGenerator.java b/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGenerator.java
new file mode 100644
index 0000000..3274224
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGenerator.java
@@ -0,0 +1,10 @@
+package net.onrc.onos.core.matchaction;
+/**
+  * A generator of MatchActionId.
+  */
+public interface MatchActionOperationsIdGenerator {
+    /**
+      * Generates a globally unique MatchActionId instance.
+      */
+    MatchActionOperationsId getNewId();
+}
diff --git a/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGeneratorWithIdBlockAllocator.java b/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGeneratorWithIdBlockAllocator.java
new file mode 100644
index 0000000..d1d5240
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGeneratorWithIdBlockAllocator.java
@@ -0,0 +1,37 @@
+package net.onrc.onos.core.matchaction;
+
+import net.onrc.onos.core.util.IdBlock;
+import net.onrc.onos.core.util.IdBlockAllocator;
+import net.onrc.onos.core.util.UnavailableIdException;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Generates a global unique MatchActionIdId.
+ */
+public class MatchActionOperationsIdGeneratorWithIdBlockAllocator
+        implements MatchActionOperationsIdGenerator {
+
+        private final IdBlockAllocator allocator;
+        private IdBlock idBlock;
+
+        /**
+          * Creates a FlowId generator instance using specified ID block allocator.
+          *
+          * @param allocator the ID block allocator to be used
+          */
+        public MatchActionOperationsIdGeneratorWithIdBlockAllocator(IdBlockAllocator allocator) {
+            this.allocator = checkNotNull(allocator);
+            this.idBlock = allocator.allocateUniqueIdBlock();
+        }
+
+        @Override
+        public synchronized MatchActionOperationsId getNewId() {
+            try {
+                return new MatchActionOperationsId(idBlock.getNextId());
+            } catch (UnavailableIdException e) {
+                idBlock = allocator.allocateUniqueIdBlock();
+                return new MatchActionOperationsId(idBlock.getNextId());
+            }
+        }
+}
diff --git a/src/test/java/net/onrc/onos/core/matchaction/MatchActionIdGeneratorTest.java b/src/test/java/net/onrc/onos/core/matchaction/MatchActionIdGeneratorTest.java
new file mode 100644
index 0000000..cb4ed35
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/matchaction/MatchActionIdGeneratorTest.java
@@ -0,0 +1,47 @@
+package net.onrc.onos.core.matchaction;
+
+import net.onrc.onos.core.util.IdBlock;
+import net.onrc.onos.core.util.IdBlockAllocator;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests MatchActionIdGeneratorWithIdBlockAllocator.
+ */
+public class MatchActionIdGeneratorTest {
+    private IdBlockAllocator allocator;
+
+    @Before
+    public void setUp() {
+        allocator = createMock(IdBlockAllocator.class);
+
+    }
+
+    /**
+     * Tests generated MatchActionId sequences using two {@link net.onrc.onos.core.util.IdBlock blocks}.
+     */
+    @Test
+    public void testIds() {
+        expect(allocator.allocateUniqueIdBlock())
+                .andReturn(new IdBlock(0, 3))
+                .andReturn(new IdBlock(4, 3));
+
+        replay(allocator);
+        final MatchActionIdGeneratorWithIdBlockAllocator matchActionIdGenerator =
+            new MatchActionIdGeneratorWithIdBlockAllocator(allocator);
+
+        assertThat(matchActionIdGenerator.getNewId(), is(new MatchActionId(0L)));
+        assertThat(matchActionIdGenerator.getNewId(), is(new MatchActionId(1L)));
+        assertThat(matchActionIdGenerator.getNewId(), is(new MatchActionId(2L)));
+
+        assertThat(matchActionIdGenerator.getNewId(), is(new MatchActionId(4L)));
+        assertThat(matchActionIdGenerator.getNewId(), is(new MatchActionId(5L)));
+        assertThat(matchActionIdGenerator.getNewId(), is(new MatchActionId(6L)));
+    }
+}
diff --git a/src/test/java/net/onrc/onos/core/matchaction/MatchActionModuleTest.java b/src/test/java/net/onrc/onos/core/matchaction/MatchActionModuleTest.java
index 0a4e8d3..37fb579 100644
--- a/src/test/java/net/onrc/onos/core/matchaction/MatchActionModuleTest.java
+++ b/src/test/java/net/onrc/onos/core/matchaction/MatchActionModuleTest.java
@@ -33,19 +33,20 @@
              operationsIteration <= iterations;
              operationsIteration++) {
             final MatchActionOperationsId id =
-                    MatchActionOperationsId.createNewOperationsId();
+                    new MatchActionOperationsId(1L);
             assertThat(id, is(notNullValue()));
             final MatchActionOperations operations =
-                    MatchActionOperations.createMatchActionsOperations(id);
+                    new MatchActionOperations(id);
             assertThat(operations, is(notNullValue()));
 
             for (int entriesIteration = 1;
                  entriesIteration <= iterations;
                  entriesIteration++) {
 
-                final String entryId = "MA" +
-                        Integer.toString(operationsIteration) +
-                        Integer.toString(entriesIteration);
+                final MatchActionId entryId =
+                        new MatchActionId(
+                        (operationsIteration * 10) +
+                        entriesIteration);
                 final MatchAction matchAction =
                         new MatchAction(entryId, null, null, null);
                 final MatchActionOperationEntry entry =
@@ -74,7 +75,7 @@
         //  Make sure that the returned list cannot be modified
         Throwable errorThrown = null;
         try {
-            matchActions.add(new MatchAction("", null, null, null));
+            matchActions.add(new MatchAction(new MatchActionId(1L), null, null, null));
         } catch (UnsupportedOperationException e) {
             errorThrown = e;
         }
@@ -90,9 +91,9 @@
 
         // Create two MatchAction objects using the same ID
         final MatchAction matchAction =
-                new MatchAction("ID", null, null, null);
+                new MatchAction(new MatchActionId(111L), null, null, null);
         final MatchAction duplicateMatchAction =
-                new MatchAction("ID", null, null, null);
+                new MatchAction(new MatchActionId(111L), null, null, null);
 
         // create Operation Entries for the two MatchAction objects
         final MatchActionOperationEntry entry =
@@ -104,10 +105,10 @@
 
         // Create an Operations object to execute the first MatchAction
         final MatchActionOperationsId id =
-                MatchActionOperationsId.createNewOperationsId();
+                new MatchActionOperationsId(11L);
         assertThat(id, is(notNullValue()));
         final MatchActionOperations operations =
-                MatchActionOperations.createMatchActionsOperations(id);
+                new MatchActionOperations(id);
         operations.addOperation(entry);
 
         // Create a module to use to execute the Operations.
@@ -120,10 +121,10 @@
 
         // Now add the duplicate entry.  This should fail.
         final MatchActionOperationsId idForDuplicate =
-                MatchActionOperationsId.createNewOperationsId();
+                new MatchActionOperationsId(22L);
         assertThat(idForDuplicate, is(notNullValue()));
         final MatchActionOperations operationsForDuplicate =
-                MatchActionOperations.createMatchActionsOperations(idForDuplicate);
+                new MatchActionOperations(idForDuplicate);
         operationsForDuplicate.addOperation(duplicateEntry);
 
         final boolean resultForDuplicate =
diff --git a/src/test/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGeneratorTest.java b/src/test/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGeneratorTest.java
new file mode 100644
index 0000000..e95f1df
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/matchaction/MatchActionOperationsIdGeneratorTest.java
@@ -0,0 +1,49 @@
+package net.onrc.onos.core.matchaction;
+
+import net.onrc.onos.core.util.IdBlock;
+import net.onrc.onos.core.util.IdBlockAllocator;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests MatchActionOperationsIdGeneratorWithIdBlockAllocator.
+ */
+public class MatchActionOperationsIdGeneratorTest {
+
+    private IdBlockAllocator allocator;
+
+    @Before
+    public void setUp() {
+        allocator = createMock(IdBlockAllocator.class);
+
+    }
+
+    /**
+     * Tests generated MatchActionOperationsId sequences using two {@link net.onrc.onos.core.util.IdBlock blocks}.
+     */
+    @Test
+    public void testIds() {
+        expect(allocator.allocateUniqueIdBlock())
+                .andReturn(new IdBlock(0, 3))
+                .andReturn(new IdBlock(4, 3));
+
+        replay(allocator);
+        final MatchActionOperationsIdGeneratorWithIdBlockAllocator generator =
+                new MatchActionOperationsIdGeneratorWithIdBlockAllocator(allocator);
+
+        assertThat(generator.getNewId(), is(new MatchActionOperationsId(0L)));
+        assertThat(generator.getNewId(), is(new MatchActionOperationsId(1L)));
+        assertThat(generator.getNewId(), is(new MatchActionOperationsId(2L)));
+
+        assertThat(generator.getNewId(), is(new MatchActionOperationsId(4L)));
+        assertThat(generator.getNewId(), is(new MatchActionOperationsId(5L)));
+        assertThat(generator.getNewId(), is(new MatchActionOperationsId(6L)));
+    }
+}
+
diff --git a/src/test/java/net/onrc/onos/core/matchaction/MatchActionOperationsTest.java b/src/test/java/net/onrc/onos/core/matchaction/MatchActionOperationsTest.java
index fd96de4..b01f1c8 100644
--- a/src/test/java/net/onrc/onos/core/matchaction/MatchActionOperationsTest.java
+++ b/src/test/java/net/onrc/onos/core/matchaction/MatchActionOperationsTest.java
@@ -21,16 +21,16 @@
     @Test
     public void testMatchActionoperationsCreate() {
         final MatchActionOperationsId id1 =
-            MatchActionOperationsId.createNewOperationsId();
+            new MatchActionOperationsId(1L);
         final MatchActionOperations operations1 =
-            MatchActionOperations.createMatchActionsOperations(id1);
+            new MatchActionOperations(id1);
         assertThat(id1, is(notNullValue()));
         assertThat(id1, is(equalTo(operations1.getOperationsId())));
 
         final MatchActionOperationsId id2 =
-            MatchActionOperationsId.createNewOperationsId();
+            new MatchActionOperationsId(2L);
         final MatchActionOperations operations2 =
-            MatchActionOperations.createMatchActionsOperations(id2);
+            new MatchActionOperations(id2);
         assertThat(id2, is(notNullValue()));
         assertThat(id2, is(equalTo(operations2.getOperationsId())));
 
@@ -45,11 +45,11 @@
     @Test
     public void testMatchActionOperationsIdEquals() {
         final MatchActionOperationsId id1 =
-                MatchActionOperationsId.createNewOperationsId();
+                new MatchActionOperationsId(1L);
         final MatchActionOperationsId id2 =
-                MatchActionOperationsId.createNewOperationsId();
+                new MatchActionOperationsId(2L);
         final MatchActionOperationsId id1Copy =
-                MatchActionOperationsId.createNewOperationsId();
+                new MatchActionOperationsId(1L);
 
 
         // Check that null does not match
@@ -73,7 +73,7 @@
     @Test
     public void testMatchActionOperationsIdHashCode() {
         final MatchActionOperationsId id1 =
-                MatchActionOperationsId.createNewOperationsId();
-        assertThat(id1.hashCode(), is(equalTo(id1.getId().hashCode())));
+                new MatchActionOperationsId(22L);
+        assertThat(id1.hashCode(), is(equalTo(22)));
     }
 }
diff --git a/src/test/java/net/onrc/onos/core/matchaction/MatchActionTest.java b/src/test/java/net/onrc/onos/core/matchaction/MatchActionTest.java
index cb32096..2684f19 100644
--- a/src/test/java/net/onrc/onos/core/matchaction/MatchActionTest.java
+++ b/src/test/java/net/onrc/onos/core/matchaction/MatchActionTest.java
@@ -22,7 +22,7 @@
         builder.setDstTcpPort((short) 80);
         List<Action> actions = new LinkedList<Action>();
         actions.add(new ModifyDstMacAction(MACAddress.valueOf("00:01:02:03:04:05")));
-        MatchAction ma = new MatchAction("1", port, builder.build(), actions);
+        MatchAction ma = new MatchAction(new MatchActionId(1L), port, builder.build(), actions);
 
         assertEquals(actions, ma.getActions());
         assertEquals("1", ma.getId().toString());
diff --git a/src/test/java/net/onrc/onos/core/matchaction/TestOperationsCreation.java b/src/test/java/net/onrc/onos/core/matchaction/TestOperationsCreation.java
index fc33f14..2278949 100644
--- a/src/test/java/net/onrc/onos/core/matchaction/TestOperationsCreation.java
+++ b/src/test/java/net/onrc/onos/core/matchaction/TestOperationsCreation.java
@@ -23,12 +23,13 @@
     public void testOperationsCreation() {
         //  Create the MatchActionOperations
         final MatchActionOperationsId operationsId =
-            MatchActionOperationsId.createNewOperationsId();
+            new MatchActionOperationsId(1L);
         final MatchActionOperations operations =
-                MatchActionOperations.createMatchActionsOperations(operationsId);
+                new MatchActionOperations(operationsId);
 
         //  Create one MatchActionEntry and add it to the Operations
-        final String matchActionId1 = "MA1";
+
+        final MatchActionId matchActionId1 = new MatchActionId(1L);
         final MatchAction action1 = new MatchAction(matchActionId1, null, null, null);
 
         final MatchActionOperationEntry entry1 =
@@ -47,7 +48,8 @@
         assertThat(loadedEntry1, is(notNullValue()));
 
         final MatchAction loadedAction1 = loadedEntry1.getTarget();
-        assertThat(loadedAction1.getId().toString(), is(equalTo(matchActionId1)));
+        assertThat(loadedAction1.getId().toString(),
+                   is(equalTo(matchActionId1.toString())));
 
         final MatchActionOperations.Operator loadedOperator1 = loadedEntry1.getOperator();
         assertThat(loadedOperator1, is(equalTo(MatchActionOperations.Operator.ADD)));