Updated and refactored the JSON serialization of Topology-related
and "Low Intent" objects:

* Added JSON serialization for topology-related FooEvent objects
  For now, their format matches exactly the corresponding Topology Foo object:
  - DeviceEvent: matches Device
  - SwitchEvent: matches Switch
  - PortEvent: matches Port
  - LinkEvent: matches Link

* Refactored the JSON serialization of existing objects so it
  is more consistent:

============================================
  - Topology Device serialization: "port" is renamed to "portNumber"

  OLD:
{
    "mac": "00:01:02:03:04:05"
    "attachmentPoints": [
        {
            "dpid": "11:22:33:44:55:66:77:88",
            "port": 1
        },
        ...
    ]
}

  NEW:
{
    "mac": "00:01:02:03:04:05"
    "attachmentPoints": [
        {
            "dpid": "11:22:33:44:55:66:77:88",
            "portNumber": 1
        },
        ...
    ]
}
============================================
   - Low Level Intent serialization (LinkEvent used by "path"):
     portNumber is an integer instead of a string

OLD:
[
        ...
        "path": [
            {
                "src": {
                    "portNumber": "2",
                    "dpid": "00:00:00:00:00:00:02:02"
                },
                "dst": {
                    "portNumber": "2",
                    "dpid": "00:00:00:00:00:00:02:01"
                }
            },

NEW:
[
        ...
        "path": [
            {
                "src": {
                    "portNumber": 2,
                    "dpid": "00:00:00:00:00:00:02:02"
                },
                "dst": {
                    "portNumber": 2,
                    "dpid": "00:00:00:00:00:00:02:01"
                }
            },
============================================
   - Topology Link serialization: Format changed to match LinkEvent (and SwitchPort):

OLD:
{
    ...
    "links": [
        {
            "dst-switch": "00:00:00:00:00:00:01:03",
            "src-switch": "00:00:00:00:00:00:01:06",
            "src-port": 3,
            "dst-port": 4
        },

NEW:
{
    ...
    "links": [
        {
            "src": {
                "portNumber": 3,
                "dpid": "00:00:00:00:00:00:01:06"
            },
            "dst": {
                "portNumber": 4,
                "dpid": "00:00:00:00:00:00:01:03"
            }
        },

============================================
    - Topology Port serialization: Renamed "number" to "portNumber"

OLD:
{
    "switches": [
        {
            "state": "ACTIVE",
            "ports": [
                {
                    "state": "ACTIVE",
                    "desc": null,
                    "number": 1,
                    "dpid": "00:00:00:00:00:00:04:0e"
                },

NEW:
{
    "switches": [
        {
            "state": "ACTIVE",
            "ports": [
                {
                    "state": "ACTIVE",
                    "desc": null,
                    "portNumber": 1,
                    "dpid": "00:00:00:00:00:00:04:0e"
                },

============================================
      - SwitchPort serialization (used in number of places referred above):
        portNumber is an integer instead of a string
OLD:
                {
                    "portNumber": "2",
                    "dpid": "00:00:00:00:00:00:02:02"
                }

NEW:
                {
                    "portNumber": 2,
                    "dpid": "00:00:00:00:00:00:02:02"
                }

======================

* Added JSON serialization for TopologyEvents. The format is:

{
    "addedSwitches": [
        {
            "state": "ACTIVE",
            "ports": [
            ],
            "dpid": "00:00:00:00:00:00:02:07"
        },
        ...
    ],
    "removedSwitches": [
        {
            "state": "ACTIVE",
            "ports": [
            ],
            "dpid": "00:00:00:00:00:00:02:08"
        },
        ...
    ],
    "addedPorts": [
        {
            "state": "ACTIVE",
            "desc": null,
            "portNumber": 1,
            "dpid": "00:00:00:00:00:00:02:07"
        },
        ...
    ],
    "removedPorts": [
        {
            "state": "ACTIVE",
            "desc": null,
            "portNumber": 1,
            "dpid": "00:00:00:00:00:00:02:08"
        },
        ...
    ],
    "addedLinks": [
        {
            "src": {
                "portNumber": 10,
                "dpid": "00:00:00:00:00:00:04:01"
            },
            "dst": {
                "portNumber": 2,
                "dpid": "00:00:00:00:00:00:04:0a"
            }
        },
        ...
    ],
    "removedLinks": [
        {
            "src": {
                "portNumber": 5,
                "dpid": "00:00:00:00:00:00:05:01"
            },
            "dst": {
                "portNumber": 6,
                "dpid": "00:00:00:00:00:00:05:0a"
            }
        },
        ...
    ],
    "addedHosts": [
        {
            "mac": "00:01:02:03:04:05"
            "attachmentPoints": [
                {
                    "dpid": "11:22:33:44:55:66:77:88",
                    "port": 1
                },
                ...
            ]
        },
        ...
    ],
    "removedHosts": [
        {
            "mac": "00:01:02:03:08:08"
            "attachmentPoints": [
                {
                    "dpid": "11:22:33:44:55:11:11:11",
                    "port": 1
                },
                ...
            ]
        },
        ...
    ]
}

Change-Id: Ib72be653bc03444b888c0417b3f026966a7df3f3
diff --git a/src/main/java/net/onrc/onos/core/topology/web/serializers/TopologyEventsSerializer.java b/src/main/java/net/onrc/onos/core/topology/web/serializers/TopologyEventsSerializer.java
new file mode 100644
index 0000000..e5f81c0
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/web/serializers/TopologyEventsSerializer.java
@@ -0,0 +1,105 @@
+package net.onrc.onos.core.topology.web.serializers;
+
+import net.onrc.onos.core.topology.DeviceEvent;
+import net.onrc.onos.core.topology.LinkEvent;
+import net.onrc.onos.core.topology.PortEvent;
+import net.onrc.onos.core.topology.SwitchEvent;
+import net.onrc.onos.core.topology.TopologyEvents;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.SerializerProvider;
+import org.codehaus.jackson.map.ser.std.SerializerBase;
+
+import java.io.IOException;
+
+/**
+ * JSON serializer for TopologyEvents objects.  Used by WebSocket
+ * implementation of the topology APIs.
+ */
+public class TopologyEventsSerializer extends SerializerBase<TopologyEvents> {
+
+    /**
+     * Default constructor. Performs basic initialization of the JSON
+     * serializer.
+     */
+    public TopologyEventsSerializer() {
+        super(TopologyEvents.class);
+    }
+
+    /**
+     * Serialize a TopologyEvents object in JSON.  The resulting JSON contains
+     * the added and removed topology objects: switches, links and ports.
+     *
+     * @param topologyEvents the TopologyEvents that is being converted to JSON
+     * @param jsonGenerator generator to place the serialized JSON into
+     * @param serializerProvider unused but required for method override
+     * @throws IOException if the JSON serialization process fails
+     */
+    @Override
+    public void serialize(TopologyEvents topologyEvents,
+                          JsonGenerator jsonGenerator,
+                          SerializerProvider serializerProvider)
+            throws IOException {
+
+        // Start the object
+        jsonGenerator.writeStartObject();
+
+        // Output the added switches array
+        jsonGenerator.writeArrayFieldStart("addedSwitches");
+        for (final SwitchEvent switchEvent : topologyEvents.getAddedSwitchEvents()) {
+            jsonGenerator.writeObject(switchEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // Output the removed switches array
+        jsonGenerator.writeArrayFieldStart("removedSwitches");
+        for (final SwitchEvent switchEvent : topologyEvents.getRemovedSwitchEvents()) {
+            jsonGenerator.writeObject(switchEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // Output the added ports array
+        jsonGenerator.writeArrayFieldStart("addedPorts");
+        for (final PortEvent portEvent : topologyEvents.getAddedPortEvents()) {
+            jsonGenerator.writeObject(portEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // Output the removed ports array
+        jsonGenerator.writeArrayFieldStart("removedPorts");
+        for (final PortEvent portEvent : topologyEvents.getRemovedPortEvents()) {
+            jsonGenerator.writeObject(portEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // Output the added links array
+        jsonGenerator.writeArrayFieldStart("addedLinks");
+        for (final LinkEvent linkEvent : topologyEvents.getAddedLinkEvents()) {
+            jsonGenerator.writeObject(linkEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // Output the removed links array
+        jsonGenerator.writeArrayFieldStart("removedLinks");
+        for (final LinkEvent linkEvent : topologyEvents.getRemovedLinkEvents()) {
+            jsonGenerator.writeObject(linkEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // Output the added hosts array
+        jsonGenerator.writeArrayFieldStart("addedHosts");
+        for (final DeviceEvent hostEvent : topologyEvents.getAddedHostEvents()) {
+            jsonGenerator.writeObject(hostEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // Output the removed hosts array
+        jsonGenerator.writeArrayFieldStart("removedHosts");
+        for (final DeviceEvent hostEvent : topologyEvents.getRemovedHostEvents()) {
+            jsonGenerator.writeObject(hostEvent);
+        }
+        jsonGenerator.writeEndArray();
+
+        // All done
+        jsonGenerator.writeEndObject();
+    }
+}