Work toward ONOS-1451: Separate Event Key space per instance

Misc changes and cleanup (Step 3):

* Enabled the usage of ONOS Instance ID inside class TopologyEvent
  - Added the ONOS Instance ID as part of the TopologyEvent key
  - Use the ONOS Instance ID inside method toString() and equals()
  - Also, added new method TopologyEvent.getIDasByteBuffer()

* Added support for Mastership Events inside class TopologyEvents,
  including the JSON output.
  NOTE: For now the JSON output for the Topology object itself doesn't
  contain the corresponding Mastership info. The need for
  adding such info is TBD.

* Added new class TopologyEventFilter that will perform the filtering
  if incoming events. For now the internal logic of this filter is empty.

* Reordered some of the MastershipEvent-related code right before the
  SwitchEvent-related code so it is more consistent.

Change-Id: I940c4686b776f5136a10c25bc49278b69c548fc5
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 df38b5e..4ea9e31 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyEvent.java
@@ -1,5 +1,7 @@
 package net.onrc.onos.core.topology;
 
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 
 import net.onrc.onos.core.util.OnosInstanceId;
@@ -10,17 +12,17 @@
  * Self-contained Topology event Object
  * <p/>
  * TODO: For now the topology event contains one of the following events:
- * Switch, Port, Link, Host, Switch Mastership. In the future it will contain
+ * Switch Mastership, Switch, Port, Link, Host. In the future it will contain
  * multiple events in a single transaction.
  * TODO: This class should become immutable after its internals and usage
  * are finalized.
  */
 public final class TopologyEvent {
+    private final MastershipEvent mastershipEvent; // Set for Mastership event
     private final SwitchEvent switchEvent;      // Set for Switch event
     private final PortEvent portEvent;          // Set for Port event
     private final LinkEvent linkEvent;          // Set for Link event
     private final HostEvent hostEvent;          // Set for Host event
-    private final MastershipEvent mastershipEvent; // Set for Mastership event
     private final OnosInstanceId onosInstanceId;   // The ONOS Instance ID
 
     /**
@@ -28,75 +30,15 @@
      */
     @Deprecated
     protected TopologyEvent() {
+        mastershipEvent = null;
         switchEvent = null;
         portEvent = null;
         linkEvent = null;
         hostEvent = null;
-        mastershipEvent = null;
         onosInstanceId = null;
     }
 
     /**
-     * Constructor for given Switch event.
-     *
-     * @param switchEvent the Switch event to use.
-     * @param onosInstanceId the ONOS Instance ID that originates the event.
-     */
-    TopologyEvent(SwitchEvent switchEvent, OnosInstanceId onosInstanceId) {
-        this.switchEvent = checkNotNull(switchEvent);
-        this.portEvent = null;
-        this.linkEvent = null;
-        this.hostEvent = null;
-        this.mastershipEvent = null;
-        this.onosInstanceId = checkNotNull(onosInstanceId);
-    }
-
-    /**
-     * Constructor for given Port event.
-     *
-     * @param portEvent the Port event to use.
-     * @param onosInstanceId the ONOS Instance ID that originates the event.
-     */
-    TopologyEvent(PortEvent portEvent, OnosInstanceId onosInstanceId) {
-        this.switchEvent = null;
-        this.portEvent = checkNotNull(portEvent);
-        this.linkEvent = null;
-        this.hostEvent = null;
-        this.mastershipEvent = null;
-        this.onosInstanceId = checkNotNull(onosInstanceId);
-    }
-
-    /**
-     * Constructor for given Link event.
-     *
-     * @param linkEvent the Link event to use.
-     * @param onosInstanceId the ONOS Instance ID that originates the event.
-     */
-    TopologyEvent(LinkEvent linkEvent, OnosInstanceId onosInstanceId) {
-        this.switchEvent = null;
-        this.portEvent = null;
-        this.linkEvent = checkNotNull(linkEvent);
-        this.hostEvent = null;
-        this.mastershipEvent = null;
-        this.onosInstanceId = checkNotNull(onosInstanceId);
-    }
-
-    /**
-     * Constructor for given Host event.
-     *
-     * @param hostEvent the Host event to use.
-     * @param onosInstanceId the ONOS Instance ID that originates the event.
-     */
-    TopologyEvent(HostEvent hostEvent, OnosInstanceId onosInstanceId) {
-        this.switchEvent = null;
-        this.portEvent = null;
-        this.linkEvent = null;
-        this.hostEvent = checkNotNull(hostEvent);
-        this.mastershipEvent = null;
-        this.onosInstanceId = checkNotNull(onosInstanceId);
-    }
-
-    /**
      * Constructor for given Switch Mastership event.
      *
      * @param mastershipEvent the Switch Mastership event to use.
@@ -104,15 +46,84 @@
      */
     TopologyEvent(MastershipEvent mastershipEvent,
                   OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = checkNotNull(mastershipEvent);
         this.switchEvent = null;
         this.portEvent = null;
         this.linkEvent = null;
         this.hostEvent = null;
-        this.mastershipEvent = checkNotNull(mastershipEvent);
         this.onosInstanceId = checkNotNull(onosInstanceId);
     }
 
     /**
+     * Constructor for given Switch event.
+     *
+     * @param switchEvent the Switch event to use.
+     * @param onosInstanceId the ONOS Instance ID that originates the event.
+     */
+    TopologyEvent(SwitchEvent switchEvent, OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = null;
+        this.switchEvent = checkNotNull(switchEvent);
+        this.portEvent = null;
+        this.linkEvent = null;
+        this.hostEvent = null;
+        this.onosInstanceId = checkNotNull(onosInstanceId);
+    }
+
+    /**
+     * Constructor for given Port event.
+     *
+     * @param portEvent the Port event to use.
+     * @param onosInstanceId the ONOS Instance ID that originates the event.
+     */
+    TopologyEvent(PortEvent portEvent, OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = null;
+        this.switchEvent = null;
+        this.portEvent = checkNotNull(portEvent);
+        this.linkEvent = null;
+        this.hostEvent = null;
+        this.onosInstanceId = checkNotNull(onosInstanceId);
+    }
+
+    /**
+     * Constructor for given Link event.
+     *
+     * @param linkEvent the Link event to use.
+     * @param onosInstanceId the ONOS Instance ID that originates the event.
+     */
+    TopologyEvent(LinkEvent linkEvent, OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = null;
+        this.switchEvent = null;
+        this.portEvent = null;
+        this.linkEvent = checkNotNull(linkEvent);
+        this.hostEvent = null;
+        this.onosInstanceId = checkNotNull(onosInstanceId);
+    }
+
+    /**
+     * Constructor for given Host event.
+     *
+     * @param hostEvent the Host event to use.
+     * @param onosInstanceId the ONOS Instance ID that originates the event.
+     */
+    TopologyEvent(HostEvent hostEvent, OnosInstanceId onosInstanceId) {
+        this.mastershipEvent = null;
+        this.switchEvent = null;
+        this.portEvent = null;
+        this.linkEvent = null;
+        this.hostEvent = checkNotNull(hostEvent);
+        this.onosInstanceId = checkNotNull(onosInstanceId);
+    }
+
+    /**
+     * Gets the Mastership event.
+     *
+     * @return the Mastership event.
+     */
+    public MastershipEvent getMastershipEvent() {
+        return mastershipEvent;
+    }
+
+    /**
      * Gets the Switch event.
      *
      * @return the Switch event.
@@ -149,16 +160,16 @@
     }
 
     /**
-     * Gets the Mastership event.
+     * Gets the ONOS Instance ID.
      *
-     * @return the Mastership event.
+     * @return the ONOS Instance ID.
      */
-    public MastershipEvent getMastershipEvent() {
-        return mastershipEvent;
+    public OnosInstanceId getOnosInstanceId() {
+        return onosInstanceId;
     }
 
     /**
-     * Check if all events contained are equal.
+     * Checks if all events contained are equal.
      *
      * @param obj TopologyEvent to compare against
      */
@@ -177,69 +188,118 @@
         }
 
         TopologyEvent other = (TopologyEvent) obj;
-        // TODO: For now the onosInstanceId is not used
-        return Objects.equals(switchEvent, other.switchEvent) &&
-                Objects.equals(portEvent, other.portEvent) &&
-                Objects.equals(linkEvent, other.linkEvent) &&
-                Objects.equals(hostEvent, other.hostEvent) &&
-                Objects.equals(mastershipEvent, other.mastershipEvent);
+        return Objects.equals(mastershipEvent, other.mastershipEvent) &&
+            Objects.equals(switchEvent, other.switchEvent) &&
+            Objects.equals(portEvent, other.portEvent) &&
+            Objects.equals(linkEvent, other.linkEvent) &&
+            Objects.equals(hostEvent, other.hostEvent) &&
+            Objects.equals(onosInstanceId, other.onosInstanceId);
     }
 
     @Override
     public int hashCode() {
-        // TODO: For now the onosInstanceId is not used
-        return Objects.hash(switchEvent, portEvent, linkEvent, hostEvent,
-                            mastershipEvent);
+        return Objects.hash(mastershipEvent, switchEvent, portEvent,
+                            linkEvent, hostEvent, onosInstanceId);
     }
 
     /**
-     * Get the string representation of the event.
+     * Gets the string representation of the event.
      *
      * @return the string representation of the event.
      */
     @Override
     public String toString() {
-        // TODO: For now the onosInstanceId is not used
-        if (switchEvent != null) {
-            return switchEvent.toString();
-        }
-        if (portEvent != null) {
-            return portEvent.toString();
-        }
-        if (linkEvent != null) {
-            return linkEvent.toString();
-        }
-        if (hostEvent != null) {
-            return hostEvent.toString();
-        }
-        if (mastershipEvent != null) {
-            return mastershipEvent.toString();
-        }
-        return "[Empty TopologyEvent]";
+        String eventStr = null;
+
+        //
+        // Get the Event string
+        //
+        do {
+            if (mastershipEvent != null) {
+                eventStr = mastershipEvent.toString();
+                break;
+            }
+            if (switchEvent != null) {
+                eventStr = switchEvent.toString();
+                break;
+            }
+            if (portEvent != null) {
+                eventStr = portEvent.toString();
+                break;
+            }
+            if (linkEvent != null) {
+                eventStr = linkEvent.toString();
+                break;
+            }
+            if (hostEvent != null) {
+                eventStr = hostEvent.toString();
+                break;
+            }
+            // No event found
+            return "[Empty TopologyEvent]";
+        } while (false);
+
+        return "[TopologyEvent " + eventStr + " from " +
+            onosInstanceId.toString() + "]";
     }
 
     /**
-     * Get the Topology event ID.
+     * Gets the Topology event ID as a byte array.
      *
-     * @return the Topology event ID.
+     * @return the Topology event ID as a byte array.
      */
     public byte[] getID() {
-        // TODO: For now the onosInstanceId is not used
-        if (switchEvent != null) {
-            return switchEvent.getID();
-        }
-        if (portEvent != null) {
-            return portEvent.getID();
-        }
-        if (linkEvent != null) {
-            return linkEvent.getID();
-        }
-        if (hostEvent != null) {
-            return hostEvent.getID();
-        }
-        if (mastershipEvent != null) {
-            return mastershipEvent.getID();
-        }
-        throw new IllegalStateException("Invalid TopologyEvent ID");
+        return getIDasByteBuffer().array();
+    }
+
+    /**
+     * Gets the Topology event ID as a ByteBuffer.
+     *
+     * @return the Topology event ID as a ByteBuffer.
+     */
+    public ByteBuffer getIDasByteBuffer() {
+        ByteBuffer eventId = null;
+
+        //
+        // Get the Event ID
+        //
+        do {
+            if (mastershipEvent != null) {
+                eventId = mastershipEvent.getIDasByteBuffer();
+                break;
+            }
+            if (switchEvent != null) {
+                eventId = switchEvent.getIDasByteBuffer();
+                break;
+            }
+            if (portEvent != null) {
+                eventId = portEvent.getIDasByteBuffer();
+                break;
+            }
+            if (linkEvent != null) {
+                eventId = linkEvent.getIDasByteBuffer();
+                break;
+            }
+            if (hostEvent != null) {
+                eventId = hostEvent.getIDasByteBuffer();
+                break;
+            }
+            // No event found
+            throw new IllegalStateException("Invalid TopologyEvent ID");
+        } while (false);
+
+        //
+        // Prepare the ONOS Instance ID. The '@' separator is needed to avoid
+        // potential key collisions.
+        //
+        byte[] onosId = ("@" + onosInstanceId.toString()).getBytes(StandardCharsets.UTF_8);
+
+        // Concatenate the IDs
+        ByteBuffer buf =
+            ByteBuffer.allocate(eventId.capacity() + onosId.length);
+        buf.put(eventId);
+        buf.put(onosId);
+        buf.flip();
+        return buf;
     }
 }