ONOS-1846 Added new class TopologyBatchOperation that can be used to
represent mixed sequence of topology event operations.

Added Kryo serialization unit test for the new class.

Also, added methods equals(), hashCode() and toString() to
classes BatchOperation and BatchOperationEntry.

Change-Id: I8c91499c95a48ba68ca6ff99c0ec613c951dd648
diff --git a/src/main/java/net/onrc/onos/api/batchoperation/BatchOperation.java b/src/main/java/net/onrc/onos/api/batchoperation/BatchOperation.java
index 7ef8c45..6232a86 100644
--- a/src/main/java/net/onrc/onos/api/batchoperation/BatchOperation.java
+++ b/src/main/java/net/onrc/onos/api/batchoperation/BatchOperation.java
@@ -55,4 +55,32 @@
     public BatchOperation<T> addOperation(T entry) {
         return ops.add(entry) ? this : null;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        if (getClass() != o.getClass()) {
+            return false;
+        }
+        BatchOperation<?> other = (BatchOperation<?>) o;
+
+        return this.ops.equals(other.ops);
+    }
+
+    @Override
+    public int hashCode() {
+        return ops.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return ops.toString();
+    }
 }
diff --git a/src/main/java/net/onrc/onos/api/batchoperation/BatchOperationEntry.java b/src/main/java/net/onrc/onos/api/batchoperation/BatchOperationEntry.java
index 9c15d31..928a502 100644
--- a/src/main/java/net/onrc/onos/api/batchoperation/BatchOperationEntry.java
+++ b/src/main/java/net/onrc/onos/api/batchoperation/BatchOperationEntry.java
@@ -1,5 +1,7 @@
 package net.onrc.onos.api.batchoperation;
 
+import com.google.common.base.Objects;
+
 /**
  * A super class for batch operation entry classes.
  * <p>
@@ -47,4 +49,31 @@
     public T getOperator() {
         return operator;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        BatchOperationEntry<?, ?> other = (BatchOperationEntry<?, ?>) o;
+        return (this.operator == other.operator) &&
+            Objects.equal(this.target, other.target);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(operator, target);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this)
+            .add("operator", operator)
+            .add("target", target)
+            .toString();
+    }
 }
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyBatchOperation.java b/src/main/java/net/onrc/onos/core/topology/TopologyBatchOperation.java
new file mode 100644
index 0000000..2292b5b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyBatchOperation.java
@@ -0,0 +1,53 @@
+package net.onrc.onos.core.topology;
+
+import net.onrc.onos.api.batchoperation.BatchOperation;
+import net.onrc.onos.api.batchoperation.BatchOperationEntry;
+
+/**
+ * A list of topology operations.
+ */
+public class TopologyBatchOperation extends
+        BatchOperation<BatchOperationEntry<TopologyBatchOperation.Operator, ?>> {
+    /**
+     * The topology operations' operators.
+     */
+    public enum Operator {
+        /**
+         * Adds a new topology event.
+         */
+        ADD,
+
+        /**
+         * Removes an existing topology event.
+         */
+        REMOVE,
+    }
+
+    /**
+     * Adds an add-TopologyEvent operation.
+     *
+     * @param topologyEvent the Topology Event to be added
+     * @return the TopologyBatchOperation object if succeeded, null otherwise
+     */
+    public TopologyBatchOperation addAddTopologyOperation(
+                                        TopologyEvent topologyEvent) {
+        return (null == super.addOperation(
+                new BatchOperationEntry<Operator, TopologyEvent>(
+                                        Operator.ADD, topologyEvent)))
+                ? null : this;
+    }
+
+    /**
+     * Adds a remove-TopologyEvent operation.
+     *
+     * @param topologyEvent the Topology Event to be removed
+     * @return the TopologyBatchOperation object if succeeded, null otherwise
+     */
+    public TopologyBatchOperation addRemoveTopologyOperation(
+                                        TopologyEvent topologyEvent) {
+        return (null == super.addOperation(
+                new BatchOperationEntry<Operator, TopologyEvent>(
+                                        Operator.REMOVE, topologyEvent)))
+                ? null : this;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java b/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java
index 28a9821..a36d221 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java
@@ -4,6 +4,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 
+import net.onrc.onos.api.batchoperation.BatchOperationTarget;
 import net.onrc.onos.core.util.Dpid;
 import net.onrc.onos.core.util.OnosInstanceId;
 
@@ -18,7 +19,7 @@
  * TODO: This class should become immutable after its internals and usage
  * are finalized.
  */
-public final class TopologyEvent {
+public final class TopologyEvent implements BatchOperationTarget {
     private final MastershipEvent mastershipEvent; // Set for Mastership event
     private final SwitchEvent switchEvent;      // Set for Switch event
     private final PortEvent portEvent;          // Set for Port event
diff --git a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
index 4ab832e..679e7f9 100644
--- a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
+++ b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
@@ -11,6 +11,7 @@
 
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.api.batchoperation.BatchOperationEntry;
 import net.onrc.onos.apps.proxyarp.ArpCacheNotification;
 import net.onrc.onos.apps.proxyarp.ArpReplyNotification;
 import net.onrc.onos.core.hostmanager.Host;
@@ -33,6 +34,7 @@
 import net.onrc.onos.core.topology.MastershipEvent;
 import net.onrc.onos.core.topology.PortEvent;
 import net.onrc.onos.core.topology.SwitchEvent;
+import net.onrc.onos.core.topology.TopologyBatchOperation;
 import net.onrc.onos.core.topology.TopologyElement;
 import net.onrc.onos.core.topology.TopologyEvent;
 import net.onrc.onos.core.util.CallerId;
@@ -213,6 +215,8 @@
         kryo.register(PortEvent.class);
         kryo.register(Role.class);
         kryo.register(SwitchEvent.class);
+        kryo.register(TopologyBatchOperation.class);
+        kryo.register(TopologyBatchOperation.Operator.class);
         kryo.register(TopologyElement.class);
         kryo.register(TopologyEvent.class);
 
@@ -231,6 +235,9 @@
         kryo.register(IntentStateList.class);
         kryo.register(HashMap.class);
 
+        // New intent-related classes
+        kryo.register(BatchOperationEntry.class);
+
         // Host-related classes
         kryo.register(HashSet.class);
         kryo.register(Host.class);