diff --git a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
index 7c86fc3..3ff46b2 100755
--- a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
+++ b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
@@ -19,19 +19,10 @@
 import net.onrc.onos.datagrid.web.DatagridWebRoutable;
 import net.onrc.onos.ofcontroller.devicemanager.IDeviceEventHandler;
 import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
-import net.onrc.onos.ofcontroller.flowmanager.IFlowEventHandlerService;
 import net.onrc.onos.ofcontroller.proxyarp.ArpReplyNotification;
 import net.onrc.onos.ofcontroller.proxyarp.IArpReplyEventHandler;
 import net.onrc.onos.ofcontroller.proxyarp.IPacketOutEventHandler;
 import net.onrc.onos.ofcontroller.proxyarp.PacketOutNotification;
-import net.onrc.onos.ofcontroller.topology.TopologyElement;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntryId;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.Pair;
-import net.onrc.onos.ofcontroller.util.PerformanceMonitor;
 import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
 
 import org.slf4j.Logger;
@@ -67,40 +58,9 @@
     private Config hazelcastConfig;
 
     private final KryoFactory kryoFactory = new KryoFactory();
-    private IFlowEventHandlerService flowEventHandlerService;
 
     private final Map<String, IEventChannel<?, ?>> eventChannels = new HashMap<>();
 
-    // State related to the Flow map
-    private static final String MAP_FLOW_NAME = "mapFlow";
-    private IMap<Long, byte[]> mapFlow;
-    private MapFlowListener mapFlowListener;
-    private String mapFlowListenerId;
-
-    // State related to the Flow Entry map
-    private static final String MAP_FLOW_ENTRY_NAME = "mapFlowEntry";
-    private IMap<Long, byte[]> mapFlowEntry;
-    private MapFlowEntryListener mapFlowEntryListener;
-    private String mapFlowEntryListenerId;
-
-    // State related to the Flow ID map
-    private static final String MAP_FLOW_ID_NAME = "mapFlowId";
-    private IMap<Long, byte[]> mapFlowId;
-    private MapFlowIdListener mapFlowIdListener;
-    private String mapFlowIdListenerId;
-
-    // State related to the Flow Entry ID map
-    private static final String MAP_FLOW_ENTRY_ID_NAME = "mapFlowEntryId";
-    private IMap<Long, byte[]> mapFlowEntryId;
-    private MapFlowEntryIdListener mapFlowEntryIdListener;
-    private String mapFlowEntryIdListenerId;
-
-    // State related to the Network Topology map
-    private static final String MAP_TOPOLOGY_NAME = "mapTopology";
-    private IMap<String, byte[]> mapTopology;
-    private MapTopologyListener mapTopologyListener;
-    private String mapTopologyListenerId;
-
     // State related to the packet out map
     private static final String PACKET_OUT_MAP_NAME = "packetOutMap";
     private IMap<PacketOutNotification, byte[]> packetOutMap;
@@ -129,405 +89,6 @@
     private final List<IDeviceEventHandler> deviceEventHandlers = new ArrayList<>();
 
     /**
-     * Class for receiving notifications for Flow state.
-     * <p/>
-     * The datagrid map is:
-     * - Key : Flow ID (Long)
-     * - Value : Serialized FlowPath (byte[])
-     */
-    class MapFlowListener implements EntryListener<Long, byte[]> {
-        /**
-         * Receive a notification that an entry is added.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryAdded(EntryEvent<Long, byte[]> event) {
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            FlowPath flowPath = kryo.readObject(input, FlowPath.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowAdded(flowPath);
-        }
-
-        /**
-         * Receive a notification that an entry is removed.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryRemoved(EntryEvent<Long, byte[]> event) {
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            FlowPath flowPath = kryo.readObject(input, FlowPath.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowRemoved(flowPath);
-        }
-
-        /**
-         * Receive a notification that an entry is updated.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryUpdated(EntryEvent<Long, byte[]> event) {
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            FlowPath flowPath = kryo.readObject(input, FlowPath.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowUpdated(flowPath);
-        }
-
-        /**
-         * Receive a notification that an entry is evicted.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryEvicted(EntryEvent<Long, byte[]> event) {
-            // NOTE: We don't use eviction for this map
-        }
-    }
-
-    /**
-     * Class for receiving notifications for FlowEntry state.
-     * <p/>
-     * The datagrid map is:
-     * - Key : FlowEntry ID (Long)
-     * - Value : Serialized FlowEntry (byte[])
-     */
-    class MapFlowEntryListener implements EntryListener<Long, byte[]> {
-        /**
-         * Receive a notification that an entry is added.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryAdded(EntryEvent<Long, byte[]> event) {
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowEntryAdded(flowEntry);
-        }
-
-        /**
-         * Receive a notification that an entry is removed.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryRemoved(EntryEvent<Long, byte[]> event) {
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowEntryRemoved(flowEntry);
-        }
-
-        /**
-         * Receive a notification that an entry is updated.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryUpdated(EntryEvent<Long, byte[]> event) {
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowEntryUpdated(flowEntry);
-        }
-
-        /**
-         * Receive a notification that an entry is evicted.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryEvicted(EntryEvent<Long, byte[]> event) {
-            // NOTE: We don't use eviction for this map
-        }
-    }
-
-    /**
-     * Class for receiving notifications for FlowId state.
-     * <p/>
-     * The datagrid map is:
-     * - Key : FlowId (Long)
-     * - Value : Serialized Switch Dpid (byte[])
-     */
-    class MapFlowIdListener implements EntryListener<Long, byte[]> {
-        /**
-         * Receive a notification that an entry is added.
-         *
-         * @param event the notification event for the entry.
-         */
-        public void entryAdded(EntryEvent<Long, byte[]> event) {
-            Long keyLong = event.getKey();
-            FlowId flowId = new FlowId(keyLong);
-
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            Dpid dpid = kryo.readObject(input, Dpid.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowIdAdded(flowId, dpid);
-        }
-
-        /**
-         * Receive a notification that an entry is removed.
-         *
-         * @param event the notification event for the entry.
-         */
-        public void entryRemoved(EntryEvent<Long, byte[]> event) {
-            Long keyLong = event.getKey();
-            FlowId flowId = new FlowId(keyLong);
-
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            Dpid dpid = kryo.readObject(input, Dpid.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowIdRemoved(flowId, dpid);
-        }
-
-        /**
-         * Receive a notification that an entry is updated.
-         *
-         * @param event the notification event for the entry.
-         */
-        public void entryUpdated(EntryEvent<Long, byte[]> event) {
-            Long keyLong = event.getKey();
-            FlowId flowId = new FlowId(keyLong);
-
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            Dpid dpid = kryo.readObject(input, Dpid.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowIdUpdated(flowId, dpid);
-        }
-
-        /**
-         * Receive a notification that an entry is evicted.
-         *
-         * @param event the notification event for the entry.
-         */
-        public void entryEvicted(EntryEvent<Long, byte[]> event) {
-            // NOTE: We don't use eviction for this map
-        }
-    }
-
-    /**
-     * Class for receiving notifications for FlowEntryId state.
-     * <p/>
-     * The datagrid map is:
-     * - Key : FlowEntryId (Long)
-     * - Value : Serialized Switch Dpid (byte[])
-     */
-    class MapFlowEntryIdListener implements EntryListener<Long, byte[]> {
-        /**
-         * Receive a notification that an entry is added.
-         *
-         * @param event the notification event for the entry.
-         */
-        public void entryAdded(EntryEvent<Long, byte[]> event) {
-            Long keyLong = event.getKey();
-            FlowEntryId flowEntryId = new FlowEntryId(keyLong);
-
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            Dpid dpid = kryo.readObject(input, Dpid.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowEntryIdAdded(flowEntryId, dpid);
-        }
-
-        /**
-         * Receive a notification that an entry is removed.
-         *
-         * @param event the notification event for the entry.
-         */
-        public void entryRemoved(EntryEvent<Long, byte[]> event) {
-            Long keyLong = event.getKey();
-            FlowEntryId flowEntryId = new FlowEntryId(keyLong);
-
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            Dpid dpid = kryo.readObject(input, Dpid.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowEntryIdRemoved(flowEntryId, dpid);
-        }
-
-        /**
-         * Receive a notification that an entry is updated.
-         *
-         * @param event the notification event for the entry.
-         */
-        public void entryUpdated(EntryEvent<Long, byte[]> event) {
-            Long keyLong = event.getKey();
-            FlowEntryId flowEntryId = new FlowEntryId(keyLong);
-
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            Dpid dpid = kryo.readObject(input, Dpid.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvFlowEntryIdUpdated(flowEntryId, dpid);
-        }
-
-        /**
-         * Receive a notification that an entry is evicted.
-         *
-         * @param event the notification event for the entry.
-         */
-        public void entryEvicted(EntryEvent<Long, byte[]> event) {
-            // NOTE: We don't use eviction for this map
-        }
-    }
-
-    /**
-     * Class for receiving notifications for Network Topology state.
-     * <p/>
-     * The datagrid map is:
-     * - Key: TopologyElement ID (String)
-     * - Value: Serialized TopologyElement (byte[])
-     */
-    class MapTopologyListener implements EntryListener<String, byte[]> {
-        /**
-         * Receive a notification that an entry is added.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryAdded(EntryEvent<String, byte[]> event) {
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            TopologyElement topologyElement =
-                    kryo.readObject(input, TopologyElement.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvTopologyElementAdded(topologyElement);
-        }
-
-        /**
-         * Receive a notification that an entry is removed.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryRemoved(EntryEvent<String, byte[]> event) {
-//          String tag = "TopologyEntryRemoved.NotificationReceived." + event.getKey();
-            String tag = "TopologyEntryRemoved.NotificationReceived";
-            PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            TopologyElement topologyElement =
-                    kryo.readObject(input, TopologyElement.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvTopologyElementRemoved(topologyElement);
-//          PerformanceMonitor.stop(tag);
-            m.stop();
-//          PerformanceMonitor.report(tag);
-        }
-
-        /**
-         * Receive a notification that an entry is updated.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryUpdated(EntryEvent<String, byte[]> event) {
-            byte[] valueBytes = event.getValue();
-
-            //
-            // Decode the value and deliver the notification
-            //
-            Kryo kryo = kryoFactory.newKryo();
-            Input input = new Input(valueBytes);
-            TopologyElement topologyElement =
-                    kryo.readObject(input, TopologyElement.class);
-            kryoFactory.deleteKryo(kryo);
-            flowEventHandlerService.notificationRecvTopologyElementUpdated(topologyElement);
-        }
-
-        /**
-         * Receive a notification that an entry is evicted.
-         *
-         * @param event the notification event for the entry.
-         */
-        @Override
-        public void entryEvicted(EntryEvent<String, byte[]> event) {
-            // NOTE: We don't use eviction for this map
-        }
-    }
-
-    /**
      * MapDeviceListener - reacts to Device related events.
      */
     class MapDeviceListener implements EntryListener<Long, OnosDevice> {
@@ -897,83 +458,6 @@
         }
     }
 
-    /**
-     * Register Flow Event Handler Service for receiving Flow-related
-     * notifications.
-     * <p/>
-     * NOTE: Only a single Flow Event Handler Service can be registered.
-     *
-     * @param flowEventHandlerServiceToRegister the Flow Event Handler Service to register.
-     */
-    @Override
-    public void registerFlowEventHandlerService(IFlowEventHandlerService flowEventHandlerServiceToRegister) {
-        this.flowEventHandlerService = flowEventHandlerServiceToRegister;
-
-        // Initialize the Flow-related map state
-        mapFlowListener = new MapFlowListener();
-        mapFlow = hazelcastInstance.getMap(MAP_FLOW_NAME);
-        mapFlowListenerId = mapFlow.addEntryListener(mapFlowListener, true);
-
-        // Initialize the FlowEntry-related map state
-        mapFlowEntryListener = new MapFlowEntryListener();
-        mapFlowEntry = hazelcastInstance.getMap(MAP_FLOW_ENTRY_NAME);
-        mapFlowEntryListenerId = mapFlowEntry.addEntryListener(mapFlowEntryListener, true);
-
-        // Initialize the FlowId-related map state
-        mapFlowIdListener = new MapFlowIdListener();
-        mapFlowId = hazelcastInstance.getMap(MAP_FLOW_ID_NAME);
-        mapFlowIdListenerId = mapFlowId.addEntryListener(mapFlowIdListener, true);
-
-        // Initialize the FlowEntryId-related map state
-        mapFlowEntryIdListener = new MapFlowEntryIdListener();
-        mapFlowEntryId = hazelcastInstance.getMap(MAP_FLOW_ENTRY_ID_NAME);
-        mapFlowEntryIdListenerId = mapFlowEntryId.addEntryListener(mapFlowEntryIdListener, true);
-
-        // Initialize the Topology-related map state
-        mapTopologyListener = new MapTopologyListener();
-        mapTopology = hazelcastInstance.getMap(MAP_TOPOLOGY_NAME);
-        mapTopologyListenerId = mapTopology.addEntryListener(mapTopologyListener, true);
-    }
-
-    /**
-     * De-register Flow Event Handler Service for receiving Flow-related
-     * notifications.
-     * <p/>
-     * NOTE: Only a single Flow Event Handler Service can be registered.
-     *
-     * @param flowEventHandlerServiceToDeregister the Flow Event Handler Service to
-     *                                de-register.
-     */
-    @Override
-    public void deregisterFlowEventHandlerService(IFlowEventHandlerService flowEventHandlerServiceToDeregister) {
-        // Clear the Flow-related map state
-        mapFlow.removeEntryListener(mapFlowListenerId);
-        mapFlow = null;
-        mapFlowListener = null;
-
-        // Clear the FlowEntry-related map state
-        mapFlowEntry.removeEntryListener(mapFlowEntryListenerId);
-        mapFlowEntry = null;
-        mapFlowEntryListener = null;
-
-        // Clear the FlowId-related map state
-        mapFlowId.removeEntryListener(mapFlowIdListenerId);
-        mapFlowId = null;
-        mapFlowIdListener = null;
-
-        // Clear the FlowEntryId-related map state
-        mapFlowEntryId.removeEntryListener(mapFlowEntryIdListenerId);
-        mapFlowEntryId = null;
-        mapFlowEntryIdListener = null;
-
-        // Clear the Topology-related map state
-        mapTopology.removeEntryListener(mapTopologyListenerId);
-        mapTopology = null;
-        mapTopologyListener = null;
-
-        this.flowEventHandlerService = null;
-    }
-
     @Override
     public void registerPacketOutEventHandler(IPacketOutEventHandler packetOutEventHandler) {
         if (packetOutEventHandler != null) {
@@ -1010,552 +494,6 @@
         deviceEventHandlers.remove(deviceEventHandler);
     }
 
-    /**
-     * Get all Flows that are currently in the datagrid.
-     *
-     * @return all Flows that are currently in the datagrid.
-     */
-    @Override
-    public Collection<FlowPath> getAllFlows() {
-        Collection<FlowPath> allFlows = new LinkedList<FlowPath>();
-
-        //
-        // Get all current entries
-        //
-        Collection<byte[]> values = mapFlow.values();
-        Kryo kryo = kryoFactory.newKryo();
-        for (byte[] valueBytes : values) {
-            //
-            // Decode the value
-            //
-            Input input = new Input(valueBytes);
-            FlowPath flowPath = kryo.readObject(input, FlowPath.class);
-            allFlows.add(flowPath);
-        }
-        kryoFactory.deleteKryo(kryo);
-
-        return allFlows;
-    }
-
-    /**
-     * Get a Flow for a given Flow ID.
-     *
-     * @param flowId the Flow ID of the Flow to get.
-     * @return the Flow if found, otherwise null.
-     */
-    @Override
-    public FlowPath getFlow(FlowId flowId) {
-        byte[] valueBytes = mapFlow.get(flowId.value());
-        if (valueBytes == null) {
-            return null;
-        }
-
-        Kryo kryo = kryoFactory.newKryo();
-        //
-        // Decode the value
-        //
-        Input input = new Input(valueBytes);
-        FlowPath flowPath = kryo.readObject(input, FlowPath.class);
-        kryoFactory.deleteKryo(kryo);
-
-        return flowPath;
-    }
-
-    /**
-     * Send a notification that a Flow is added.
-     *
-     * @param flowPath the Flow that is added.
-     */
-    @Override
-    public void notificationSendFlowAdded(FlowPath flowPath) {
-        //
-        // Encode the value
-        //
-        byte[] buffer = new byte[MAX_BUFFER_SIZE];
-        Kryo kryo = kryoFactory.newKryo();
-        Output output = new Output(buffer, -1);
-        kryo.writeObject(output, flowPath);
-        byte[] valueBytes = output.toBytes();
-        kryoFactory.deleteKryo(kryo);
-
-        //
-        // Put the entry:
-        //  - Key : Flow ID (Long)
-        //  - Value : Serialized Flow (byte[])
-        //
-        mapFlow.putAsync(flowPath.flowId().value(), valueBytes);
-    }
-
-    /**
-     * Send a notification that a Flow is removed.
-     *
-     * @param flowId the Flow ID of the Flow that is removed.
-     */
-    @Override
-    public void notificationSendFlowRemoved(FlowId flowId) {
-        //
-        // Remove the entry:
-        //  - Key : Flow ID (Long)
-        //  - Value : Serialized Flow (byte[])
-        //
-        mapFlow.removeAsync(flowId.value());
-    }
-
-    /**
-     * Send a notification that a Flow is updated.
-     *
-     * @param flowPath the Flow that is updated.
-     */
-    @Override
-    public void notificationSendFlowUpdated(FlowPath flowPath) {
-        // NOTE: Adding an entry with an existing key automatically updates it
-        notificationSendFlowAdded(flowPath);
-    }
-
-    /**
-     * Send a notification that all Flows are removed.
-     */
-    @Override
-    public void notificationSendAllFlowsRemoved() {
-        //
-        // Remove all entries
-        // NOTE: We remove the entries one-by-one so the per-entry
-        // notifications will be delivered.
-        //
-        // mapFlow.clear();
-        Set<Long> keySet = mapFlow.keySet();
-        for (Long key : keySet) {
-            mapFlow.removeAsync(key);
-        }
-    }
-
-    /**
-     * Get all Flow Entries that are currently in the datagrid.
-     *
-     * @return all Flow Entries that are currently in the datagrid.
-     */
-    @Override
-    public Collection<FlowEntry> getAllFlowEntries() {
-        Collection<FlowEntry> allFlowEntries = new LinkedList<FlowEntry>();
-
-        //
-        // Get all current entries
-        //
-        Collection<byte[]> values = mapFlowEntry.values();
-        Kryo kryo = kryoFactory.newKryo();
-        for (byte[] valueBytes : values) {
-            //
-            // Decode the value
-            //
-            Input input = new Input(valueBytes);
-            FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
-            allFlowEntries.add(flowEntry);
-        }
-        kryoFactory.deleteKryo(kryo);
-
-        return allFlowEntries;
-    }
-
-    /**
-     * Get a Flow Entry for a given Flow Entry ID.
-     *
-     * @param flowEntryId the Flow Entry ID of the Flow Entry to get.
-     * @return the Flow Entry if found, otherwise null.
-     */
-    @Override
-    public FlowEntry getFlowEntry(FlowEntryId flowEntryId) {
-        byte[] valueBytes = mapFlowEntry.get(flowEntryId.value());
-        if (valueBytes == null) {
-            return null;
-        }
-
-        Kryo kryo = kryoFactory.newKryo();
-        //
-        // Decode the value
-        //
-        Input input = new Input(valueBytes);
-        FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
-        kryoFactory.deleteKryo(kryo);
-
-        return flowEntry;
-    }
-
-    /**
-     * Send a notification that a FlowEntry is added.
-     *
-     * @param flowEntry the FlowEntry that is added.
-     */
-    @Override
-    public void notificationSendFlowEntryAdded(FlowEntry flowEntry) {
-        //
-        // Encode the value
-        //
-        byte[] buffer = new byte[MAX_BUFFER_SIZE];
-        Kryo kryo = kryoFactory.newKryo();
-        Output output = new Output(buffer, -1);
-        kryo.writeObject(output, flowEntry);
-        byte[] valueBytes = output.toBytes();
-        kryoFactory.deleteKryo(kryo);
-
-        //
-        // Put the entry:
-        //  - Key : FlowEntry ID (Long)
-        //  - Value : Serialized FlowEntry (byte[])
-        //
-        mapFlowEntry.putAsync(flowEntry.flowEntryId().value(), valueBytes);
-    }
-
-    /**
-     * Send a notification that a FlowEntry is removed.
-     *
-     * @param flowEntryId the FlowEntry ID of the FlowEntry that is removed.
-     */
-    @Override
-    public void notificationSendFlowEntryRemoved(FlowEntryId flowEntryId) {
-        //
-        // Remove the entry:
-        //  - Key : FlowEntry ID (Long)
-        //  - Value : Serialized FlowEntry (byte[])
-        //
-        mapFlowEntry.removeAsync(flowEntryId.value());
-    }
-
-    /**
-     * Send a notification that a FlowEntry is updated.
-     *
-     * @param flowEntry the FlowEntry that is updated.
-     */
-    @Override
-    public void notificationSendFlowEntryUpdated(FlowEntry flowEntry) {
-        // NOTE: Adding an entry with an existing key automatically updates it
-        notificationSendFlowEntryAdded(flowEntry);
-    }
-
-    /**
-     * Send a notification that all Flow Entries are removed.
-     */
-    @Override
-    public void notificationSendAllFlowEntriesRemoved() {
-        //
-        // Remove all entries
-        // NOTE: We remove the entries one-by-one so the per-entry
-        // notifications will be delivered.
-        //
-        // mapFlowEntry.clear();
-        Set<Long> keySet = mapFlowEntry.keySet();
-        for (Long key : keySet) {
-            mapFlowEntry.removeAsync(key);
-        }
-    }
-
-    /**
-     * Get all Flow IDs that are currently in the datagrid.
-     *
-     * @return all Flow IDs that are currently in the datagrid.
-     */
-    @Override
-    public Collection<Pair<FlowId, Dpid>> getAllFlowIds() {
-        Collection<Pair<FlowId, Dpid>> allFlowIds =
-                new LinkedList<Pair<FlowId, Dpid>>();
-
-        //
-        // Get all current entries
-        //
-        Kryo kryo = kryoFactory.newKryo();
-        for (Map.Entry<Long, byte[]> entry : mapFlowId.entrySet()) {
-            Long key = entry.getKey();
-            byte[] valueBytes = entry.getValue();
-
-            FlowId flowId = new FlowId(key);
-
-            //
-            // Decode the value
-            //
-            Input input = new Input(valueBytes);
-            Dpid dpid = kryo.readObject(input, Dpid.class);
-
-            Pair<FlowId, Dpid> pair = new Pair(flowId, dpid);
-            allFlowIds.add(pair);
-        }
-        kryoFactory.deleteKryo(kryo);
-
-        return allFlowIds;
-    }
-
-    /**
-     * Get all Flow Entry IDs that are currently in the datagrid.
-     *
-     * @return all Flow Entry IDs that ae currently in the datagrid.
-     */
-    @Override
-    public Collection<Pair<FlowEntryId, Dpid>> getAllFlowEntryIds() {
-        Collection<Pair<FlowEntryId, Dpid>> allFlowEntryIds =
-                new LinkedList<Pair<FlowEntryId, Dpid>>();
-
-        //
-        // Get all current entries
-        //
-        Kryo kryo = kryoFactory.newKryo();
-        for (Map.Entry<Long, byte[]> entry : mapFlowEntryId.entrySet()) {
-            Long key = entry.getKey();
-            byte[] valueBytes = entry.getValue();
-
-            FlowEntryId flowEntryId = new FlowEntryId(key);
-
-            //
-            // Decode the value
-            //
-            Input input = new Input(valueBytes);
-            Dpid dpid = kryo.readObject(input, Dpid.class);
-
-            Pair<FlowEntryId, Dpid> pair = new Pair(flowEntryId, dpid);
-            allFlowEntryIds.add(pair);
-        }
-        kryoFactory.deleteKryo(kryo);
-
-        return allFlowEntryIds;
-    }
-
-    /**
-     * Send a notification that a FlowId is added.
-     *
-     * @param flowId the FlowId that is added.
-     * @param dpid   the Source Switch Dpid.
-     */
-    @Override
-    public void notificationSendFlowIdAdded(FlowId flowId, Dpid dpid) {
-        //
-        // Encode the value
-        //
-        byte[] buffer = new byte[MAX_BUFFER_SIZE];
-        Kryo kryo = kryoFactory.newKryo();
-        Output output = new Output(buffer, -1);
-        kryo.writeObject(output, dpid);
-        byte[] valueBytes = output.toBytes();
-        kryoFactory.deleteKryo(kryo);
-
-        //
-        // Put the entry:
-        //  - Key : FlowId (Long)
-        //  - Value : Serialized Switch Dpid (byte[])
-        //
-        mapFlowId.putAsync(flowId.value(), valueBytes);
-    }
-
-    /**
-     * Send a notification that a FlowId is removed.
-     *
-     * @param flowId the FlowId that is removed.
-     */
-    @Override
-    public void notificationSendFlowIdRemoved(FlowId flowId) {
-        //
-        // Remove the entry:
-        //  - Key : FlowId (Long)
-        //  - Value : Serialized Switch Dpid (byte[])
-        //
-        mapFlowId.removeAsync(flowId.value());
-    }
-
-    /**
-     * Send a notification that a FlowId is updated.
-     *
-     * @param flowId the FlowId that is updated.
-     * @param dpid   the Source Switch Dpid.
-     */
-    @Override
-    public void notificationSendFlowIdUpdated(FlowId flowId, Dpid dpid) {
-        // NOTE: Adding an entry with an existing key automatically updates it
-        notificationSendFlowIdAdded(flowId, dpid);
-    }
-
-    /**
-     * Send a notification that all Flow IDs are removed.
-     */
-    @Override
-    public void notificationSendAllFlowIdsRemoved() {
-        //
-        // Remove all entries
-        // NOTE: We remove the entries one-by-one so the per-entry
-        // notifications will be delivered.
-        //
-        // mapFlowId.clear();
-        Set<Long> keySet = mapFlowId.keySet();
-        for (Long key : keySet) {
-            mapFlowId.removeAsync(key);
-        }
-    }
-
-    /**
-     * Send a notification that a FlowEntryId is added.
-     *
-     * @param flowEntryId the FlowEntryId that is added.
-     * @param dpid        the Switch Dpid.
-     */
-    @Override
-    public void notificationSendFlowEntryIdAdded(FlowEntryId flowEntryId,
-                                                 Dpid dpid) {
-        //
-        // Encode the value
-        //
-        byte[] buffer = new byte[MAX_BUFFER_SIZE];
-        Kryo kryo = kryoFactory.newKryo();
-        Output output = new Output(buffer, -1);
-        kryo.writeObject(output, dpid);
-        byte[] valueBytes = output.toBytes();
-        kryoFactory.deleteKryo(kryo);
-
-        //
-        // Put the entry:
-        //  - Key : FlowEntryId (Long)
-        //  - Value : Serialized Switch Dpid (byte[])
-        //
-        mapFlowEntryId.putAsync(flowEntryId.value(), valueBytes);
-    }
-
-    /**
-     * Send a notification that a FlowEntryId is removed.
-     *
-     * @param flowEntryId the FlowEntryId that is removed.
-     */
-    @Override
-    public void notificationSendFlowEntryIdRemoved(FlowEntryId flowEntryId) {
-        //
-        // Remove the entry:
-        //  - Key : FlowEntryId (Long)
-        //  - Value : Serialized Switch Dpid (byte[])
-        //
-        mapFlowEntryId.removeAsync(flowEntryId.value());
-    }
-
-    /**
-     * Send a notification that a FlowEntryId is updated.
-     *
-     * @param flowEntryId the FlowEntryId that is updated.
-     * @param dpid        the Switch Dpid.
-     */
-    @Override
-    public void notificationSendFlowEntryIdUpdated(FlowEntryId flowEntryId,
-                                                   Dpid dpid) {
-        // NOTE: Adding an entry with an existing key automatically updates it
-        notificationSendFlowEntryIdAdded(flowEntryId, dpid);
-    }
-
-    /**
-     * Send a notification that all Flow Entry IDs are removed.
-     */
-    @Override
-    public void notificationSendAllFlowEntryIdsRemoved() {
-        //
-        // Remove all entries
-        // NOTE: We remove the entries one-by-one so the per-entry
-        // notifications will be delivered.
-        //
-        // mapFlowEntryId.clear();
-        Set<Long> keySet = mapFlowEntryId.keySet();
-        for (Long key : keySet) {
-            mapFlowEntryId.removeAsync(key);
-        }
-    }
-
-    /**
-     * Get all Topology Elements that are currently in the datagrid.
-     *
-     * @return all Topology Elements that are currently in the datagrid.
-     */
-    @Override
-    public Collection<TopologyElement> getAllTopologyElements() {
-        Collection<TopologyElement> allTopologyElements =
-                new LinkedList<TopologyElement>();
-
-        //
-        // Get all current entries
-        //
-        Collection<byte[]> values = mapTopology.values();
-        Kryo kryo = kryoFactory.newKryo();
-        for (byte[] valueBytes : values) {
-            //
-            // Decode the value
-            //
-            Input input = new Input(valueBytes);
-            TopologyElement topologyElement =
-                    kryo.readObject(input, TopologyElement.class);
-            allTopologyElements.add(topologyElement);
-        }
-        kryoFactory.deleteKryo(kryo);
-
-        return allTopologyElements;
-    }
-
-    /**
-     * Send a notification that a Topology Element is added.
-     *
-     * @param topologyElement the Topology Element that is added.
-     */
-    @Override
-    public void notificationSendTopologyElementAdded(TopologyElement topologyElement) {
-        //
-        // Encode the value
-        //
-        byte[] buffer = new byte[MAX_BUFFER_SIZE];
-        Kryo kryo = kryoFactory.newKryo();
-        Output output = new Output(buffer, -1);
-        kryo.writeObject(output, topologyElement);
-        byte[] valueBytes = output.toBytes();
-        kryoFactory.deleteKryo(kryo);
-
-        //
-        // Put the entry:
-        //  - Key : TopologyElement ID (String)
-        //  - Value : Serialized TopologyElement (byte[])
-        //
-        mapTopology.putAsync(topologyElement.elementId(), valueBytes);
-
-    }
-
-    /**
-     * Send a notification that a Topology Element is removed.
-     *
-     * @param topologyElement the Topology Element that is removed.
-     */
-    @Override
-    public void notificationSendTopologyElementRemoved(TopologyElement topologyElement) {
-        //
-        // Remove the entry:
-        //  - Key : TopologyElement ID (String)
-        //  - Value : Serialized TopologyElement (byte[])
-        //
-        mapTopology.removeAsync(topologyElement.elementId());
-    }
-
-    /**
-     * Send a notification that a Topology Element is updated.
-     *
-     * @param topologyElement the Topology Element that is updated.
-     */
-    @Override
-    public void notificationSendTopologyElementUpdated(TopologyElement topologyElement) {
-        // NOTE: Adding an entry with an existing key automatically updates it
-        notificationSendTopologyElementAdded(topologyElement);
-    }
-
-    /**
-     * Send a notification that all Topology Elements are removed.
-     */
-    @Override
-    public void notificationSendAllTopologyElementsRemoved() {
-        //
-        // Remove all entries
-        // NOTE: We remove the entries one-by-one so the per-entry
-        // notifications will be delivered.
-        //
-        // mapTopology.clear();
-        Set<String> keySet = mapTopology.keySet();
-        for (String key : keySet) {
-            mapTopology.removeAsync(key);
-        }
-    }
-
     @Override
     public void sendPacketOutNotification(PacketOutNotification packetOutNotification) {
         packetOutMap.putAsync(packetOutNotification, dummyByte, 1L, TimeUnit.MILLISECONDS);
diff --git a/src/main/java/net/onrc/onos/datagrid/IDatagridService.java b/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
index 0c79b81..1045bcd 100755
--- a/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
+++ b/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
@@ -6,18 +6,10 @@
 import net.onrc.onos.intent.Intent;
 import net.onrc.onos.ofcontroller.devicemanager.IDeviceEventHandler;
 import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
-import net.onrc.onos.ofcontroller.flowmanager.IFlowEventHandlerService;
 import net.onrc.onos.ofcontroller.proxyarp.ArpReplyNotification;
 import net.onrc.onos.ofcontroller.proxyarp.IArpReplyEventHandler;
 import net.onrc.onos.ofcontroller.proxyarp.IPacketOutEventHandler;
 import net.onrc.onos.ofcontroller.proxyarp.PacketOutNotification;
-import net.onrc.onos.ofcontroller.topology.TopologyElement;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntryId;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.Pair;
 
 /**
  * Interface for providing Datagrid Service to other modules.
@@ -66,26 +58,6 @@
      * register all the intents as one batch
      */
     void registerIntent(Collection<Intent> intents);
-    /**
-     * Register Flow Event Handler Service for receiving Flow-related
-     * notifications.
-     *
-     * NOTE: Only a single Flow Event Handler Service can be registered.
-     *
-     * @param flowEventHandlerService the Flow Event Handler Service to register.
-     */
-    void registerFlowEventHandlerService(IFlowEventHandlerService flowEventHandlerService);
-
-    /**
-     * De-register Flow Event Handler Service for receiving Flow-related
-     * notifications.
-     *
-     * NOTE: Only a single Flow Event Handler Service can be registered.
-     *
-     * @param flowEventHandlerService the Flow Event Handler Service to
-     * de-register.
-     */
-    void deregisterFlowEventHandlerService(IFlowEventHandlerService flowEventHandlerService);
 
     /**
      * Register event handler for packet-out events.
@@ -116,192 +88,6 @@
     public void deregisterArpReplyEventHandler(IArpReplyEventHandler arpReplyEventHandler);
 
     /**
-     * Get all Flows that are currently in the datagrid.
-     *
-     * @return all Flows that are currently in the datagrid.
-     */
-    Collection<FlowPath> getAllFlows();
-
-    /**
-     * Get a Flow for a given Flow ID.
-     *
-     * @param flowId the Flow ID of the Flow to get.
-     * @return the Flow if found, otherwise null.
-     */
-    FlowPath getFlow(FlowId flowId);
-
-    /**
-     * Send a notification that a Flow is added.
-     *
-     * @param flowPath the Flow that is added.
-     */
-    void notificationSendFlowAdded(FlowPath flowPath);
-
-    /**
-     * Send a notification that a Flow is removed.
-     *
-     * @param flowId the Flow ID of the Flow that is removed.
-     */
-    void notificationSendFlowRemoved(FlowId flowId);
-
-    /**
-     * Send a notification that a Flow is updated.
-     *
-     * @param flowPath the Flow that is updated.
-     */
-    void notificationSendFlowUpdated(FlowPath flowPath);
-
-    /**
-     * Send a notification that all Flows are removed.
-     */
-    void notificationSendAllFlowsRemoved();
-
-    /**
-     * Get all Flow Entries that are currently in the datagrid.
-     *
-     * @return all Flow Entries that are currently in the datagrid.
-     */
-    Collection<FlowEntry> getAllFlowEntries();
-
-    /**
-     * Get a Flow Entry for a given Flow Entry ID.
-     *
-     * @param flowEntryId the Flow Entry ID of the Flow Entry to get.
-     * @return the Flow Entry if found, otherwise null.
-     */
-    FlowEntry getFlowEntry(FlowEntryId flowEntryId);
-
-    /**
-     * Send a notification that a FlowEntry is added.
-     *
-     * @param flowEntry the FlowEntry that is added.
-     */
-    void notificationSendFlowEntryAdded(FlowEntry flowEntry);
-
-    /**
-     * Send a notification that a FlowEntry is removed.
-     *
-     * @param flowEntryId the FlowEntry ID of the FlowEntry that is removed.
-     */
-    void notificationSendFlowEntryRemoved(FlowEntryId flowEntryId);
-
-    /**
-     * Send a notification that a FlowEntry is updated.
-     *
-     * @param flowEntry the FlowEntry that is updated.
-     */
-    void notificationSendFlowEntryUpdated(FlowEntry flowEntry);
-
-    /**
-     * Send a notification that all Flow Entries are removed.
-     */
-    void notificationSendAllFlowEntriesRemoved();
-
-    /**
-     * Get all Flow IDs that are currently in the datagrid.
-     *
-     * @return all Flow IDs that ae currently in the datagrid.
-     */
-    Collection<Pair<FlowId, Dpid>> getAllFlowIds();
-
-    /**
-     * Send a notification that a FlowId is added.
-     *
-     * @param flowId the FlowId that is added.
-     * @param dpid the Source Switch Dpid.
-     */
-    void notificationSendFlowIdAdded(FlowId flowId, Dpid dpid);
-
-    /**
-     * Send a notification that a FlowId is removed.
-     *
-     * @param flowId the FlowId that is removed.
-     */
-    void notificationSendFlowIdRemoved(FlowId flowId);
-
-    /**
-     * Send a notification that a FlowId is updated.
-     *
-     * @param flowId the FlowId that is updated.
-     * @param dpid the Source Switch Dpid.
-     */
-    void notificationSendFlowIdUpdated(FlowId flowId, Dpid dpid);
-
-    /**
-     * Send a notification that all Flow IDs are removed.
-     */
-    void notificationSendAllFlowIdsRemoved();
-
-    /**
-     * Get all Flow Entry IDs that are currently in the datagrid.
-     *
-     * @return all Flow Entry IDs that ae currently in the datagrid.
-     */
-    Collection<Pair<FlowEntryId, Dpid>> getAllFlowEntryIds();
-
-    /**
-     * Send a notification that a FlowEntryId is added.
-     *
-     * @param flowEntryId the FlowEntryId that is added.
-     * @param dpid the Switch Dpid.
-     */
-    void notificationSendFlowEntryIdAdded(FlowEntryId flowEntryId, Dpid dpid);
-
-    /**
-     * Send a notification that a FlowEntryId is removed.
-     *
-     * @param flowEntryId the FlowEntryId that is removed.
-     */
-    void notificationSendFlowEntryIdRemoved(FlowEntryId flowEntryId);
-
-    /**
-     * Send a notification that a FlowEntryId is updated.
-     *
-     * @param flowEntryId the FlowEntryId that is updated.
-     * @param dpid the Switch Dpid.
-     */
-    void notificationSendFlowEntryIdUpdated(FlowEntryId flowEntryId,
-					    Dpid dpid);
-
-    /**
-     * Send a notification that all Flow Entry IDs are removed.
-     */
-    void notificationSendAllFlowEntryIdsRemoved();
-
-    /**
-     * Get all Topology Elements that are currently in the datagrid.
-     *
-     * @return all Topology Elements that are currently in the datagrid.
-     */
-    Collection<TopologyElement> getAllTopologyElements();
-
-    /**
-     * Send a notification that a Topology Element is added.
-     *
-     * @param topologyElement the Topology Element that is added.
-     */
-    void notificationSendTopologyElementAdded(TopologyElement topologyElement);
-
-    /**
-     * Send a notification that a Topology Element is removed.
-     *
-     * @param topologyElement the Topology Element that is removed.
-     */
-    void notificationSendTopologyElementRemoved(TopologyElement topologyElement);
-
-    /**
-     * Send a notification that a Topology Element is updated.
-     *
-     * @param topologyElement the Topology Element that is updated.
-     */
-    void notificationSendTopologyElementUpdated(TopologyElement topologyElement);
-
-    /**
-     * Send a notification that all Topology Elements are removed.
-     */
-    void notificationSendAllTopologyElementsRemoved();
-    
-    /**
      * Send a packet-out notification to other ONOS instances. This informs
      * other instances that they should send this packet out some of the ports
      * they control. Not all notifications are applicable to all instances 
diff --git a/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java b/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
index 82a1157..5491d34 100755
--- a/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
+++ b/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
@@ -16,7 +16,6 @@
     @Override
     public Restlet getRestlet(Context context) {
         Router router = new Router(context);
-        router.attach("/get/map/{map-name}/json", GetMapResource.class);
         router.attach("/add/intents/json", IntentResource.class);
         router.attach("/get/intents/json", IntentResource.class);
         router.attach("/get/intent/{intent_id}/json", IntentResource.class);
diff --git a/src/main/java/net/onrc/onos/datagrid/web/GetMapResource.java b/src/main/java/net/onrc/onos/datagrid/web/GetMapResource.java
deleted file mode 100644
index 6a56b2f..0000000
--- a/src/main/java/net/onrc/onos/datagrid/web/GetMapResource.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package net.onrc.onos.datagrid.web;
-
-import java.util.Collection;
-
-import net.onrc.onos.datagrid.IDatagridService;
-import net.onrc.onos.ofcontroller.topology.TopologyElement;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Datagrid REST API implementation: Get the state of a map.
- *
- * Valid map names:
- *  - "all"        : Get all maps
- *  - "flow"       : Get the Flows
- *  - "flow-entry" : Get the Flow Entries
- *  - "topology"   : Get the Topology
- *
- *   GET /wm/onos/datagrid/get/map/{map-name}/json
- */
-public class GetMapResource extends ServerResource {
-    protected final static Logger log = LoggerFactory.getLogger(GetMapResource.class);
-
-    /**
-     * Implement the API.
-     *
-     * @return a string with the state of the map(s).
-     */
-    @Get("json")
-    public String retrieve() {
-	String result = "";
-
-        IDatagridService datagridService =
-                (IDatagridService)getContext().getAttributes().
-                get(IDatagridService.class.getCanonicalName());
-
-        if (datagridService == null) {
-	    log.debug("ONOS Datagrid Service not found");
-            return result;
-	}
-
-	// Extract the arguments
-	String mapNameStr = (String)getRequestAttributes().get("map-name");
-
-	log.debug("Get Datagrid Map: {}", mapNameStr);
-
-	//
-	// Get the Flows
-	//
-	if (mapNameStr.equals("flow") || mapNameStr.equals("all")) {
-	    Collection<FlowPath> flowPaths = datagridService.getAllFlows();
-	    result += "Flows:\n";
-	    for (FlowPath flowPath : flowPaths) {
-		result += flowPath.toString() + "\n";
-	    }
-	}
-
-	//
-	// Get the Flow Entries
-	//
-	if (mapNameStr.equals("flow-entry") || mapNameStr.equals("all")) {
-	    Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
-	    result += "Flow Entries:\n";
-	    for (FlowEntry flowEntry : flowEntries) {
-		result += flowEntry.toString() + "\n";
-	    }
-	}
-
-	if (mapNameStr.equals("topology") || mapNameStr.equals("all")) {
-	    Collection<TopologyElement> topologyElements = datagridService.getAllTopologyElements();
-	    result += "Topology:\n";
-	    for (TopologyElement topologyElement : topologyElements) {
-		result += topologyElement.toString() + "\n";
-	    }
-	}
-
-        return result;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/ApplnObjectType.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/ApplnObjectType.java
deleted file mode 100644
index 6fa2cd1..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/ApplnObjectType.java
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package net.onrc.onos.ofcontroller.flowmanager;
-
-public enum ApplnObjectType {
-    FLOWPATH,
-    FLOWENTRY,  
-    UNKNOWN
-}
-
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/DBOperationType.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/DBOperationType.java
deleted file mode 100644
index 8764ce4..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/DBOperationType.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package net.onrc.onos.ofcontroller.flowmanager;
-
-public enum DBOperationType {
-    ADD,
-    UPDATE,
-    QUERY,
-    REMOVE,
-    INVALID
-}
-
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
deleted file mode 100755
index 514e389..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
+++ /dev/null
@@ -1,1258 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import com.tinkerpop.blueprints.Direction;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.Map;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.util.MACAddress;
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IBaseObject;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.onrc.onos.ofcontroller.util.*;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.tinkerpop.blueprints.impls.ramcloud.PerfMon;
-import com.tinkerpop.blueprints.impls.ramcloud.RamCloudVertex;
-
-/**
- * Class for performing Flow-related operations on the Database.
- */
-public class FlowDatabaseOperation {
-    private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
-    private static final boolean measureONOSFlowTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlow", "0")) != 0;
-    private static final boolean measureONOSFlowEntryTimeProp = Long.valueOf(System.getProperty("benchmark.measureONOSFlowEntry", "0")) != 0;
-
-    /**
-     * Add a flow by batching all flow path properties and flow entries together.
-     * This is done for performance reasons.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowPath the Flow Path to install.
-     * @return true on success, otherwise false.
-     */
-    static boolean addFlowFast(DBOperation dbHandler, FlowPath flowPath) {
-	IFlowPath flowPathObj;
-	FlowPathProperty flowProp = new FlowPathProperty();
-        FlowEntity flowPathEntity = new FlowEntity();
-        boolean flowPathUpdate = false;
-	
-	flowPathObj = dbHandler.searchFlowPath(flowPath.flowId()); // getVertices("flow_id")
-	if (flowPathObj == null) {
-	    try {
-                flowPathEntity.operationBegin(DBOperationType.ADD.toString());
-		flowPathObj = dbHandler.newFlowPath();
-	    } catch (Exception e) {
-		flowPathObj = null;
-		StringWriter sw = new StringWriter();
-		e.printStackTrace(new PrintWriter(sw));
-		log.error(":addFlow FlowId:{} failed: {}", flowPath.flowId(), sw.toString());
-	    }
-            flowPathEntity.setProperty("user_state", "FP_USER_ADD");
-	    flowProp.setFlowPathUserState("FP_USER_ADD");
-	} else {
-            flowPathUpdate = true;
-	    // Remove the old Flow Entries (this is special for RAMCloud)
-	    for (IFlowEntry flowEntryObj : flowPathObj.getFlowEntries()) { // get.@Adjacency("flow", IN)
-                flowPathEntity.operationBegin(DBOperationType.REMOVE.toString());
-		dbHandler.removeFlowEntry(flowEntryObj); // removeVertex()
-                flowPathEntity.operationEnd(DBOperationType.REMOVE.toString());
-	    }
-            flowPathEntity.operationBegin(DBOperationType.UPDATE.toString());
-            flowPathEntity.setProperty("user_state", "FP_USER_ADD");
-	    flowProp.setFlowPathUserState("FP_USER_MODIFY");
-	}
-	if (flowPathObj == null) {
-	    log.error(":addFlow FlowId:{} failed: Flow object not created", flowPath.flowId());
-	    dbHandler.rollback();
-	    return false;
-	}
-
-        flowPathEntity.setProperty("flow_id", flowPath.flowId().toString());
-	// Set the Flow key
-	flowProp.setFlowId(flowPath.flowId().toString());
-
-	// Set the Flow attributes
-        flowPathEntity.setProperty("installer_id", flowPath.installerId().toString());
-	flowProp.setInstallerId(flowPath.installerId().toString());
-
-        flowPathEntity.setProperty("flow_path_type", flowPath.flowPathType().toString());
-	flowProp.setFlowPathType(flowPath.flowPathType().toString());
-
-        flowPathEntity.setProperty("user_state", flowPath.flowPathUserState().toString());
-	flowProp.setFlowPathUserState(flowPath.flowPathUserState().toString());
-
-
-        flowPathEntity.setProperty("flow_path_flags", flowPath.flowPathFlags().flags());
-	flowProp.setFlowPathFlags(flowPath.flowPathFlags().flags());
-
-        flowPathEntity.setProperty("idle_timeout", flowPath.idleTimeout());
-	flowProp.setIdleTimeout(flowPath.idleTimeout());
-
-        flowPathEntity.setProperty("hard_timeout", flowPath.hardTimeout());
-	flowProp.setHardTimeout(flowPath.hardTimeout());
-
-        flowPathEntity.setProperty("priority", flowPath.priority());
-	flowProp.setPriority(flowPath.priority());
-
-        flowPathEntity.setProperty("src_switch", flowPath.dataPath().srcPort().dpid().toString());
-	flowProp.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
-
-        flowPathEntity.setProperty("src_port", flowPath.dataPath().srcPort().port().value());
-	flowProp.setSrcPort(flowPath.dataPath().srcPort().port().value());
-
-        flowPathEntity.setProperty("dst_switch", flowPath.dataPath().dstPort().dpid().toString());
-	flowProp.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
-
-        flowPathEntity.setProperty("dst_port", flowPath.dataPath().dstPort().port().value());
-	flowProp.setDstPort(flowPath.dataPath().dstPort().port().value());
-
-	if (flowPath.flowEntryMatch().matchSrcMac()) {
-            flowPathEntity.setProperty("matchSrcMac",flowPath.flowEntryMatch().srcMac().toString());
-	    flowProp.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
-	}
-	if (flowPath.flowEntryMatch().matchDstMac()) {
-            flowPathEntity.setProperty("matchDstMac", flowPath.flowEntryMatch().dstMac().toString());
-	    flowProp.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
-	}
-	if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
-            flowPathEntity.setProperty("matchEthernetFrameType", flowPath.flowEntryMatch().ethernetFrameType());
-	    flowProp.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
-	}
-	if (flowPath.flowEntryMatch().matchVlanId()) {
-            flowPathEntity.setProperty("matchVlanId", flowPath.flowEntryMatch().vlanId());
-	    flowProp.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
-	}
-	if (flowPath.flowEntryMatch().matchVlanPriority()) {
-            flowPathEntity.setProperty("matchVlanPriority", flowPath.flowEntryMatch().vlanPriority());
-	    flowProp.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
-	}
-	if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
-            flowPathEntity.setProperty("matchSrcIPv4Net", flowPath.flowEntryMatch().srcIPv4Net().toString());
-	    flowProp.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
-	}
-	if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
-            flowPathEntity.setProperty("matchDstIPv4Net", flowPath.flowEntryMatch().dstIPv4Net().toString());
-	    flowProp.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
-	}
-	if (flowPath.flowEntryMatch().matchIpProto()) {
-            flowPathEntity.setProperty("matchIpProto", flowPath.flowEntryMatch().ipProto());
-	    flowProp.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
-	}
-	if (flowPath.flowEntryMatch().matchIpToS()) {
-            flowPathEntity.setProperty("matchIpToS", flowPath.flowEntryMatch().ipToS());
-	    flowProp.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
-	}
-	if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
-            flowPathEntity.setProperty("matchSrcTcpUdpPort", flowPath.flowEntryMatch().srcTcpUdpPort());
-	    flowProp.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
-	}
-	if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
-            flowPathEntity.setProperty("matchDstTcpUdpPort", flowPath.flowEntryMatch().dstTcpUdpPort());
-	    flowProp.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
-	}
-	if (! flowPath.flowEntryActions().actions().isEmpty()) {
-            flowPathEntity.setProperty("actions", flowPath.flowEntryActions().toString());
-	    flowProp.setActions(flowPath.flowEntryActions().toString());
-	}
-
-	flowProp.commitProperties(dbHandler, flowPathObj);
-
-	//
-	// Flow Entries:
-	// flowPath.dataPath().flowEntries()
-	//
-	for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
-	    if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE)
-		continue;	// Skip: all Flow Entries were deleted earlier
-
-	    IFlowEntry iFlowEntry;
-	    FlowEntryProperty flowEntryProp = new FlowEntryProperty();
-            FlowEntity flowEntryEntity = new FlowEntity();
-            boolean updateFlowEntry = false;
-	    
-	    try {
-		iFlowEntry = dbHandler.searchFlowEntry(flowEntry.flowEntryId()); // getVertices()
-		if (iFlowEntry != null) {
-                    updateFlowEntry = true;
-                    flowEntryEntity.operationBegin(DBOperationType.UPDATE.toString());
-                    flowEntryEntity.setProperty("user_state", "FE_USER_MODIFY");
-		    flowEntryProp.setUserState("FE_USER_MODIFY");
-		} else {
-                    flowEntryEntity.operationBegin(DBOperationType.ADD.toString());
-                    flowEntryEntity.setProperty("user_state", "FE_USER_ADD");
-		    flowEntryProp.setUserState("FE_USER_ADD");
-                    flowEntryEntity.addEdge(flowPathObj, Direction.OUT, "flow");
-		}
-	    } catch (Exception e) {
-                // TODO do we really need to catch this exception.
-	    }
-	    
-            flowEntryEntity.setProperty("flow_id", flowEntry.flowEntryId().toString());
-	    // Set the Flow Entry key
-           flowEntryEntity.setProperty("flow_entry_id", flowEntry.flowEntryId().toString());
-
-            flowEntryEntity.setProperty("type", "flow_entry");
-
-	    // Set the Flow Entry Edges
-	    ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString()); // toshi memo: getVertices()
-
-            flowEntryEntity.setProperty("idle_timeout", flowEntry.idleTimeout());
-
-            flowEntryEntity.setProperty("hard_timeout", flowEntry.hardTimeout());
-
-            flowEntryEntity.setProperty("priority", flowEntry.priority());
-
-            flowEntryEntity.setProperty("switch_dpid", flowEntry.dpid().toString());
-
-            flowEntryEntity.addEdge(sw, Direction.OUT, "switch");
-	    if (flowEntry.flowEntryMatch().matchInPort()) {
-		IPortObject inport = dbHandler.searchPort(flowEntry.dpid().toString(), flowEntry.flowEntryMatch().inPort().value()); // toshi memo: getVertices()
-
-                flowEntryEntity.setProperty("matchInPort", flowEntry.flowEntryMatch().inPort().value());
-                flowEntryEntity.addEdge(inport, Direction.OUT, "inport");
-	    }
-
-	    // Set the Flow Entry attributes
-	    if (flowEntry.flowEntryMatch().matchSrcMac()) {
-                flowEntryEntity.setProperty("matchSrcMac", flowEntry.flowEntryMatch().srcMac().toString());
-	    }
-	    if (flowEntry.flowEntryMatch().matchDstMac()) {
-                flowEntryEntity.setProperty("matchDstMac", flowEntry.flowEntryMatch().dstMac().toString());
-	    }
-	    if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
-                flowEntryEntity.setProperty("matchEthernetFrameType", flowEntry.flowEntryMatch().ethernetFrameType());
-	    }
-	    if (flowEntry.flowEntryMatch().matchVlanId()) {
-                flowEntryEntity.setProperty("matchVlanId", flowEntry.flowEntryMatch().vlanId());
-	    }
-	    if (flowEntry.flowEntryMatch().matchVlanPriority()) {
-                flowEntryEntity.setProperty("matchVlanPriority", flowEntry.flowEntryMatch().vlanPriority());
-	    }
-	    if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
-                flowEntryEntity.setProperty("matchSrcIPv4Net", flowEntry.flowEntryMatch().srcIPv4Net().toString());
-	    }
-	    if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
-                flowEntryEntity.setProperty("matchDstIPv4Net", flowEntry.flowEntryMatch().dstIPv4Net().toString());
-	    }
-	    if (flowEntry.flowEntryMatch().matchIpProto()) {
-                flowEntryEntity.setProperty("matchIpProto", flowEntry.flowEntryMatch().ipProto());
-	    }
-	    if (flowEntry.flowEntryMatch().matchIpToS()) {
-                flowEntryEntity.setProperty("matchIpToS", flowEntry.flowEntryMatch().ipToS());
-	    }
-	    if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
-                flowEntryEntity.setProperty("matchSrcTcpUdpPort", flowEntry.flowEntryMatch().srcTcpUdpPort());
-	    }
-	    if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
-                flowEntryEntity.setProperty("matchDstTcpUdpPort", flowEntry.flowEntryMatch().dstTcpUdpPort());
-	    }
-
-	    for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
-		if (fa.actionOutput() != null) {
-		    IPortObject outport = dbHandler.searchPort(flowEntry.dpid().toString(), fa.actionOutput().port().value()); // toshi memo: getVertices()
-                    flowEntryEntity.setProperty("actionOutputPort", fa.actionOutput().port().value());
-                    flowEntryEntity.addEdge(outport, Direction.OUT, "outport");
-		}
-	    }
-	    if (! flowEntry.flowEntryActions().isEmpty()) {
-                flowEntryEntity.setProperty("actions", flowEntry.flowEntryActions().toString());
-	    }
-
-            flowEntryEntity.setProperty("switch_state", flowEntry.flowEntrySwitchState().toString());
-            if (updateFlowEntry) {
-               flowEntryEntity.operationEnd(DBOperationType.UPDATE.toString());
-            } else {
-               flowEntryEntity.operationEnd(DBOperationType.ADD.toString());
-            }
-            flowPathEntity.append(flowEntryEntity);
-	}
-	
-        if (flowPathUpdate) {
-            flowPathEntity.operationEnd(DBOperationType.UPDATE.toString());
-        } else {
-            flowPathEntity.operationEnd(DBOperationType.ADD.toString());
-        }
-        flowPathEntity.persist(dbHandler);
-	return true;
-    }
-    
-    /**
-     * Add a flow.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowPath the Flow Path to install.
-     * @return true on success, otherwise false.
-     */
-    static boolean addFlow(DBOperation dbHandler, FlowPath flowPath) {
-        PerfMon pm = PerfMon.getInstance();
-        pm.addflowpath_start();
-        boolean retValue = addFlowFast(dbHandler, flowPath);
-        pm.addflowpath_end();
-        return retValue;
-    }
-
-    /**
-     * Add a flow entry to the Network MAP.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowObj the corresponding Flow Path object for the Flow Entry.
-     * @param flowEntry the Flow Entry to install.
-     * @return the added Flow Entry object on success, otherwise null.
-     */
-    static IFlowEntry addFlowEntry(DBOperation dbHandler,
-				   IFlowPath flowObj,
-				   FlowEntry flowEntry) {
-	// Flow edges
-	//   HeadFE (TODO)
-	long startAddFlowEntry = 0;
-	long endAddFlowEntry = 0;
-
-	long endSearchFlowEntry = 0;
-
-	long startCreateNewFlowEntry = 0;
-	long endCreateNewFlowEntry = 0;
-
-	long startSetProperties = 0;
-	long endSetProperties = 0;
-	int numProperties = 0;
-
-	long startSearchSwitch = 0;
-	long endSearchSwitch = 0;
-
-	long startAddEdgeToSwitch =0;
-	long endAddEdgeToSwitch =0;
-
-	long startSearchInPort = 0;
-	long endSearchInPort = 0;
-
-	long startAddEdgeToInPort =0;
-	long endAddEdgeToInPort =0;
-
-	long startSearchOutPort = 0;
-	long endSearchOutPort = 0;
-
-	long startAddEdgeToOutPort =0;
-	long endAddEdgeToOutPort =0;
-
-	long startAddEdgeBetweenFlowPath = 0;
-	long endAddEdgeBetweenFlowPath = 0;
-
-	if (measureONOSFlowEntryTimeProp) {
-		startAddFlowEntry = System.nanoTime();
-	}
-
-	IFlowEntry flowEntryObj = null;
-	boolean found = false;
-	try {
-	    flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
-	    if (measureONOSFlowEntryTimeProp) {
-		endSearchFlowEntry = System.nanoTime();
-	    }
-	    if (flowEntryObj != null) {
-		found = true;
-	    } else {
-		if (measureONOSFlowEntryTimeProp) {
-		    startCreateNewFlowEntry = System.nanoTime();
-		}
-		flowEntryObj = dbHandler.newFlowEntry();
-		if (measureONOSFlowEntryTimeProp) {
-		    endCreateNewFlowEntry = System.nanoTime();
-		}
-	    }
-	} catch (Exception e) {
-	    log.error(":addFlow FlowEntryId:{} failed",
-		      flowEntry.flowEntryId());
-	    return null;
-	}
-	if (flowEntryObj == null) {
-	    log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
-		      flowEntry.flowEntryId());
-	    return null;
-	}
-
-	if (measureONOSFlowEntryTimeProp) {
-	    startSetProperties = System.nanoTime();
-	}
-
-	FlowEntryProperty flowProp = new FlowEntryProperty();
-
-	//
-	// Set the Flow Entry key:
-	// - flowEntry.flowEntryId()
-	//
-	flowProp.setFlowEntryId(flowEntry.flowEntryId().toString());
-	flowProp.setType("flow_entry");
-	if (measureONOSFlowEntryTimeProp) {
-	    numProperties += 2;
-	}
-
-	//
-	// Set the Flow Entry Edges and attributes:
-	// - Switch edge
-	// - InPort edge
-	// - OutPort edge
-	//
-	// - flowEntry.idleTimeout()
-	// - flowEntry.hardTimeout()
-	// - flowEntry.priority()
-	// - flowEntry.dpid()
-	// - flowEntry.flowEntryUserState()
-	// - flowEntry.flowEntrySwitchState()
-	// - flowEntry.flowEntryErrorState()
-	// - flowEntry.matchInPort()
-	// - flowEntry.matchSrcMac()
-	// - flowEntry.matchDstMac()
-	// - flowEntry.matchEthernetFrameType()
-	// - flowEntry.matchVlanId()
-	// - flowEntry.matchVlanPriority()
-	// - flowEntry.matchSrcIPv4Net()
-	// - flowEntry.matchDstIPv4Net()
-	// - flowEntry.matchIpProto()
-	// - flowEntry.matchIpToS()
-	// - flowEntry.matchSrcTcpUdpPort()
-	// - flowEntry.matchDstTcpUdpPort()
-	// - flowEntry.actionOutputPort()
-	// - flowEntry.actions()
-	//
-	if (measureONOSFlowEntryTimeProp) {
-	    startSearchSwitch = System.nanoTime();
-	}
-	ISwitchObject sw = dbHandler.searchSwitch(flowEntry.dpid().toString());
-	if (measureONOSFlowEntryTimeProp) {
-	    endSearchSwitch = System.nanoTime();
-	}
-
-	flowProp.setIdleTimeout(flowEntry.idleTimeout());
-	flowProp.setHardTimeout(flowEntry.hardTimeout());
-	flowProp.setPriority(flowEntry.priority());
-	flowProp.setSwitchDpid(flowEntry.dpid().toString());
-	if (measureONOSFlowEntryTimeProp) {
-	    numProperties += 3;
-	}
-
-	if (measureONOSFlowEntryTimeProp) {
-	    startAddEdgeToSwitch = System.nanoTime();
-	}
-	flowEntryObj.setSwitch(sw);
-	if (measureONOSFlowEntryTimeProp) {
-	    endAddEdgeToSwitch = System.nanoTime();
-	}
-	if (flowEntry.flowEntryMatch().matchInPort()) {
-	    if (measureONOSFlowEntryTimeProp) {
-		startSearchInPort = System.nanoTime();
-	    }
-	    IPortObject inport =
-		    dbHandler.searchPort(flowEntry.dpid().toString(),
-			    flowEntry.flowEntryMatch().inPort().value());
-	    if (measureONOSFlowEntryTimeProp) {
-		endSearchInPort = System.nanoTime();
-	    }
-
-	    flowProp.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-
-	    if (measureONOSFlowEntryTimeProp) {
-		startAddEdgeToInPort = System.nanoTime();
-	    }
-	    flowEntryObj.setInPort(inport);
-	    if (measureONOSFlowEntryTimeProp) {
-		endAddEdgeToInPort = System.nanoTime();
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchSrcMac()) {
-		flowProp.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchDstMac()) {
-		flowProp.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
-		flowProp.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchVlanId()) {
-		flowProp.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchVlanPriority()) {
-		flowProp.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
-		flowProp.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
-		flowProp.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchIpProto()) {
-		flowProp.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchIpToS()) {
-		flowProp.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
-		flowProp.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-	if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
-		flowProp.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-
-	for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
-	    if (fa.actionOutput() != null) {
-		if (measureONOSFlowEntryTimeProp) {
-		    if ( startSearchOutPort != 0 ) log.error("Performance addFlowEntry(_,{},{}) -- Multiple output port action unexpected.", flowEntry.flowId(), flowEntry.flowEntryId());
-		    startSearchOutPort = System.nanoTime();
-		}
-		IPortObject outport =
-			dbHandler.searchPort(flowEntry.dpid().toString(),
-				fa.actionOutput().port().value());
-		if (measureONOSFlowEntryTimeProp) {
-		    endSearchOutPort = System.nanoTime();
-		}
-
-		flowProp.setActionOutputPort(fa.actionOutput().port().value());
-		if (measureONOSFlowEntryTimeProp) {
-		    ++numProperties;
-		}
-
-		if (measureONOSFlowEntryTimeProp) {
-		    startAddEdgeToOutPort = System.nanoTime();
-		}
-		flowEntryObj.setOutPort(outport);
-		if (measureONOSFlowEntryTimeProp) {
-		    endAddEdgeToOutPort = System.nanoTime();
-		}
-	    }
-	}
-	if (! flowEntry.flowEntryActions().isEmpty()) {
-		flowProp.setActions(flowEntry.flowEntryActions().toString());
-	    if (measureONOSFlowEntryTimeProp) {
-		++numProperties;
-	    }
-	}
-
-	flowProp.setUserState(flowEntry.flowEntryUserState().toString());
-	flowProp.setSwitchState(flowEntry.flowEntrySwitchState().toString());
-	if (measureONOSFlowEntryTimeProp) {
-	    numProperties += 2;
-	}
-	flowProp.commitProperties(dbHandler, flowEntryObj);
-	//
-	// TODO: Take care of the FlowEntryErrorState.
-	//
-	if (measureONOSFlowEntryTimeProp) {
-	    endSetProperties = System.nanoTime();
-	}
-
-	// Flow Entries edges:
-	//   Flow
-	//   NextFE (TODO)
-	if (! found) {
-	    if (measureONOSFlowEntryTimeProp) {
-		startAddEdgeBetweenFlowPath = System.nanoTime();
-	    }
-	    //flowObj.addFlowEntry(flowEntryObj);
-	    flowEntryObj.setFlow(flowObj);
-	    if (measureONOSFlowEntryTimeProp) {
-		endAddEdgeBetweenFlowPath = System.nanoTime();
-	    }
-	}
-	if (measureONOSFlowEntryTimeProp) {
-	    endAddFlowEntry = System.nanoTime();
-
-	    log.error("Performance addFlowEntry(_,{},{}) -- "
-		    + "GrandTotal: {} "
-		    + "SearchExistingFE: {} "
-		    + "CreateNewFE: {} "
-		    + "SetProp+Edge: {} #Props: {} "
-		    + "SearchSwitch: {} "
-		    + "AddEdgeToSwitch: {} "
-		    + "SearchInPort: {} "
-		    + "AddEdgeToInPort: {} "
-		    + "SearchOutPort: {} "
-		    + "AddEdgeToOutPort: {} "
-		    + "AddEdgeBetweenFlowPath: {} "
-		    , flowEntry.flowId(), flowEntry.flowEntryId()
-		    , endAddFlowEntry - startAddFlowEntry
-		    , endSearchFlowEntry - startAddFlowEntry
-		    , endCreateNewFlowEntry - startCreateNewFlowEntry
-		    , endSetProperties - startSetProperties, numProperties
-		    , endSearchSwitch - startSearchSwitch
-		    , endAddEdgeToSwitch - startAddEdgeToSwitch
-		    , endSearchInPort - startSearchInPort
-		    , endAddEdgeToInPort - startAddEdgeToInPort
-		    , endSearchOutPort - startSearchOutPort
-		    , endAddEdgeToOutPort - startAddEdgeToOutPort
-		    , endAddEdgeBetweenFlowPath - startAddEdgeBetweenFlowPath
-		    );
-	}
-
-	return flowEntryObj;
-    }
-
-    /**
-     * Delete a flow entry from the Network MAP.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowObj the corresponding Flow Path object for the Flow Entry.
-     * @param flowEntry the Flow Entry to delete.
-     * @return true on success, otherwise false.
-     */
-    static boolean deleteFlowEntry(DBOperation dbHandler,
-				   IFlowPath flowObj,
-				   FlowEntry flowEntry) {
-	IFlowEntry flowEntryObj = null;
-	try {
-	    flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
-	} catch (Exception e) {
-	    log.error(":deleteFlowEntry FlowEntryId:{} failed",
-		      flowEntry.flowEntryId());
-	    return false;
-	}
-	//
-	// TODO: Don't print an error for now, because multiple controller
-	// instances might be deleting the same flow entry.
-	//
-	/*
-	if (flowEntryObj == null) {
-	    log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
-		      flowEntry.flowEntryId());
-	    return false;
-	}
-	*/
-	if (flowEntryObj == null)
-	    return true;
-
-	flowObj.removeFlowEntry(flowEntryObj);
-	dbHandler.removeFlowEntry(flowEntryObj);
-	return true;
-    }
-
-    /**
-     * Delete all previously added flows.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @return true on success, otherwise false.
-     */
-    static boolean deleteAllFlows(DBOperation dbHandler) {
-	try {
-	    // Get all Flow IDs
-	    Iterable<IFlowPath> allFlowPaths = dbHandler.getAllFlowPaths();
-	    for (IFlowPath flowPathObj : allFlowPaths) {
-		if (flowPathObj == null)
-		    continue;
-
-		deleteIFlowPath(dbHandler, flowPathObj);
-	    }
-	    dbHandler.commit();
-	} catch (Exception e) {
-	    log.error("Exception deleting all Flow Paths from Network MAP: ", e);
-	    return false;
-	}
-
-	return true;
-    }
-
-    /**
-     * Delete a previously added flow.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowId the Flow ID of the flow to delete.
-     * @return true on success, otherwise false.
-     */
-    static boolean deleteFlow(DBOperation dbHandler, FlowId flowId) {
-	IFlowPath flowObj = null;
-	try {
-	    flowObj = dbHandler.searchFlowPath(flowId);
-	} catch (Exception e) {
-	    // TODO: handle exceptions
-	    dbHandler.rollback();
-	    log.error(":deleteFlow FlowId:{} failed", flowId);
-	    return false;
-	}
-	if (flowObj == null) {
-	    dbHandler.commit();
-	    return true;		// OK: No such flow
-	}
-
-	deleteIFlowPath(dbHandler, flowObj);
-	dbHandler.commit();
-	return true;
-    }
-
-    /**
-     * Delete a previously added flow.
-     * @note You need to call commit after calling this method.
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowObj IFlowPath object to delete.
-     */
-    private static void deleteIFlowPath(DBOperation dbHandler, IFlowPath flowObj) {
-	//
-	// Remove all Flow Entries
-	//
-	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
-	for (IFlowEntry flowEntryObj : flowEntries) {
-	    flowObj.removeFlowEntry(flowEntryObj);
-	    dbHandler.removeFlowEntry(flowEntryObj);
-	}
-	// Remove the Flow itself
-	dbHandler.removeFlowPath(flowObj);
-    }
-
-    /**
-     * Get a previously added flow.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowId the Flow ID of the flow to get.
-     * @return the Flow Path if found, otherwise null.
-     */
-    static FlowPath getFlow(DBOperation dbHandler, FlowId flowId) {
-	IFlowPath flowObj = null;
-	try {
-	    flowObj = dbHandler.searchFlowPath(flowId);
-	} catch (Exception e) {
-	    // TODO: handle exceptions
-	    dbHandler.rollback();
-	    log.error(":getFlow FlowId:{} failed", flowId);
-	    return null;
-	}
-	if (flowObj == null) {
-	    dbHandler.commit();
-	    return null;		// Flow not found
-	}
-
-	//
-	// Extract the Flow state
-	//
-	FlowPath flowPath = extractFlowPath(flowObj);
-	dbHandler.commit();
-
-	return flowPath;
-    }
-
-    /**
-     * Get a previously added flow entry.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowEntryId the Flow Entry ID of the flow entry to get.
-     * @return the Flow Entry if found, otherwise null.
-     */
-    static FlowEntry getFlowEntry(DBOperation dbHandler,
-				  FlowEntryId flowEntryId) {
-	IFlowEntry flowEntryObj = null;
-	try {
-	    flowEntryObj = dbHandler.searchFlowEntry(flowEntryId);
-	} catch (Exception e) {
-	    // TODO: handle exceptions
-	    dbHandler.rollback();
-	    log.error(":getFlowEntry FlowEntryId:{} failed", flowEntryId);
-	    return null;
-	}
-	if (flowEntryObj == null) {
-	    dbHandler.commit();
-	    return null;		// Flow not found
-	}
-
-	//
-	// Extract the Flow Entry state
-	//
-	FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
-	dbHandler.commit();
-
-	return flowEntry;
-    }
-
-    /**
-     * Get the source switch DPID of a previously added flow.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowId the Flow ID of the flow to get.
-     * @return the source switch DPID if found, otherwise null.
-     */
-    static Dpid getFlowSourceDpid(DBOperation dbHandler, FlowId flowId) {
-	IFlowPath flowObj = null;
-	try {
-	    flowObj = dbHandler.searchFlowPath(flowId);
-	} catch (Exception e) {
-	    // TODO: handle exceptions
-	    dbHandler.rollback();
-	    log.error(":getFlowSourceDpid FlowId:{} failed", flowId);
-	    return null;
-	}
-	if (flowObj == null) {
-	    dbHandler.commit();
-	    return null;		// Flow not found
-	}
-
-	//
-	// Extract the Flow Source DPID
-	//
-	String srcSwitchStr = flowObj.getSrcSwitch();
-	if (srcSwitchStr == null) {
-	    // TODO: A work-around, becauuse of some bogus database objects
-	    dbHandler.commit();
-	    return null;
-	}
-
-	Dpid dpid = new Dpid(srcSwitchStr);
-
-	dbHandler.commit();
-
-	return dpid;
-    }
-
-    /**
-     * Get all installed flows by all installers.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @return the Flow Paths if found, otherwise null.
-     */
-    static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler) {
-	Iterable<IFlowPath> flowPathsObj = null;
-	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
-	try {
-	    flowPathsObj = dbHandler.getAllFlowPaths();
-	} catch (Exception e) {
-	    // TODO: handle exceptions
-	    dbHandler.rollback();
-	    log.error(":getAllFlowPaths failed");
-	    return flowPaths;
-	}
-	if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
-	    dbHandler.commit();
-	    return flowPaths;	// No Flows found
-	}
-
-	for (IFlowPath flowObj : flowPathsObj) {
-	    //
-	    // Extract the Flow state
-	    //
-	    FlowPath flowPath = extractFlowPath(flowObj);
-	    if (flowPath != null)
-		flowPaths.add(flowPath);
-	}
-
-	dbHandler.commit();
-
-	return flowPaths;
-    }
-
-    /**
-     * Get all installed flows whose Source Switch is controlled by this
-     * instance.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param mySwitches the collection of the switches controlled by this
-     * instance.
-     * @return the Flow Paths if found, otherwise null.
-     */
-    static ArrayList<FlowPath> getAllMyFlows(DBOperation dbHandler,
-					     Map<Long, IOFSwitch> mySwitches) {
-	Iterable<IFlowPath> flowPathsObj = null;
-	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
-	try {
-	    flowPathsObj = dbHandler.getAllFlowPaths();
-	} catch (Exception e) {
-	    // TODO: handle exceptions
-	    dbHandler.rollback();
-	    log.error(":getAllMyFlowPaths failed");
-	    return flowPaths;
-	}
-	if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
-	    dbHandler.commit();
-	    return flowPaths;	// No Flows found
-	}
-
-	for (IFlowPath flowObj : flowPathsObj) {
-	    //
-	    // Extract the Source Switch DPID and ignore if the switch
-	    // is not controlled by this instance.
-	    //
-	    String srcSwitchStr = flowObj.getSrcSwitch();
-	    if (srcSwitchStr == null) {
-		// TODO: A work-around, becauuse of some bogus database objects
-		continue;
-	    }
-	    Dpid dpid = new Dpid(srcSwitchStr);
-	    if (mySwitches.get(dpid.value()) == null)
-		continue;
-
-	    //
-	    // Extract the Flow state
-	    //
-	    FlowPath flowPath = extractFlowPath(flowObj);
-	    if (flowPath != null)
-		flowPaths.add(flowPath);
-	}
-
-	dbHandler.commit();
-
-	return flowPaths;
-    }
-
-    /**
-     * Get a subset of installed flows.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowIds the collection of Flow IDs to get.
-     * @return the Flow Paths if found, otherwise null.
-     */
-    static ArrayList<FlowPath> getFlows(DBOperation dbHandler,
-					Collection<FlowId> flowIds) {
-	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
-	// TODO: This implementation should use threads
-	for (FlowId flowId : flowIds) {
-	    FlowPath flowPath = getFlow(dbHandler, flowId);
-	    if (flowPath != null)
-		flowPaths.add(flowPath);
-	}
-	// dbHandler.commit();
-
-	return flowPaths;
-    }
-
-    /**
-     * Extract Flow Path State from a Titan Database Object @ref IFlowPath.
-     *
-     * @param flowObj the object to extract the Flow Path State from.
-     * @return the extracted Flow Path State.
-     */
-    static FlowPath extractFlowPath(IFlowPath flowObj) {
-	//
-	// Extract the Flow state
-	//
-    log.info("extractFlowPath: start");
-	String flowIdStr;
-	String installerIdStr;
-	String flowPathType;
-	String flowPathUserState;
-	Long flowPathFlags;
-	Integer idleTimeout;
-	Integer hardTimeout;
-	Integer priority;
-	String srcSwitchStr;
-	Short srcPortShort;
-	String dstSwitchStr;
-	Short dstPortShort;
-
-	if ( flowObj.asVertex() instanceof RamCloudVertex ) {
-	    RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
-	    Map<String,Object> propMap = v.getProperties();
-
-	    flowIdStr = (String) propMap.get("flow_id");
-	    installerIdStr = (String) propMap.get("installer_id");
-	    flowPathType = (String) propMap.get("flow_path_type");
-	    flowPathUserState = (String) propMap.get("user_state");
-	    flowPathFlags = (Long)propMap.get("flow_path_flags");
-	    idleTimeout = (Integer) propMap.get("idle_timeout");
-	    hardTimeout = (Integer) propMap.get("hard_timeout");
-	    priority = (Integer) propMap.get("priority");
-	    srcSwitchStr = (String) propMap.get("src_switch");
-	    srcPortShort = (Short)propMap.get("src_port");
-	    dstSwitchStr = (String) propMap.get("dst_switch");
-	    dstPortShort = (Short)propMap.get("dst_port");
-	} else {
-	    flowIdStr = flowObj.getFlowId();
-	    installerIdStr = flowObj.getInstallerId();
-	    flowPathType = flowObj.getFlowPathType();
-	    flowPathUserState = flowObj.getFlowPathUserState();
-	    flowPathFlags = flowObj.getFlowPathFlags();
-	    idleTimeout = flowObj.getIdleTimeout();
-	    hardTimeout = flowObj.getHardTimeout();
-	    priority = flowObj.getPriority();
-	    srcSwitchStr = flowObj.getSrcSwitch();
-	    srcPortShort = flowObj.getSrcPort();
-	    dstSwitchStr = flowObj.getDstSwitch();
-	    dstPortShort = flowObj.getDstPort();
-	}
-
-	if ((flowIdStr == null) ||
-	    (installerIdStr == null) ||
-	    (flowPathType == null) ||
-	    (flowPathUserState == null) ||
-	    (flowPathFlags == null) ||
-	    (idleTimeout == null) ||
-	    (hardTimeout == null) ||
-	    (priority == null) ||
-	    (srcSwitchStr == null) ||
-	    (srcPortShort == null) ||
-	    (dstSwitchStr == null) ||
-	    (dstPortShort == null)) {
-	    // TODO: A work-around, because of some bogus database objects
-	    log.error("extractFlowPath: wrong properties");
-	    return null;
-	}
-
-	FlowPath flowPath = new FlowPath();
-	flowPath.setFlowId(new FlowId(flowIdStr));
-	flowPath.setInstallerId(new CallerId(installerIdStr));
-	flowPath.setFlowPathType(FlowPathType.valueOf(flowPathType));
-	flowPath.setFlowPathUserState(FlowPathUserState.valueOf(flowPathUserState));
-	flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
-	flowPath.setIdleTimeout(idleTimeout);
-	flowPath.setHardTimeout(hardTimeout);
-	flowPath.setPriority(priority);
-	flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
-	flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
-	flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
-	flowPath.dataPath().dstPort().setPort(new Port(dstPortShort));
-	//
-	// Extract the match conditions common for all Flow Entries
-	//
-	{
-	    FlowEntryMatch match = extractMatch(flowObj);
-
-	    flowPath.setFlowEntryMatch(match);
-	}
-	//
-	// Extract the actions for the first Flow Entry
-	//
-	{
-	    String actionsStr = flowObj.getActions();
-	    if (actionsStr != null) {
-		FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
-		flowPath.setFlowEntryActions(flowEntryActions);
-	    }
-	}
-
-	//
-	// Extract all Flow Entries
-	//
-	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
-	for (IFlowEntry flowEntryObj : flowEntries) {
-	    FlowEntry flowEntry = extractFlowEntry(flowEntryObj);
-	    if (flowEntry == null)
-		continue;
-	    flowPath.dataPath().flowEntries().add(flowEntry);
-	}
-
-    log.info("extractFlowPath: end");
-	return flowPath;
-    }
-
-    /**
-     * Extract Flow Entry State from a Titan Database Object @ref IFlowEntry.
-     *
-     * @param flowEntryObj the object to extract the Flow Entry State from.
-     * @return the extracted Flow Entry State.
-     */
-    public static FlowEntry extractFlowEntry(IFlowEntry flowEntryObj) {
-	log.info("extractFlowEntry: start");
-	IFlowPath flowObj = flowEntryObj.getFlow();
-	if (flowObj == null) {
-		log.error("extractFlowEntry: no flowPath exists");
-	    return null;
-	}
-
-	String flowIdStr = flowObj.getFlowId();
-	//
-	String flowEntryIdStr;
-	Integer idleTimeout;
-	Integer hardTimeout;
-	Integer priority;
-	String switchDpidStr;
-	String userState;
-	String switchState;
-	if ( flowEntryObj.asVertex() instanceof RamCloudVertex ) {
-	    RamCloudVertex v = (RamCloudVertex)flowEntryObj.asVertex();
-	    Map<String,Object> propMap = v.getProperties();
-
-	    flowEntryIdStr = (String) propMap.get("flow_entry_id");
-	    idleTimeout = (Integer) propMap.get("idle_timeout");
-	    hardTimeout = (Integer) propMap.get("hard_timeout");
-	    priority = (Integer) propMap.get("priority");
-	    switchDpidStr = (String) propMap.get("switch_dpid");
-	    userState = (String) propMap.get("user_state");
-	    switchState = (String) propMap.get("switch_state");
-	} else {
-	    flowEntryIdStr = flowEntryObj.getFlowEntryId();
-	    idleTimeout = flowEntryObj.getIdleTimeout();
-	    hardTimeout = flowEntryObj.getHardTimeout();
-	    priority = flowEntryObj.getPriority();
-	    switchDpidStr = flowEntryObj.getSwitchDpid();
-	    userState = flowEntryObj.getUserState();
-	    switchState = flowEntryObj.getSwitchState();
-	}
-
-	if ((flowIdStr == null) ||
-	    (flowEntryIdStr == null) ||
-	    (idleTimeout == null) ||
-	    (hardTimeout == null) ||
-	    (priority == null) ||
-	    (switchDpidStr == null) ||
-	    (userState == null) ||
-	    (switchState == null)) {
-	    // TODO: A work-around, because of some bogus database objects
-		log.error("extractFlowEntry: wrong properties");
-	    return null;
-	}
-
-	FlowEntry flowEntry = new FlowEntry();
-	flowEntry.setFlowEntryId(new FlowEntryId(flowEntryIdStr));
-	flowEntry.setFlowId(new FlowId(flowIdStr));
-	flowEntry.setDpid(new Dpid(switchDpidStr));
-	flowEntry.setIdleTimeout(idleTimeout);
-	flowEntry.setHardTimeout(hardTimeout);
-	flowEntry.setPriority(priority);
-
-	//
-	// Extract the match conditions
-	//
-	FlowEntryMatch match = extractMatch(flowEntryObj);
-	flowEntry.setFlowEntryMatch(match);
-
-	//
-	// Extract the actions
-	//
-	FlowEntryActions actions = new FlowEntryActions();
-	String actionsStr = flowEntryObj.getActions();
-	if (actionsStr != null)
-	    actions = new FlowEntryActions(actionsStr);
-	flowEntry.setFlowEntryActions(actions);
-	flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
-	flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
-	//
-	// TODO: Take care of FlowEntryErrorState.
-	//
-	log.info("extractFlowEntry: end");
-	return flowEntry;
-    }
-
-    /**
-     * Extract FlowEntryMatch from IFlowPath or IFlowEntry
-     * @param flowObj : either IFlowPath or IFlowEntry
-     * @return extracted Match info
-     */
-    private static FlowEntryMatch extractMatch(IBaseObject flowObj) {
-	FlowEntryMatch match = new FlowEntryMatch();
-
-	Short matchInPort = null; // Only for IFlowEntry
-	String matchSrcMac = null;
-	String matchDstMac = null;
-	Short matchEthernetFrameType = null;
-	Short matchVlanId = null;
-	Byte matchVlanPriority = null;
-	String matchSrcIPv4Net = null;
-	String matchDstIPv4Net = null;
-	Byte matchIpProto = null;
-	Byte matchIpToS = null;
-	Short matchSrcTcpUdpPort = null;
-	Short matchDstTcpUdpPort = null;
-
-	if ( flowObj.asVertex() instanceof RamCloudVertex ) {
-	    RamCloudVertex v = (RamCloudVertex)flowObj.asVertex();
-	    Map<String,Object> propMap = v.getProperties();
-	    matchInPort = (Short) propMap.get("matchInPort");
-	    matchSrcMac = (String) propMap.get("matchSrcMac");
-	    matchDstMac = (String) propMap.get("matchDstMac");
-	    matchEthernetFrameType = (Short) propMap.get("matchEthernetFrameType");
-	    matchVlanId = (Short) propMap.get("matchVlanId");
-	    matchVlanPriority = (Byte) propMap.get("matchVlanPriority");
-	    matchSrcIPv4Net = (String) propMap.get("matchSrcIPv4Net");
-	    matchDstIPv4Net = (String) propMap.get("matchDstIPv4Net");
-	    matchIpProto = (Byte) propMap.get("matchIpProto");
-	    matchIpToS = (Byte) propMap.get("matchIpToS");
-	    matchSrcTcpUdpPort = (Short) propMap.get("matchSrcTcpUdpPort");
-	    matchDstTcpUdpPort = (Short) propMap.get("matchDstTcpUdpPort");
-	} else {
-	    if (flowObj instanceof IFlowEntry ){
-		IFlowEntry flowEntry = (IFlowEntry) flowObj;
-		matchInPort = flowEntry.getMatchInPort();
-		matchSrcMac = flowEntry.getMatchSrcMac();
-		matchDstMac = flowEntry.getMatchDstMac();
-		matchEthernetFrameType = flowEntry.getMatchEthernetFrameType();
-		matchVlanId = flowEntry.getMatchVlanId();
-		matchVlanPriority = flowEntry.getMatchVlanPriority();
-		matchSrcIPv4Net = flowEntry.getMatchSrcIPv4Net();
-		matchDstIPv4Net = flowEntry.getMatchDstIPv4Net();
-		matchIpProto = flowEntry.getMatchIpProto();
-		matchIpToS = flowEntry.getMatchIpToS();
-		matchSrcTcpUdpPort = flowEntry.getMatchSrcTcpUdpPort();
-		matchDstTcpUdpPort = flowEntry.getMatchDstTcpUdpPort();
-	    } else if(flowObj instanceof IFlowPath) {
-		IFlowPath flowPath = (IFlowPath) flowObj;
-		matchSrcMac = flowPath.getMatchSrcMac();
-		matchDstMac = flowPath.getMatchDstMac();
-		matchEthernetFrameType = flowPath.getMatchEthernetFrameType();
-		matchVlanId = flowPath.getMatchVlanId();
-		matchVlanPriority = flowPath.getMatchVlanPriority();
-		matchSrcIPv4Net = flowPath.getMatchSrcIPv4Net();
-		matchDstIPv4Net = flowPath.getMatchDstIPv4Net();
-		matchIpProto = flowPath.getMatchIpProto();
-		matchIpToS = flowPath.getMatchIpToS();
-		matchSrcTcpUdpPort = flowPath.getMatchSrcTcpUdpPort();
-		matchDstTcpUdpPort = flowPath.getMatchDstTcpUdpPort();
-	    }
-	}
-
-	if (matchInPort != null)
-	    match.enableInPort(new Port(matchInPort));
-	if (matchSrcMac != null)
-	    match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
-	if (matchDstMac != null)
-	    match.enableDstMac(MACAddress.valueOf(matchDstMac));
-	if (matchEthernetFrameType != null)
-	    match.enableEthernetFrameType(matchEthernetFrameType);
-	if (matchVlanId != null)
-	    match.enableVlanId(matchVlanId);
-	if (matchVlanPriority != null)
-	    match.enableVlanPriority(matchVlanPriority);
-	if (matchSrcIPv4Net != null)
-	    match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
-	if (matchDstIPv4Net != null)
-	    match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
-	if (matchIpProto != null)
-	    match.enableIpProto(matchIpProto);
-	if (matchIpToS != null)
-	    match.enableIpToS(matchIpToS);
-	if (matchSrcTcpUdpPort != null)
-	    match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
-	if (matchDstTcpUdpPort != null)
-	    match.enableDstTcpUdpPort(matchDstTcpUdpPort);
-	return match;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntity.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntity.java
deleted file mode 100644
index 327fae5..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntity.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.blueprints.Edge;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IBaseObject;
-import com.tinkerpop.blueprints.impls.ramcloud.RamCloudGraph;
-import com.tinkerpop.blueprints.impls.ramcloud.RamCloudVertex;
-import java.util.List;
-import java.util.Set;
-
-public class FlowEntity implements FlowEntityManager {
-    private String primaryKey;
-    // TODO: Should remove since not implemented.
-    private Class<?> hasMany;
-    private Collection<?> many = new ArrayList<>();
-    private Map<String, Object> properties;
-    private Map<String, Map<String, Object>> operations = new HashMap<>();
-    private ArrayList<Object> children = new ArrayList<>();
-    private ArrayList<Object> edges = new ArrayList<>();
-    private int opCount;
-    public Direction dir;
-
-    public FlowEntity() {
-        opCount = 0;
-    }
-    
-    private class EntityEdge {
-        private Object src;
-        private Object dst;
-        private Direction dir;
-        private String label;
-        private DBOperationType op;
-        
-        public EntityEdge(Object src, Object dst, DBOperationType op, Direction dir, String label) {
-            this.src = src;
-            this.dst = dst;
-            this.dir = dir;
-            this.label = label;
-            this.op = op;
-        }
-        
-        public EntityEdge(Object src, Object dst, String label) {
-            this.src = src;
-            this.dst = dst;
-            this.label = label;
-        }
-        
-        @Override
-        public String toString() {
-            return "EntityEdge: " + src + " " + dst + " " + label;
-        }
-    }
-
-    private class RamCloudEdgeEntity implements Edge {
-        private Vertex src;
-        private Vertex dst;
-        private Direction direction;
-        private String label;
-
-        public RamCloudEdgeEntity(Vertex src, Vertex dst, Direction direction, String label) {
-            this.src = src;
-            this.dst = dst;
-            this.direction = direction;
-            this.label = label;
-        }
-        
-        @Override
-        public Vertex getVertex(com.tinkerpop.blueprints.Direction dir) throws IllegalArgumentException {
-            if (dir == Direction.IN) {
-                return dst;
-            } else if (dir == Direction.OUT) {
-                return src;
-            }
-            return null;
-        }
-
-        @Override
-        public String getLabel() {
-            return this.label;
-        }
-
-        @Override
-        public <T> T getProperty(String key) {
-            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-        }
-
-        @Override
-        public Set<String> getPropertyKeys() {
-            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-        }
-
-        @Override
-        public void setProperty(String key, Object value) {
-            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-        }
-
-        @Override
-        public <T> T removeProperty(String key) {
-            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-        }
-
-        @Override
-        public Object getId() {
-            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
-        }
-        
-    }
-    
-    @Override
-    public void setPrimaryKey(String key) {
-        primaryKey = key;
-    }
-    
-    @Override
-    public String getPrimaryKey() {
-        return primaryKey;
-    }
-
-    @Override
-    public void hasMany(Class<?> cClass) {
-        hasMany = cClass;
-    }
-    
-    @Override
-    public void operationBegin(String opName) {
-        properties = new HashMap<>();
-        operations.put(getOpKey(opName), properties);
-        opCount++;
-    }
-    
-    @Override
-    public void operationEnd(String opName) {
-        // TODO: This method is implemented in case we need to reset any variables.
-        /*
-        String opKey = getOpKey(opName);
-        if (operations.containsKey(opKey)) {
-            System.out.println(operations);
-        }
-        */
-    }
-    
-    
-    private String getOpKey(String opName) {
-        return opName + new Integer(opCount).toString();
-        
-    }
-
-    @Override
-    public void setProperty(String propertyName, Object value) {
-        properties.put(propertyName, value);
-    }
-
-    @Override
-    public FlowEntityManager append(Object entity) {
-        children.add(entity);
-        return this;
-    }
-    
-    @Override
-    public Object getProperty(String propertyName) {
-        if (properties.containsKey(propertyName)) {
-            return properties.get(propertyName);
-        }
-        return null;
-    }
-    
-    @Override
-    public void persist(DBOperation dbHandler) {
-        // get a hold of all the flow entries for the current flowpath.
-        if (children.size() > 0) {
-            int noOfChildren = children.size();
-            if (noOfChildren > 0) {
-                // construct a list of null ids for creating vertices for all
-                // flow entries.
-                ArrayList<Object> ids = new ArrayList<>(noOfChildren);
-                // set properties
-                Map<RamCloudVertex, Map<String, Object>> propertiesToSet = new HashMap<>();
-                
-                RamCloudGraph graph = (RamCloudGraph)dbHandler.getDBConnection().getFramedGraph().getBaseGraph();
-                for (int i = 0; i < noOfChildren; i++) {
-                    ids.add(null);
-                }
-                List<RamCloudVertex> addedVertices = graph.addVertices(ids);
-                //Iterable<Vertex> vertices = dbHandler.setVertices(ids);
-                //Iterator vi = vertices.iterator();
-                // get source and destination edge match vertex v construct list
-                // of edges
-                ArrayList<Edge> edgesToSet = new ArrayList<>();
-                for (int i = 0; i < noOfChildren; i++) {
-                    FlowEntity childEntity = (FlowEntity)children.get(i);
-                    Vertex srcVertex = addedVertices.get(i);                    
-                    propertiesToSet.put((RamCloudVertex)srcVertex, childEntity.properties);
-
-                    if (srcVertex == null) continue;
-                    for (int j = 0; j < childEntity.edges.size(); j++) {
-                        EntityEdge edge = (EntityEdge) childEntity.edges.get(j);
-                        if (edge !=null) {
-                            edgesToSet.add(new RamCloudEdgeEntity(srcVertex, ((IBaseObject) edge.dst).asVertex(), edge.dir, edge.label));
-                        }
-                    }
-                }
-                graph.addEdges(edgesToSet);
-                graph.setProperties(propertiesToSet);
-            }
-        }
-    }
-
-    private Vertex getVertexEdge(Iterator vi, int idx) {
-        int i = 0;
-        while (vi.hasNext()) {
-            Vertex v = (Vertex)vi.next();
-            if (i == idx) {
-                return v;
-            }
-            i++;
-        }
-        return null;
-    }
-    
-    @Override
-    public Map<String, Object> getProperties() {
-        return properties;
-    }
-    
-    @Override
-    public void addEdge(Object dst, Direction dir, String label) {
-        edges.add(new EntityEdge(this, dst, DBOperationType.ADD, dir, label));
-    }
-    
-    @Override
-    public void removeEdge(Object src, Object dst, Direction dir, String label) {
-        edges.add(new EntityEdge(src, dst, DBOperationType.REMOVE, dir, label));
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntityManager.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntityManager.java
deleted file mode 100644
index 5e45ee5..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntityManager.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import com.tinkerpop.blueprints.Direction;
-import java.util.Map;
-import net.onrc.onos.graph.DBOperation;
-
-public interface FlowEntityManager {
-    public void setPrimaryKey(String key);
-    public String getPrimaryKey();
-    public void hasMany(Class<?> cClass);
-    public void operationBegin(String opName);
-    public void operationEnd(String opName);
-    public void setProperty(String propertyName, Object value);
-    public Object getProperty(String propertyName);
-    public Map<String, Object> getProperties();
-    public FlowEntityManager append(Object entity);
-    public void addEdge(Object dst, Direction dir, String label);
-    public void removeEdge(Object src, Object dst, Direction dir, String label);
-    public void persist(DBOperation dbHandler);
-}
-
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntryProperty.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntryProperty.java
deleted file mode 100644
index 5ef1243..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEntryProperty.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
-
-public class FlowEntryProperty {
-    private Map<String, Object> map = new HashMap<>();
-    
-    public void setFlowId(String value) {
-        map.put("flow_id", value);
-    }
-    
-    public void setUserState(String value) {
-        map.put("user_state", value);
-    }
-    
-    public void setFlowEntryId(String value) {
-        map.put("flow_entry_id", value);
-    }
-    
-    public void setType(String value) {
-        map.put("type", value);
-    }
-    
-    public void setInstallerId(String value) {
-        map.put("installer_id", value);
-    }
-    
-    public void setFlowPathType(String value) {
-        map.put("flow_path_type", value);
-    }
-    
-    public void setFlowPathUserState(String value) {
-        map.put("user_state", value);
-    }
-    
-    public void flow_path_flags(Long value) {
-        map.put("flow_path_flags", value);
-    }
-    
-    public void setIdleTimeout(Integer value) {
-        map.put("idle_timeout", value);
-    }
-    
-    public void setHardTimeout(Integer value) {
-        map.put("hard_timeout", value);
-    }
-
-    public void setPriority(Integer value) {
-        map.put("priority", value);
-    }
-    
-    public void setSwitchDpid(String value) {
-        map.put("switch_dpid", value);
-    }
-    
-    public void setSwitchState(String value) {
-        map.put("switch_state", value);
-    }
-    
-    public void setSrcSwitch(String value) {
-        map.put("src_switch", value);
-    }
-    
-    public void setSrcPort(Short value) {
-        map.put("src_port", value);
-    }
-    
-    public void setDstSwitch(String value) {
-        map.put("dst_switch", value);
-    }
-    
-    public void setDstPort(Short value) {
-        map.put("dst_port", value);
-    }
-    
-    public void setMatchSrcMac(String value) {
-        map.put("matchSrcMac", value);
-    }
-    
-    public void setMatchDstMac(String value) {
-        map.put("matchDstMac", value);
-    }
-    
-    public void setMatchEthernetFrameType(Short value) {
-        map.put("matchEthernetFrameType", value);
-    }
-    
-    public void setMatchVlanId(Short value) {
-        map.put("matchVlanId", value);
-    }
-    
-    public void setMatchVlanPriority(Byte value) {
-        map.put("matchVlanPriority", value);
-    }
-    
-    public void setMatchSrcIPv4Net(String value) {
-        map.put("matchSrcIPv4Net", value);
-    }
-    
-    public void setMatchDstIPv4Net(String value) {
-        map.put("matchDstIPv4Net", value);
-    }
-    
-    public void setMatchIpProto(Byte value) {
-        map.put("matchIpProto", value);
-    }
-    
-    public void setMatchIpToS(Byte value) {
-        map.put("matchIpToS", value);
-    }
-    
-    public void setMatchInPort(Short value) {
-        map.put("matchInPort", value);
-    }
-    
-    public void setMatchSrcTcpUdpPort(Short value) {
-        map.put("matchSrcTcpUdpPort", value);
-    }
-    
-    public void setMatchDstTcpUdpPort(Short value) {
-        map.put("matchDstTcpUdpPort", value);
-    }
-    
-    public void setActions(String value) {
-        map.put("actions", value);
-    }
-    
-    public void setActionOutputPort(Short value) {
-        map.put("actionOutputPort", value);
-    }
-    
-    /**
-     *
-     * @param dbhandler
-     */
-    public void commitProperties(DBOperation dbhandler, IFlowEntry flowEntry) {
-        dbhandler.setVertexProperties(flowEntry.asVertex(), map);
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
deleted file mode 100644
index 4c2bdf8..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
+++ /dev/null
@@ -1,1699 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.IOFSwitchListener;
-import net.onrc.onos.datagrid.IDatagridService;
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.graph.GraphDBManager;
-import net.onrc.onos.ofcontroller.topology.Topology;
-import net.onrc.onos.ofcontroller.topology.TopologyElement;
-import net.onrc.onos.ofcontroller.topology.TopologyManager;
-import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.EventEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntryAction;
-import net.onrc.onos.ofcontroller.util.FlowEntryActions;
-import net.onrc.onos.ofcontroller.util.FlowEntryId;
-import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
-import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
-import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.FlowPathUserState;
-import net.onrc.onos.ofcontroller.util.Pair;
-import net.onrc.onos.ofcontroller.util.PerformanceMonitor;
-import net.onrc.onos.ofcontroller.util.Port;
-import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
-import net.onrc.onos.registry.controller.IControllerRegistryService;
-
-import com.esotericsoftware.kryo.Kryo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Class for FlowPath Maintenance.
- * This class listens for FlowEvents to:
- * - Maintain a local cache of the Network Topology.
- * - Detect FlowPaths impacted by Topology change.
- * - Recompute impacted FlowPath using cached Topology.
- */
-class FlowEventHandler extends Thread implements IFlowEventHandlerService,
-						 IOFSwitchListener {
-
-    private boolean enableOnrc2014MeasurementsFlows = false;
-    private boolean enableOnrc2014MeasurementsTopology = false;
-
-    /** The logger. */
-    private final static Logger log = LoggerFactory.getLogger(FlowEventHandler.class);
-    
-    private final int FLOW_IDLE_TIMEOUT_ADDED_SECONDS = 5;
-
-    private DBOperation dbHandler;
-
-    private FlowManager flowManager;		// The Flow Manager to use
-    private IDatagridService datagridService;	// The Datagrid Service to use
-    private IControllerRegistryService registryService; // The Registry Service
-    private Topology topology;			// The network topology
-    private KryoFactory kryoFactory = new KryoFactory();
-
-    // The queue with Flow Path and Topology Element updates
-    private BlockingQueue<EventEntry<?>> networkEvents =
-	new LinkedBlockingQueue<EventEntry<?>>();
-
-    // The pending Topology, FlowPath, and FlowEntry events
-    private List<EventEntry<TopologyElement>> topologyEvents =
-	new LinkedList<EventEntry<TopologyElement>>();
-    private List<EventEntry<FlowPath>> flowPathEvents =
-	new LinkedList<EventEntry<FlowPath>>();
-    private List<EventEntry<FlowEntry>> flowEntryEvents =
-	new LinkedList<EventEntry<FlowEntry>>();
-    private List<EventEntry<Pair<FlowId, Dpid>>> flowIdEvents =
-	new LinkedList<EventEntry<Pair<FlowId, Dpid>>>();
-    private List<EventEntry<Pair<FlowEntryId, Dpid>>> flowEntryIdEvents =
-	new LinkedList<EventEntry<Pair<FlowEntryId, Dpid>>>();
-    private List<EventEntry<Dpid>> switchDpidEvents =
-	new LinkedList<EventEntry<Dpid>>();
-
-    // All internally computed Flow Paths
-    private Map<Long, FlowPath> allFlowPaths = new HashMap<Long, FlowPath>();
-
-    // The Flow Entries received as notifications with unmatched Flow Paths
-    private Map<Long, FlowEntry> unmatchedFlowEntryAdd =
-	new HashMap<Long, FlowEntry>();
-
-    //
-    // Transient state for processing the Flow Paths:
-    //  - The Flow Paths that should be recomputed
-    //  - The Flow Paths with modified Flow Entries
-    //  - The Flow Paths that we should check if installed in all switches
-    //
-    private Map<Long, FlowPath> shouldRecomputeFlowPaths =
-	new HashMap<Long, FlowPath>();
-    private Map<Long, FlowPath> modifiedFlowPaths =
-	new HashMap<Long, FlowPath>();
-    private Map<Long, FlowPath> checkIfInstalledFlowPaths =
-	new HashMap<Long, FlowPath>();
-
-    /**
-     * Constructor for a given Flow Manager and Datagrid Service.
-     *
-     * @param flowManager the Flow Manager to use.
-     * @param datagridService the Datagrid Service to use.
-     * @param registryService the Registry Service to use.
-     */
-    FlowEventHandler(FlowManager flowManager,
-		     IDatagridService datagridService,
-		     IControllerRegistryService registryService) {
-	this.flowManager = flowManager;
-	this.datagridService = datagridService;
-	this.registryService = registryService;
-	this.topology = new Topology();
-    }
-
-    /**
-     * Get the network topology.
-     *
-     * @return the network topology.
-     */
-    protected Topology getTopology() { return this.topology; }
-
-    /**
-     * Startup processing.
-     */
-    private void startup() {
-	this.dbHandler = GraphDBManager.getDBOperation();
-
-	//
-	// Obtain the initial Topology state
-	//
-	Collection<TopologyElement> topologyElements =
-	    datagridService.getAllTopologyElements();
-	for (TopologyElement topologyElement : topologyElements) {
-	    EventEntry<TopologyElement> eventEntry =
-		new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
-	    topologyEvents.add(eventEntry);
-	}
-	//
-	// Obtain the initial Flow Path state
-	//
-	Collection<FlowPath> flowPaths = datagridService.getAllFlows();
-	for (FlowPath flowPath : flowPaths) {
-	    EventEntry<FlowPath> eventEntry =
-		new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
-	    flowPathEvents.add(eventEntry);
-	}
-	//
-	// Obtain the initial FlowEntry state
-	//
-	Collection<FlowEntry> flowEntries = datagridService.getAllFlowEntries();
-	for (FlowEntry flowEntry : flowEntries) {
-	    EventEntry<FlowEntry> eventEntry =
-		new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
-	    flowEntryEvents.add(eventEntry);
-	}
-
-	//
-	// Obtain the initial FlowId state
-	//
-	Collection<Pair<FlowId, Dpid>> flowIds =
-	    datagridService.getAllFlowIds();
-	for (Pair<FlowId, Dpid> pair : flowIds) {
-	    EventEntry<Pair<FlowId, Dpid>> eventEntry =
-		new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
-	    flowIdEvents.add(eventEntry);
-	}
-
-	//
-	// Obtain the initial FlowEntryId state
-	//
-	Collection<Pair<FlowEntryId, Dpid>> flowEntryIds =
-	    datagridService.getAllFlowEntryIds();
-	for (Pair<FlowEntryId, Dpid> pair : flowEntryIds) {
-	    EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
-		new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, pair);
-	    flowEntryIdEvents.add(eventEntry);
-	}
-
-	// Process the initial events (if any)
-	synchronized (allFlowPaths) {
-	    processEvents();
-	}
-
-    }
-
-    /**
-     * Run the thread.
-     */
-    @Override
-    public void run() {
-	this.setName("FlowEventHandler " + this.getId());
-	startup();
-
-	//
-	// The main loop
-	//
-	Collection<EventEntry<?>> collection = new LinkedList<EventEntry<?>>();
-	try {
-	    while (true) {
-		EventEntry<?> eventEntry = networkEvents.take();
-		collection.add(eventEntry);
-		networkEvents.drainTo(collection);
-
-		//
-		// Demultiplex all events:
-		//  - EventEntry<TopologyElement>
-		//  - EventEntry<FlowPath>
-		//  - EventEntry<FlowEntry>
-		//  - EventEntry<Pair<FlowId, Dpid>>
-		//  - EventEntry<Pair<FlowEntryId, Dpid>>
-		//
-		for (EventEntry<?> event : collection) {
-		    // Topology event
-		    if (event.eventData() instanceof TopologyElement) {
-			EventEntry<TopologyElement> topologyEventEntry =
-			    (EventEntry<TopologyElement>)event;
-			
-			topologyEvents.add(topologyEventEntry);
-			continue;
-		    }
-
-		    // FlowPath event
-		    if (event.eventData() instanceof FlowPath) {
-			EventEntry<FlowPath> flowPathEventEntry =
-			    (EventEntry<FlowPath>)event;
-			flowPathEvents.add(flowPathEventEntry);
-			continue;
-		    }
-
-		    // FlowEntry event
-		    if (event.eventData() instanceof FlowEntry) {
-			EventEntry<FlowEntry> flowEntryEventEntry =
-			    (EventEntry<FlowEntry>)event;
-			flowEntryEvents.add(flowEntryEventEntry);
-			continue;
-		    }
-
-		    // FlowId event
-		    if (event.eventData() instanceof Pair) {
-			EventEntry<Pair<FlowId, Dpid>> flowIdEventEntry =
-			    (EventEntry<Pair<FlowId, Dpid>>)event;
-			flowIdEvents.add(flowIdEventEntry);
-			continue;
-		    }
-
-		    // Switch Dpid event
-		    if (event.eventData() instanceof Dpid) {
-			EventEntry<Dpid> switchDpidEventEntry =
-			    (EventEntry<Dpid>)event;
-			switchDpidEvents.add(switchDpidEventEntry);
-			continue;
-		    }
-
-		    // FlowEntryId event
-		    // TODO: Fix the code below if we need again to handle
-		    // the FlowEntryId events
-		    /*
-		    if (event.eventData() instanceof Pair) {
-			EventEntry<Pair<FlowEntryId, Dpid>> flowEntryIdEventEntry =
-			    (EventEntry<Pair<FlowEntryId, Dpid>>)event;
-			flowEntryIdEvents.add(flowEntryIdEventEntry);
-			continue;
-		    }
-		    */
-		}
-		collection.clear();
-
-		// Process the events (if any)
-		synchronized (allFlowPaths) {
-		    processEvents();
-		}
-	    }
-	} catch (Exception exception) {
-	    log.debug("Exception processing Network Events: ", exception);
-	}
-    }
-    
-    /**
-     * Process the events (if any)
-     */
-    private void processEvents() {
-	Collection<FlowEntry> modifiedFlowEntries;
-
-	if (enableOnrc2014MeasurementsFlows) {
-
-	    PerformanceMonitor.start("EventHandler.ProcessAllEvents");
-
-	    if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
-		switchDpidEvents.isEmpty()) {
-		return;		// Nothing to do
-	    }
-
-	    Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
-
-	    // Process the Switch Dpid events
-	    PerformanceMonitor.start("EventHandler.SwitchDpidEvents");
-	    processSwitchDpidEvents();
-	    PerformanceMonitor.stop("EventHandler.SwitchDpidEvents");
-
-	    // Process the Flow ID events
-	    PerformanceMonitor.start("EventHandler.FlowIdEvents");
-	    processFlowIdEvents(mySwitches);
-	    PerformanceMonitor.stop("EventHandler.FlowIdEvents");
-
-	    // Fetch the topology
-	    PerformanceMonitor.start("EventHandler.ReadTopology");
-	    processTopologyEvents();
-	    PerformanceMonitor.stop("EventHandler.ReadTopology");
-
-	    // Recompute all affected Flow Paths and keep only the modified
-	    PerformanceMonitor.start("EventHandler.RecomputeFlows");
-	    for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
-		if (recomputeFlowPath(flowPath))
-		    modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
-	    }
-
-	    // Assign the Flow Entry ID as needed
-	    for (FlowPath flowPath : modifiedFlowPaths.values()) {
-		for (FlowEntry flowEntry : flowPath.flowEntries()) {
-		    if (! flowEntry.isValidFlowEntryId()) {
-			long id = registryService.getNextUniqueId();
-			flowEntry.setFlowEntryId(new FlowEntryId(id));
-		    }
-		}
-	    }
-	    PerformanceMonitor.stop("EventHandler.RecomputeFlows");
-
-	    //
-	    // Push the modified state to the database
-	    //
-	    PerformanceMonitor.start("EventHandler.WriteFlowsToDb");
-	    for (FlowPath flowPath : modifiedFlowPaths.values()) {
-		//
-		// Delete the Flow Path from the Network Map
-		//
-		if (flowPath.flowPathUserState() ==
-		    FlowPathUserState.FP_USER_DELETE) {
-		    log.debug("Deleting Flow Path From Database: {}", flowPath);
-		    // TODO: For now the deleting of a Flow Path is blocking
-		    ParallelFlowDatabaseOperation.deleteFlow(dbHandler,
-							     flowPath.flowId());
-		    //
-		    // NOTE: For now the sending of the notifications
-		    // is outside of this loop, so the performance measurements
-		    // are more accurate.
-		    //
-		    /*
-		    // Send the notifications for the deleted Flow Entries
-		    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-			datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
-		    }
-		    */
-
-		    continue;
-		}
-
-		log.debug("Pushing Flow Path To Database: {}", flowPath);
-		//
-		// Write the Flow Path to the Network Map
-		//
-		ParallelFlowDatabaseOperation.addFlow(dbHandler, flowPath,
-						      datagridService);
-	    }
-	    PerformanceMonitor.stop("EventHandler.WriteFlowsToDb");
-
-	    //
-	    // Send the notifications for the deleted Flow Entries
-	    // NOTE: This code was pulled outside of the above loop,
-	    // so the performance measurements are more accurate.
-	    //
-	    PerformanceMonitor.start("EventHandler.NotificationSend.FlowEntryRemoved");
-	    for (FlowPath flowPath : modifiedFlowPaths.values()) {
-		if (flowPath.flowPathUserState() ==
-		    FlowPathUserState.FP_USER_DELETE) {
-		    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-			datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
-		    }
-		}
-	    }
-	    PerformanceMonitor.stop("EventHandler.NotificationSend.FlowEntryRemoved");
-
-	    // Cleanup
-	    topologyEvents.clear();
-	    flowIdEvents.clear();
-	    switchDpidEvents.clear();
-	    //
-	    // NOTE: Keep a cache with my Flow Paths
-	    // allFlowPaths.clear();
-	    shouldRecomputeFlowPaths.clear();
-	    modifiedFlowPaths.clear();
-
-	    PerformanceMonitor.stop("EventHandler.ProcessAllEvents");
-
-
-//	    PerformanceMonitor.report("EventHandler.SwitchDpidEvents");
-//	    PerformanceMonitor.report("EventHandler.FlowIdEvents");
-//	    PerformanceMonitor.report("EventHandler.ReadTopology");
-//	    PerformanceMonitor.report("EventHandler.RecomputeFlows");
-//	    PerformanceMonitor.report("EventHandler.WriteFlowsToDb");
-//	    PerformanceMonitor.report("EventHandler.NotificationSend.FlowEntryRemoved");
-//	    PerformanceMonitor.report("EventHandler.ProcessAllEvents");
-//	    PerformanceMonitor.report();
-//	    PerformanceMonitor.clear();
-
-	    return;
-	}
-
-	if (topologyEvents.isEmpty() && flowPathEvents.isEmpty() &&
-	    flowEntryEvents.isEmpty()) {
-	    return;		// Nothing to do
-	}
-
-	processFlowPathEvents();
-	processTopologyEvents();
-	processUnmatchedFlowEntryAdd();
-	processFlowEntryEvents();
-
-	// Recompute all affected Flow Paths and keep only the modified
-	for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
-	    if (recomputeFlowPath(flowPath))
-		modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
-	}
-
-	// Extract the modified Flow Entries
-	modifiedFlowEntries = extractModifiedFlowEntries(modifiedFlowPaths.values());
-
-	// Assign missing Flow Entry IDs
-	assignFlowEntryId(modifiedFlowEntries);
-
-	//
-	// Push the modified state to the Flow Manager
-	//
-	flowManager.pushModifiedFlowState(modifiedFlowPaths.values(),
-					  modifiedFlowEntries);
-
-	//
-	// Remove Flow Entries that were deleted
-	//
-	for (FlowPath flowPath : modifiedFlowPaths.values())
-	    flowPath.dataPath().removeDeletedFlowEntries();
-
-	//
-	// Check if Flow Paths have been installed into all switches,
-	// and generate the appropriate events.
-	//
-	checkInstalledFlowPaths(checkIfInstalledFlowPaths.values());
-
-	// Cleanup
-	topologyEvents.clear();
-	flowPathEvents.clear();
-	flowEntryEvents.clear();
-	//
-	shouldRecomputeFlowPaths.clear();
-	modifiedFlowPaths.clear();
-	checkIfInstalledFlowPaths.clear();
-    }
-
-    /**
-     * Check if Flow Paths have been installed into all switches,
-     * and generate the appropriate events.
-     *
-     * @param flowPaths the flowPaths to process.
-     */
-    private void checkInstalledFlowPaths(Collection<FlowPath> flowPaths) {
-	List<FlowPath> installedFlowPaths = new LinkedList<FlowPath>();
-
-	Kryo kryo = kryoFactory.newKryo();
-
-	for (FlowPath flowPath : flowPaths) {
-	    boolean isInstalled = true;
-	    
-	    if (flowPath.flowEntries().isEmpty()) {
-	    	continue;
-	    }
-
-	    //
-	    // Check whether all Flow Entries have been installed
-	    //
-	    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-		if (flowEntry.flowEntrySwitchState() !=
-		    FlowEntrySwitchState.FE_SWITCH_UPDATED) {
-		    isInstalled = false;
-		    break;
-		}
-	    }
-
-	    if (isInstalled) {
-		// Create a copy and add it to the list
-		FlowPath copyFlowPath = kryo.copy(flowPath);
-		installedFlowPaths.add(copyFlowPath);
-	    }
-	}
-	kryoFactory.deleteKryo(kryo);
-
-	// Generate an event for the installed Flow Path.
-	flowManager.notificationFlowPathsInstalled(installedFlowPaths);
-    }
-
-    /**
-     * Extract the modified Flow Entries.
-     *
-     * @param modifiedFlowPaths the Flow Paths to process.
-     * @return a collection with the modified Flow Entries.
-     */
-    private Collection<FlowEntry> extractModifiedFlowEntries(
-			Collection<FlowPath> modifiedFlowPaths) {
-	List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
-
-	// Extract only the modified Flow Entries
-	for (FlowPath flowPath : modifiedFlowPaths) {
-	    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-		if (flowEntry.flowEntrySwitchState() ==
-		    FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
-		    modifiedFlowEntries.add(flowEntry);
-		}
-	    }
-	}
-	return modifiedFlowEntries;
-    }
-
-    /**
-     * Assign the Flow Entry ID as needed.
-     *
-     * @param modifiedFlowEnries the collection of Flow Entries that need
-     * Flow Entry ID assigned.
-     */
-    private void assignFlowEntryId(Collection<FlowEntry> modifiedFlowEntries) {
-	if (modifiedFlowEntries.isEmpty())
-	    return;
-
-	Map<Long, IOFSwitch> mySwitches = flowManager.getMySwitches();
-
-	//
-	// Assign the Flow Entry ID only for Flow Entries for my switches
-	//
-	for (FlowEntry flowEntry : modifiedFlowEntries) {
-	    IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
-	    if (mySwitch == null)
-		continue;
-	    if (! flowEntry.isValidFlowEntryId()) {
-		long id = registryService.getNextUniqueId();
-		flowEntry.setFlowEntryId(new FlowEntryId(id));
-	    }
-	}
-    }
-
-    /**
-     * Fix a flow fetched from the database.
-     *
-     * @param flowPath the Flow to fix.
-     */
-    private void fixFlowFromDatabase(FlowPath flowPath) {
-	//
-	// TODO: Bug workaround / fix :
-	// method FlowDatabaseOperation.extractFlowEntry() doesn't
-	// fetch the inPort and outPort, hence we assign them here.
-	//
-	// Assign the inPort and outPort for the Flow Entries
-	for (FlowEntry flowEntry : flowPath.flowEntries()) {
-	    // Set the inPort
-	    do {
-		if (flowEntry.inPort() != null)
-		    break;
-		if (flowEntry.flowEntryMatch() == null)
-		    break;
-		Port inPort = new Port(flowEntry.flowEntryMatch().inPort().value());
-		flowEntry.setInPort(inPort);
-	    } while (false);
-
-	    // Set the outPort
-	    do {
-		if (flowEntry.outPort() != null)
-		    break;
-		for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
-		    if (fa.actionOutput() != null) {
-			Port outPort = new Port(fa.actionOutput().port().value());
-			flowEntry.setOutPort(outPort);
-			break;
-		    }
-		}
-	    } while (false);
-	}
-    }
-
-    /**
-     * Process the Switch Dpid events.
-     */
-    private void processSwitchDpidEvents() {
-	Map<Long, Dpid> addedSwitches = new HashMap<Long, Dpid>();
-	Map<Long, Dpid> removedSwitches = new HashMap<Long, Dpid>();
-
-	//
-	// Process all Switch Dpid events and update the appropriate state
-	//
-	for (EventEntry<Dpid> eventEntry : switchDpidEvents) {
-	    Dpid dpid = eventEntry.eventData();
-			
-	    log.debug("SwitchDpid Event: {} {}", eventEntry.eventType(), dpid);
-
-	    // Compute the final set of added and removed switches
-	    switch (eventEntry.eventType()) {
-	    case ENTRY_ADD:
-		addedSwitches.put(dpid.value(), dpid);
-		removedSwitches.remove(dpid.value());
-		break;
-	    case ENTRY_REMOVE:
-		addedSwitches.remove(dpid.value());
-		removedSwitches.put(dpid.value(), dpid);
-		break;
-	    }
-	}
-
-	//
-	// Remove the Flows from the local cache if the removed
-	// switch is the Source Switch.
-	//
-	// TODO: This search can be expensive for a large number of flows
-	// and should be optmized.
-	//
-	List<FlowId> deleteFlowIds = new LinkedList<FlowId>();
-	for (Dpid switchDpid : removedSwitches.values()) {
-	    for (FlowPath flowPath : allFlowPaths.values()) {
-		Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
-		if (srcDpid.value() == switchDpid.value())
-		    deleteFlowIds.add(flowPath.flowId());
-	    }
-	}
-	//
-	// Remove the Flows from the local cache
-	//
-	for (FlowId flowId : deleteFlowIds)
-	    allFlowPaths.remove(flowId.value());
-
-	// Get the Flows for the added switches
-	Collection<FlowPath> flowPaths =
-	    ParallelFlowDatabaseOperation.getFlowsForSwitches(dbHandler,
-							      addedSwitches.values());
-	for (FlowPath flowPath : flowPaths) {
-	    allFlowPaths.put(flowPath.flowId().value(), flowPath);
-	}
-    }
-
-    /**
-     * Process the Flow ID events.
-     *
-     * @param mySwitches the collection of my switches.
-     */
-    private void processFlowIdEvents(Map<Long, IOFSwitch> mySwitches) {
-	List<FlowId> shouldFetchMyFlowIds = new LinkedList<FlowId>();
-
-	//
-	// Process all Flow Id events and update the appropriate state
-	//
-	for (EventEntry<Pair<FlowId, Dpid>> eventEntry : flowIdEvents) {
-	    Pair<FlowId, Dpid> pair = eventEntry.eventData();
-	    FlowId flowId = pair.first;
-	    Dpid dpid = pair.second;
-
-	    log.debug("Flow ID Event: {} {} {}", eventEntry.eventType(),
-		      flowId, dpid);
-
-	    //
-	    // Ignore Flows if the Source Switch is not controlled by this
-	    // instance.
-	    //
-	    if (mySwitches.get(dpid.value()) == null)
-		continue;
-
-	    switch (eventEntry.eventType()) {
-	    case ENTRY_ADD: {
-		//
-		// Add a new Flow Path
-		//
-		if (allFlowPaths.get(flowId.value()) != null) {
-		    //
-		    // TODO: What to do if the Flow Path already exists?
-		    // Fow now, we just re-add it.
-		    //
-		}
-		shouldFetchMyFlowIds.add(flowId);
-
-		break;
-	    }
-
-	    case ENTRY_REMOVE: {
-		//
-		// Remove an existing Flow Path.
-		//
-		// Find the Flow Path, and mark the Flow and its Flow Entries
-		// for deletion.
-		//
-		FlowPath existingFlowPath =
-		    allFlowPaths.get(flowId.value());
-		if (existingFlowPath == null)
-		    continue;		// Nothing to do
-
-		existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
-		for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
-		    flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
-		    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
-		}
-
-		// Remove the Flow Path from the internal state
-		Long key = existingFlowPath.flowId().value();
-		allFlowPaths.remove(key);
-		shouldRecomputeFlowPaths.remove(key);
-		modifiedFlowPaths.put(key, existingFlowPath);
-
-		break;
-	    }
-	    }
-	}
-
-	// Get my Flows
-	Collection<FlowPath> myFlows =
-	    ParallelFlowDatabaseOperation.getFlows(dbHandler,
-						   shouldFetchMyFlowIds);
-
-	for (FlowPath flowPath : myFlows) {
-	    fixFlowFromDatabase(flowPath);
-
-	    switch (flowPath.flowPathType()) {
-	    case FP_TYPE_SHORTEST_PATH:
-		//
-		// Reset the Data Path, in case it was set already, because
-		// we are going to recompute it anyway.
-		//
-		flowPath.flowEntries().clear();
-		shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
-					     flowPath);
-		break;
-	    case FP_TYPE_EXPLICIT_PATH:
-		//
-		// Mark all Flow Entries for installation in the switches.
-		//
-		for (FlowEntry flowEntry : flowPath.flowEntries()) {
-		    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
-		}
-		modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
-		break;
-	    case FP_TYPE_UNKNOWN:
-		log.error("FlowPath event with unknown type");
-		break;
-	    }
-	    allFlowPaths.put(flowPath.flowId().value(), flowPath);
-	}
-    }
-
-    /**
-     * Process the Flow Entry ID events.
-     *
-     * @param mySwitches the collection of my switches.
-     * @return a collection of modified Flow Entries this instance needs
-     * to push to its own switches.
-     */
-    private Collection<FlowEntry> processFlowEntryIdEvents(Map<Long, IOFSwitch> mySwitches) {
-	List<FlowEntry> modifiedFlowEntries = new LinkedList<FlowEntry>();
-
-	//
-	// Process all Flow ID events and update the appropriate state
-	//
-	for (EventEntry<Pair<FlowEntryId, Dpid>> eventEntry : flowEntryIdEvents) {
-	    Pair<FlowEntryId, Dpid> pair = eventEntry.eventData();
-	    FlowEntryId flowEntryId = pair.first;
-	    Dpid dpid = pair.second;
-
-	    log.debug("Flow Entry ID Event: {} {} {}", eventEntry.eventType(),
-		      flowEntryId, dpid);
-
-	    if (mySwitches.get(dpid.value()) == null)
-		continue;
-
-	    // Fetch the Flow Entry
-	    FlowEntry flowEntry = FlowDatabaseOperation.getFlowEntry(dbHandler,
-								     flowEntryId);
-	    if (flowEntry == null) {
-		log.debug("Flow Entry ID {} : Flow Entry not found!",
-			  flowEntryId);
-		continue;
-	    }
-	    modifiedFlowEntries.add(flowEntry);
-	}
-
-	return modifiedFlowEntries;
-    }
-
-    /**
-     * Process the Flow Path events.
-     */
-    private void processFlowPathEvents() {
-	//
-	// Process all Flow Path events and update the appropriate state
-	//
-	for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
-	    FlowPath flowPath = eventEntry.eventData();
-
-	    log.debug("Flow Event: {} {}", eventEntry.eventType(), flowPath);
-
-	    switch (eventEntry.eventType()) {
-	    case ENTRY_ADD: {
-		//
-		// Add a new Flow Path
-		//
-		if (allFlowPaths.get(flowPath.flowId().value()) != null) {
-		    //
-		    // TODO: What to do if the Flow Path already exists?
-		    // Fow now, we just re-add it.
-		    //
-		}
-
-		switch (flowPath.flowPathType()) {
-		case FP_TYPE_SHORTEST_PATH:
-		    //
-		    // Reset the Data Path, in case it was set already, because
-		    // we are going to recompute it anyway.
-		    //
-		    flowPath.flowEntries().clear();
-		    shouldRecomputeFlowPaths.put(flowPath.flowId().value(),
-						 flowPath);
-		    break;
-		case FP_TYPE_EXPLICIT_PATH:
-		    //
-		    // Mark all Flow Entries for installation in the switches.
-		    //
-		    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-			flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
-		    }
-		    modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
-		    break;
-		case FP_TYPE_UNKNOWN:
-		    log.error("FlowPath event with unknown type");
-		    break;
-		}
-		allFlowPaths.put(flowPath.flowId().value(), flowPath);
-
-		break;
-	    }
-
-	    case ENTRY_REMOVE: {
-		//
-		// Remove an existing Flow Path.
-		//
-		// Find the Flow Path, and mark the Flow and its Flow Entries
-		// for deletion.
-		//
-		FlowPath existingFlowPath =
-		    allFlowPaths.get(flowPath.flowId().value());
-		if (existingFlowPath == null)
-		    continue;		// Nothing to do
-
-		existingFlowPath.setFlowPathUserState(FlowPathUserState.FP_USER_DELETE);
-		for (FlowEntry flowEntry : existingFlowPath.flowEntries()) {
-		    flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
-		    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
-		}
-
-		// Remove the Flow Path from the internal state
-		Long key = existingFlowPath.flowId().value();
-		allFlowPaths.remove(key);
-		shouldRecomputeFlowPaths.remove(key);
-		modifiedFlowPaths.put(key, existingFlowPath);
-
-		break;
-	    }
-	    }
-	}
-    }
-
-    /**
-     * Process the Topology events.
-     */
-    private void processTopologyEvents() {
-	boolean isTopologyModified = false;
-
-	if (enableOnrc2014MeasurementsTopology) {
-	    if (topologyEvents.isEmpty())
-		return;
-
-	    // TODO: Code for debugging purpose only
-	    for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
-		TopologyElement topologyElement = eventEntry.eventData();
-		log.debug("Topology Event: {} {}", eventEntry.eventType(),
-			  topologyElement.toString());
-	    }
-
-	    log.debug("[BEFORE] {}", topology.toString());
-	    topology.readFromDatabase(dbHandler);
-	    log.debug("[AFTER] {}", topology.toString());
-	    shouldRecomputeFlowPaths.putAll(allFlowPaths);
-	    return;
-	}
-
-	//
-	// Process all Topology events and update the appropriate state
-	//
-	for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
-	    TopologyElement topologyElement = eventEntry.eventData();
-			
-	    log.debug("Topology Event: {} {}", eventEntry.eventType(),
-		      topologyElement.toString());
-
-	    switch (eventEntry.eventType()) {
-	    case ENTRY_ADD:
-    		isTopologyModified |= topology.addTopologyElement(topologyElement);
-		break;
-	    case ENTRY_REMOVE:
-    		isTopologyModified |= topology.removeTopologyElement(topologyElement);
-		break;
-	    }
-	}
-	if (isTopologyModified) {
-	    // TODO: For now, if the topology changes, we recompute all Flows
-	    shouldRecomputeFlowPaths.putAll(allFlowPaths);
-	}
-    }
-
-    /**
-     * Process previously received Flow Entries with unmatched Flow Paths.
-     */
-    private void processUnmatchedFlowEntryAdd() {
-	FlowPath flowPath;
-	FlowEntry localFlowEntry;
-
-	//
-	// Update Flow Entries with previously unmatched Flow Entry updates
-	//
-	if (! unmatchedFlowEntryAdd.isEmpty()) {
-	    Map<Long, FlowEntry> remainingUpdates = new HashMap<Long, FlowEntry>();
-	    for (FlowEntry flowEntry : unmatchedFlowEntryAdd.values()) {
-		// log.debug("Processing Unmatched Flow Entry: {}",
-		//	  flowEntry.toString());
-
-		flowPath = allFlowPaths.get(flowEntry.flowId().value());
-		if (flowPath == null) {
-		    remainingUpdates.put(flowEntry.flowEntryId().value(),
-					 flowEntry);
-		    continue;
-		}
-		localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
-		if (localFlowEntry == null) {
-		    remainingUpdates.put(flowEntry.flowEntryId().value(),
-					 flowEntry);
-		    continue;
-		}
-		if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
-		    modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
-		}
-	    }
-	    unmatchedFlowEntryAdd = remainingUpdates;
-	}
-    }
-
-    /**
-     * Process the Flow Entry events.
-     */
-    private void processFlowEntryEvents() {
-	FlowPath flowPath;
-	FlowEntry localFlowEntry;
-
-	//
-	// Process all Flow Entry events and update the appropriate state
-	//
-	for (EventEntry<FlowEntry> eventEntry : flowEntryEvents) {
-	    FlowEntry flowEntry = eventEntry.eventData();
-
-	    log.debug("Flow Entry Event: {} {}", eventEntry.eventType(),
-		      flowEntry);
-
-	    if ((! flowEntry.isValidFlowId()) ||
-		(! flowEntry.isValidFlowEntryId())) {
-		continue;
-	    }
-
-	    switch (eventEntry.eventType()) {
-	    case ENTRY_ADD:
-		flowPath = allFlowPaths.get(flowEntry.flowId().value());
-		if (flowPath == null) {
-		    // Flow Path not found: keep the entry for later matching
-		    unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
-					      flowEntry);
-		    break;
-		}
-		localFlowEntry = findFlowEntryAdd(flowPath, flowEntry);
-		if (localFlowEntry == null) {
-		    // Flow Entry not found: keep the entry for later matching
-		    unmatchedFlowEntryAdd.put(flowEntry.flowEntryId().value(),
-					      flowEntry);
-		    break;
-		}
-		if (updateFlowEntryAdd(flowPath, localFlowEntry, flowEntry)) {
-		    // Add the updated Flow Path to the list of updated paths
-		    modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
-		}
-		break;
-
-	    case ENTRY_REMOVE:
-		flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
-		if (unmatchedFlowEntryAdd.remove(flowEntry.flowEntryId().value()) != null) {
-		    continue;		// Removed previously unmatched entry
-		}
-
-		flowPath = allFlowPaths.get(flowEntry.flowId().value());
-		if (flowPath == null) {
-		    // Flow Path not found: ignore the update
-		    break;
-		}
-		localFlowEntry = findFlowEntryRemove(flowPath, flowEntry);
-		if (localFlowEntry == null) {
-		    // Flow Entry not found: ignore it
-		    break;
-		}
-		if (updateFlowEntryRemove(flowPath, localFlowEntry,
-					  flowEntry)) {
-		    // Add the updated Flow Path to the list of updated paths
-		    modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
-		}
-		break;
-	    }
-	}
-    }
-
-    /**
-     * Find a Flow Entry that should be updated because of an external
-     * ENTRY_ADD event.
-     *
-     * @param flowPath the FlowPath for the Flow Entry to update.
-     * @param newFlowEntry the FlowEntry with the new state.
-     * @return the Flow Entry that should be updated if found, otherwise null.
-     */
-    private FlowEntry findFlowEntryAdd(FlowPath flowPath,
-				       FlowEntry newFlowEntry) {
-	//
-	// Iterate over all Flow Entries and find a match.
-	//
-	for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
-	    if (! TopologyManager.isSameFlowEntryDataPath(localFlowEntry,
-							  newFlowEntry)) {
-		continue;
-	    }
-
-	    //
-	    // Local Flow Entry match found
-	    //
-	    if (localFlowEntry.isValidFlowEntryId()) {
-		if (localFlowEntry.flowEntryId().value() !=
-		    newFlowEntry.flowEntryId().value()) {
-		    //
-		    // Find a local Flow Entry, but the Flow Entry ID doesn't
-		    // match. Keep looking.
-		    //
-		    continue;
-		}
-	    }
-	    return localFlowEntry;
-	}
-
-	return null;		// Entry not found
-    }
-
-    /**
-     * Update a Flow Entry because of an external ENTRY_ADD event.
-     *
-     * @param flowPath the FlowPath for the Flow Entry to update.
-     * @param localFlowEntry the local Flow Entry to update.
-     * @param newFlowEntry the FlowEntry with the new state.
-     * @return true if the local Flow Entry was updated, otherwise false.
-     */
-    private boolean updateFlowEntryAdd(FlowPath flowPath,
-				       FlowEntry localFlowEntry,
-				       FlowEntry newFlowEntry) {
-	boolean updated = false;
-
-	if (localFlowEntry.flowEntryUserState() ==
-	    FlowEntryUserState.FE_USER_DELETE) {
-	    // Don't add-back a Flow Entry that is already deleted
-	    return false;
-	}
-
-	if (! localFlowEntry.isValidFlowEntryId()) {
-	    // Update the Flow Entry ID
-	    FlowEntryId flowEntryId =
-		new FlowEntryId(newFlowEntry.flowEntryId().value());
-	    localFlowEntry.setFlowEntryId(flowEntryId);
-	    updated = true;
-	}
-
-	//
-	// Update the local Flow Entry, and keep state to check
-	// if the Flow Path has been installed.
-	//
-	if (localFlowEntry.flowEntryUserState() !=
-	    newFlowEntry.flowEntryUserState()) {
-	    localFlowEntry.setFlowEntryUserState(
-			 newFlowEntry.flowEntryUserState());
-	    updated = true;
-	}
-	if (localFlowEntry.flowEntrySwitchState() !=
-	    newFlowEntry.flowEntrySwitchState()) {
-	    localFlowEntry.setFlowEntrySwitchState(
-			newFlowEntry.flowEntrySwitchState());
-	    checkIfInstalledFlowPaths.put(flowPath.flowId().value(), flowPath);
-	    updated = true;
-	}
-
-	return updated;
-    }
-
-    /**
-     * Find a Flow Entry that should be updated because of an external
-     * ENTRY_REMOVE event.
-     *
-     * @param flowPath the FlowPath for the Flow Entry to update.
-     * @param newFlowEntry the FlowEntry with the new state.
-     * @return the Flow Entry that should be updated if found, otherwise null.
-     */
-    private FlowEntry findFlowEntryRemove(FlowPath flowPath,
-					  FlowEntry newFlowEntry) {
-	//
-	// Iterate over all Flow Entries and find a match based on
-	// the Flow Entry ID.
-	//
-	for (FlowEntry localFlowEntry : flowPath.flowEntries()) {
-	    if (! localFlowEntry.isValidFlowEntryId())
-		continue;
-	    if (localFlowEntry.flowEntryId().value() !=
-		newFlowEntry.flowEntryId().value()) {
-		continue;
-	    }
-	    return localFlowEntry;
-	}
-
-	return null;		// Entry not found
-    }
-
-    /**
-     * Update a Flow Entry because of an external ENTRY_REMOVE event.
-     *
-     * @param flowPath the FlowPath for the Flow Entry to update.
-     * @param localFlowEntry the local Flow Entry to update.
-     * @param newFlowEntry the FlowEntry with the new state.
-     * @return true if the local Flow Entry was updated, otherwise false.
-     */
-    private boolean updateFlowEntryRemove(FlowPath flowPath,
-					  FlowEntry localFlowEntry,
-					  FlowEntry newFlowEntry) {
-	boolean updated = false;
-
-	//
-	// Update the local Flow Entry.
-	//
-	if (localFlowEntry.flowEntryUserState() !=
-	    newFlowEntry.flowEntryUserState()) {
-	    localFlowEntry.setFlowEntryUserState(
-			newFlowEntry.flowEntryUserState());
-	    updated = true;
-	}
-	if (localFlowEntry.flowEntrySwitchState() !=
-	    newFlowEntry.flowEntrySwitchState()) {
-	    localFlowEntry.setFlowEntrySwitchState(
-			newFlowEntry.flowEntrySwitchState());
-	    updated = true;
-	}
-
-	return updated;
-    }
-
-    /**
-     * Recompute a Flow Path.
-     *
-     * @param flowPath the Flow Path to recompute.
-     * @return true if the recomputed Flow Path has changed, otherwise false.
-     */
-    private boolean recomputeFlowPath(FlowPath flowPath) {
-	boolean hasChanged = false;
-
-	if (enableOnrc2014MeasurementsFlows) {
-	    // Cleanup the deleted Flow Entries from the earlier iteration
-	    flowPath.dataPath().removeDeletedFlowEntries();
-
-	    //
-	    // TODO: Fake it that the Flow Entries have been already pushed
-	    // into the switches, so we don't push them again.
-	    //
-	    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-		flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
-	    }
-	}
-
-	//
-	// Test whether the Flow Path needs to be recomputed
-	//
-	switch (flowPath.flowPathType()) {
-	case FP_TYPE_UNKNOWN:
-	    return false;		// Can't recompute on Unknown FlowType
-	case FP_TYPE_SHORTEST_PATH:
-	    break;
-	case FP_TYPE_EXPLICIT_PATH:
-	    return false;		// An explicit path never changes
-	}
-
-	DataPath oldDataPath = flowPath.dataPath();
-
-	// Compute the new path
-	DataPath newDataPath;
-	newDataPath = TopologyManager.computeNetworkPath(topology,
-								  flowPath);
-	if (newDataPath == null) {
-	    // We need the DataPath to compare the paths
-	    newDataPath = new DataPath();
-	}
-	newDataPath.applyFlowPathFlags(flowPath.flowPathFlags());
-
-	//
-	// Test whether the new path is same
-	//
-	if (oldDataPath.flowEntries().size() !=
-	    newDataPath.flowEntries().size()) {
-	    hasChanged = true;
-	} else {
-	    Iterator<FlowEntry> oldIter = oldDataPath.flowEntries().iterator();
-	    Iterator<FlowEntry> newIter = newDataPath.flowEntries().iterator();
-	    while (oldIter.hasNext() && newIter.hasNext()) {
-		FlowEntry oldFlowEntry = oldIter.next();
-		FlowEntry newFlowEntry = newIter.next();
-		if (! TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
-							      newFlowEntry)) {
-		    hasChanged = true;
-		    break;
-		}
-	    }
-	}
-	if (! hasChanged)
-	    return hasChanged;
-
-	//
-	// Merge the changes in the path:
-	//  - If a Flow Entry for a switch is in the old data path, but not
-	//    in the new data path, then mark it for deletion.
-	//  - If a Flow Entry for a switch is in the new data path, but not
-	//    in the old data path, then mark it for addition.
-	//  - If a Flow Entry for a switch is in both the old and the new
-	//    data path, but it has changed, e.g., the incoming and/or outgoing
-	//    port(s), then mark the old Flow Entry for deletion, and mark
-	//    the new Flow Entry for addition.
-	//  - If a Flow Entry for a switch is in both the old and the new
-	//    data path, and it hasn't changed, then just keep it.
-	//
-	// NOTE: We use the Switch DPID of each entry to match the entries
-	//
-	Map<Long, FlowEntry> oldFlowEntriesMap = new HashMap<Long, FlowEntry>();
-	Map<Long, FlowEntry> newFlowEntriesMap = new HashMap<Long, FlowEntry>();
-	ArrayList<FlowEntry> finalFlowEntries = new ArrayList<FlowEntry>();
-	List<FlowEntry> deletedFlowEntries = new LinkedList<FlowEntry>();
-
-	// Prepare maps with the Flow Entries, so they are fast to lookup
-	for (FlowEntry flowEntry : oldDataPath.flowEntries())
-	    oldFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
-	for (FlowEntry flowEntry : newDataPath.flowEntries())
-	    newFlowEntriesMap.put(flowEntry.dpid().value(), flowEntry);
-
-	//
-	// Find the old Flow Entries that should be deleted
-	//
-	for (FlowEntry oldFlowEntry : oldDataPath.flowEntries()) {
-	    FlowEntry newFlowEntry =
-		newFlowEntriesMap.get(oldFlowEntry.dpid().value());
-	    if (newFlowEntry == null) {
-		// The old Flow Entry should be deleted: not on the path
-		oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
-		oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
-		deletedFlowEntries.add(oldFlowEntry);
-	    }
-	}
-
-	//
-	// Find the new Flow Entries that should be added or updated
-	//
-	int idx = 0;
-	for (FlowEntry newFlowEntry : newDataPath.flowEntries()) {
-	    FlowEntry oldFlowEntry =
-		oldFlowEntriesMap.get(newFlowEntry.dpid().value());
-
-	    if ((oldFlowEntry != null) &&
-		TopologyManager.isSameFlowEntryDataPath(oldFlowEntry,
-							newFlowEntry)) {
-		//
-		// Both Flow Entries are same
-		//
-		finalFlowEntries.add(oldFlowEntry);
-		idx++;
-		continue;
-	    }
-
-	    if (oldFlowEntry != null) {
-		//
-		// The old Flow Entry should be deleted: path diverges
-		//
-		oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
-		oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
-		deletedFlowEntries.add(oldFlowEntry);
-	    }
-
-	    //
-	    // Add the new Flow Entry
-	    //
-	    //
-	    // NOTE: Assign only the Flow ID.
-	    // The Flow Entry ID is assigned later only for the Flow Entries
-	    // this instance is responsible for.
-	    //
-	    newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
-
-	    //
-	    // Copy the Flow timeouts
-	    //
-	    newFlowEntry.setHardTimeout(flowPath.hardTimeout());
-	    newFlowEntry.setPriority(flowPath.priority());
-
-	    if (flowPath.idleTimeout() > 0) {
-	    	if (idx == 0) {
-	    		newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
-	    	}
-	    	else {
-	    		newFlowEntry.setIdleTimeout(flowPath.idleTimeout() + FLOW_IDLE_TIMEOUT_ADDED_SECONDS);
-	    	}
-	     } else if(flowPath.idleTimeout() == 0) {
-	    	newFlowEntry.setIdleTimeout(flowPath.idleTimeout());
-	     }
-
-	    //
-	    // Allocate the FlowEntryMatch by copying the default one
-	    // from the FlowPath (if set).
-	    //
-	    FlowEntryMatch flowEntryMatch = null;
-	    if (flowPath.flowEntryMatch() != null)
-		flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
-	    else
-		flowEntryMatch = new FlowEntryMatch();
-	    newFlowEntry.setFlowEntryMatch(flowEntryMatch);
-
-	    // Set the incoming port matching
-	    flowEntryMatch.enableInPort(newFlowEntry.inPort());
-
-	    //
-	    // Set the actions:
-	    // If the first Flow Entry, copy the Flow Path actions to it.
-	    //
-	    FlowEntryActions flowEntryActions = newFlowEntry.flowEntryActions();
-	    if ((idx == 0)  && (flowPath.flowEntryActions() != null)) {
-		FlowEntryActions flowActions =
-		    new FlowEntryActions(flowPath.flowEntryActions());
-		for (FlowEntryAction action : flowActions.actions())
-		    flowEntryActions.addAction(action);
-	    }
-	    idx++;
-
-	    //
-	    // Add the outgoing port output action
-	    //
-	    FlowEntryAction flowEntryAction = new FlowEntryAction();
-	    flowEntryAction.setActionOutput(newFlowEntry.outPort());
-	    flowEntryActions.addAction(flowEntryAction);
-
-	    //
-	    // Set the state of the new Flow Entry
-	    //
-	    newFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
-	    newFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
-	    finalFlowEntries.add(newFlowEntry);
-	}
-
-	//
-	// Replace the old Flow Entries with the new Flow Entries.
-	// Note that the Flow Entries that will be deleted are added at
-	// the end.
-	//
-	finalFlowEntries.addAll(deletedFlowEntries);
-	flowPath.dataPath().setFlowEntries(finalFlowEntries);
-
-	return hasChanged;
-    }
-
-    /**
-     * Receive a notification that a Flow is added.
-     *
-     * @param flowPath the Flow that is added.
-     */
-    @Override
-    public void notificationRecvFlowAdded(FlowPath flowPath) {
-	EventEntry<FlowPath> eventEntry =
-	    new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a Flow is removed.
-     *
-     * @param flowPath the Flow that is removed.
-     */
-    @Override
-    public void notificationRecvFlowRemoved(FlowPath flowPath) {
-	EventEntry<FlowPath> eventEntry =
-	    new EventEntry<FlowPath>(EventEntry.Type.ENTRY_REMOVE, flowPath);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a Flow is updated.
-     *
-     * @param flowPath the Flow that is updated.
-     */
-    @Override
-    public void notificationRecvFlowUpdated(FlowPath flowPath) {
-	// NOTE: The ADD and UPDATE events are processed in same way
-	EventEntry<FlowPath> eventEntry =
-	    new EventEntry<FlowPath>(EventEntry.Type.ENTRY_ADD, flowPath);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowEntry is added.
-     *
-     * @param flowEntry the FlowEntry that is added.
-     */
-    @Override
-    public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
-	if (enableOnrc2014MeasurementsFlows) {
-//	    String tag = "EventHandler.AddFlowEntryToSwitch." + flowEntry.flowEntryId();
-	    String tag = "EventHandler.AddFlowEntryToSwitch";
-	    PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
-	    Collection entries = new ArrayList();
-	    entries.add(flowEntry);
-	    flowManager.pushModifiedFlowEntriesToSwitches(entries);
-//	    PerformanceMonitor.stop(tag);
-	    m.stop();
-//	    PerformanceMonitor.report(tag);
-	    return;
-	}
-
-	EventEntry<FlowEntry> eventEntry =
-	    new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowEntry is removed.
-     *
-     * @param flowEntry the FlowEntry that is removed.
-     */
-    @Override
-    public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
-	if (enableOnrc2014MeasurementsFlows) {
-//	    String tag = "EventHandler.RemoveFlowEntryFromSwitch." + flowEntry.flowEntryId();
-	    String tag = "EventHandler.RemoveFlowEntryFromSwitch";
-	    PerformanceMonitor.Measurement m = PerformanceMonitor.start(tag);
-	    //
-	    // NOTE: Must update the state to DELETE, because
-	    // the notification contains the original state.
-	    //
-	    flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
-
-	    Collection entries = new ArrayList();
-	    entries.add(flowEntry);
-	    flowManager.pushModifiedFlowEntriesToSwitches(entries);
-//	    PerformanceMonitor.stop(tag);
-	    m.stop();
-//	    PerformanceMonitor.report(tag);
-	    return;
-	}
-
-	EventEntry<FlowEntry> eventEntry =
-	    new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_REMOVE, flowEntry);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowEntry is updated.
-     *
-     * @param flowEntry the FlowEntry that is updated.
-     */
-    @Override
-    public void notificationRecvFlowEntryUpdated(FlowEntry flowEntry) {
-	if (enableOnrc2014MeasurementsFlows) {
-	    Collection entries = new ArrayList();
-	    entries.add(flowEntry);
-	    flowManager.pushModifiedFlowEntriesToSwitches(entries);
-	    return;
-	}
-
-	// NOTE: The ADD and UPDATE events are processed in same way
-	EventEntry<FlowEntry> eventEntry =
-	    new EventEntry<FlowEntry>(EventEntry.Type.ENTRY_ADD, flowEntry);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowId is added.
-     *
-     * @param flowId the FlowId that is added.
-     * @param dpid the Source Switch Dpid for the corresponding Flow.
-     */
-    @Override
-    public void notificationRecvFlowIdAdded(FlowId flowId, Dpid dpid) {
-	Pair flowIdPair = new Pair(flowId, dpid);
-
-	EventEntry<Pair<FlowId, Dpid>> eventEntry =
-	    new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowId is removed.
-     *
-     * @param flowId the FlowId that is removed.
-     * @param dpid the Source Switch Dpid for the corresponding Flow.
-     */
-    @Override
-    public void notificationRecvFlowIdRemoved(FlowId flowId, Dpid dpid) {
-	Pair flowIdPair = new Pair(flowId, dpid);
-
-	EventEntry<Pair<FlowId, Dpid>> eventEntry =
-	    new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowIdPair);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowId is updated.
-     *
-     * @param flowId the FlowId that is updated.
-     * @param dpid the Source Switch Dpid for the corresponding Flow.
-     */
-    @Override
-    public void notificationRecvFlowIdUpdated(FlowId flowId, Dpid dpid) {
-	Pair flowIdPair = new Pair(flowId, dpid);
-
-	// NOTE: The ADD and UPDATE events are processed in same way
-	EventEntry<Pair<FlowId, Dpid>> eventEntry =
-	    new EventEntry<Pair<FlowId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowIdPair);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowEntryId is added.
-     *
-     * @param flowEntryId the FlowEntryId that is added.
-     * @param dpid the Switch Dpid for the corresponding Flow Entry.
-     */
-    @Override
-    public void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId,
-						 Dpid dpid) {
-	Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
-
-	EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
-	    new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowEntryId is removed.
-     *
-     * @param flowEntryId the FlowEntryId that is removed.
-     * @param dpid the Switch Dpid for the corresponding Flow Entry.
-     */
-    @Override
-    public void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
-						   Dpid dpid) {
-	Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
-
-	EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
-	    new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_REMOVE, flowEntryIdPair);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a FlowEntryId is updated.
-     *
-     * @param flowEntryId the FlowEntryId that is updated.
-     * @param dpid the Switch Dpid for the corresponding Flow Entry.
-     */
-    @Override
-    public void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
-						   Dpid dpid) {
-	Pair flowEntryIdPair = new Pair(flowEntryId, dpid);
-
-	// NOTE: The ADD and UPDATE events are processed in same way
-	EventEntry<Pair<FlowEntryId, Dpid>> eventEntry =
-	    new EventEntry<Pair<FlowEntryId, Dpid>>(EventEntry.Type.ENTRY_ADD, flowEntryIdPair);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a Topology Element is added.
-     *
-     * @param topologyElement the Topology Element that is added.
-     */
-    @Override
-    public void notificationRecvTopologyElementAdded(TopologyElement topologyElement) {
-	EventEntry<TopologyElement> eventEntry =
-	    new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a Topology Element is removed.
-     *
-     * @param topologyElement the Topology Element that is removed.
-     */
-    @Override
-    public void notificationRecvTopologyElementRemoved(TopologyElement topologyElement) {
-	EventEntry<TopologyElement> eventEntry =
-	    new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_REMOVE, topologyElement);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a Topology Element is updated.
-     *
-     * @param topologyElement the Topology Element that is updated.
-     */
-    @Override
-    public void notificationRecvTopologyElementUpdated(TopologyElement topologyElement) {
-	// NOTE: The ADD and UPDATE events are processed in same way
-	EventEntry<TopologyElement> eventEntry =
-	    new EventEntry<TopologyElement>(EventEntry.Type.ENTRY_ADD, topologyElement);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a switch is added to this instance.
-     *
-     * @param sw the switch that is added.
-     */
-    @Override
-    public void addedSwitch(IOFSwitch sw) {
-	Dpid dpid = new Dpid(sw.getId());
-	EventEntry<Dpid> eventEntry =
-	    new EventEntry<Dpid>(EventEntry.Type.ENTRY_ADD, dpid);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that a switch is removed from this instance.
-     *
-     * @param sw the switch that is removed.
-     */
-    @Override
-    public void removedSwitch(IOFSwitch sw) {
-	Dpid dpid = new Dpid(sw.getId());
-	EventEntry<Dpid> eventEntry =
-	    new EventEntry<Dpid>(EventEntry.Type.ENTRY_REMOVE, dpid);
-	networkEvents.add(eventEntry);
-    }
-
-    /**
-     * Receive a notification that the ports on a switch have changed.
-     */
-    @Override
-    public void switchPortChanged(Long switchId) {
-	// Nothing to do
-    }
-    
-    /**
-     * Get a sorted copy of all Flow Paths.
-     *
-     * @return a sorted copy of all Flow Paths.
-     */
-    synchronized SortedMap<Long, FlowPath> getAllFlowPathsCopy() {
-	SortedMap<Long, FlowPath> sortedFlowPaths =
-	    new TreeMap<Long, FlowPath>();
-
-	//
-	// TODO: For now we use serialization/deserialization to create
-	// a copy of each Flow Path. In the future, we should use proper
-	// copy constructors.
-	//
-	Kryo kryo = kryoFactory.newKryo();
-	synchronized (allFlowPaths) {
-	    for (Map.Entry<Long, FlowPath> entry : allFlowPaths.entrySet()) {
-		FlowPath origFlowPath = entry.getValue();
-		FlowPath copyFlowPath = kryo.copy(origFlowPath);
-		sortedFlowPaths.put(entry.getKey(), copyFlowPath);
-	    }
-	}
-	kryoFactory.deleteKryo(kryo);
-
-	return sortedFlowPaths;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
deleted file mode 100644
index 55266b3..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ /dev/null
@@ -1,920 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.util.OFMessageDamper;
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.graph.GraphDBManager;
-import net.onrc.onos.datagrid.IDatagridService;
-import net.onrc.onos.ofcontroller.core.INetMapStorage;
-import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
-import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
-import net.onrc.onos.ofcontroller.forwarding.IForwardingService;
-import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
-import net.onrc.onos.ofcontroller.topology.Topology;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
-import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
-import net.onrc.onos.ofcontroller.util.FlowEntryId;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.FlowPathUserState;
-import net.onrc.onos.ofcontroller.util.Pair;
-import net.onrc.onos.ofcontroller.util.PerformanceMonitor;
-import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
-import net.onrc.onos.registry.controller.IControllerRegistryService;
-
-import com.thinkaurelius.titan.core.TitanException;
-import com.esotericsoftware.kryo.Kryo;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Flow Manager class for handling the network flows.
- */
-public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
-
-    private boolean enableOnrc2014MeasurementsFlows = false;
-
-    protected DBOperation dbHandlerApi;
-    protected DBOperation dbHandlerInner;
-
-    protected volatile IFloodlightProviderService floodlightProvider;
-    protected volatile IDatagridService datagridService;
-    protected IRestApiService restApi;
-    protected FloodlightModuleContext context;
-    protected FlowEventHandler flowEventHandler;
-
-    protected IFlowPusherService pusherService;
-    protected IForwardingService forwardingService;
-    protected IControllerRegistryService registryService;
-
-    private KryoFactory kryoFactory = new KryoFactory();
-
-    /** The logger. */
-    private final static Logger log = LoggerFactory.getLogger(FlowManager.class);
-
-    // The queue to write Flow Entries to the database
-    private BlockingQueue<FlowPath> flowPathsToDatabaseQueue =
-	new LinkedBlockingQueue<FlowPath>();
-    FlowDatabaseWriter flowDatabaseWriter;
-
-    /**
-     * Initialize the Flow Manager.
-     *
-     * @param conf the Graph Database configuration string.
-     */
-    @Override
-    public void init(final String dbStore, final String conf) {
-	dbHandlerApi = GraphDBManager.getDBOperation();
-	dbHandlerInner = GraphDBManager.getDBOperation();
-    }
-
-    /**
-     * Shutdown the Flow Manager operation.
-     */
-    @Override
-    protected void finalize() {
-    	close();
-    }
-
-    /**
-     * Shutdown the Flow Manager operation.
-     */
-    @Override
-    public void close() {
-	floodlightProvider.removeOFSwitchListener(flowEventHandler);
-	datagridService.deregisterFlowEventHandlerService(flowEventHandler);
-    	dbHandlerApi.close();
-    	dbHandlerInner.close();
-    }
-
-    /**
-     * Get the collection of offered module services.
-     *
-     * @return the collection of offered module services.
-     */
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l =
-            new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IFlowService.class);
-        return l;
-    }
-
-    /**
-     * Get the collection of implemented services.
-     *
-     * @return the collection of implemented services.
-     */
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-			       getServiceImpls() {
-        Map<Class<? extends IFloodlightService>,
-	    IFloodlightService> m =
-	    new HashMap<Class<? extends IFloodlightService>,
-	    IFloodlightService>();
-        m.put(IFlowService.class, this);
-        return m;
-    }
-
-    /**
-     * Get the collection of modules this module depends on.
-     *
-     * @return the collection of modules this module depends on.
-     */
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-				      getModuleDependencies() {
-	Collection<Class<? extends IFloodlightService>> l =
-	    new ArrayList<Class<? extends IFloodlightService>>();
-	l.add(IFloodlightProviderService.class);
-	l.add(IDatagridService.class);
-	l.add(IRestApiService.class);
-	l.add(IFlowPusherService.class);
-	l.add(IControllerRegistryService.class);
-	//
-	// TODO: Comment-out the dependency on the IForwardingService,
-	// because it is an optional module. Apparently, adding the dependency
-	// here automatically enables the module.
-	//
-	// l.add(IForwardingService.class);
-        return l;
-    }
-
-    /**
-     * Initialize the module.
-     *
-     * @param context the module context to use for the initialization.
-     */
-    @Override
-    public void init(FloodlightModuleContext context)
-	throws FloodlightModuleException {
-	this.context = context;
-	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
-	datagridService = context.getServiceImpl(IDatagridService.class);
-	restApi = context.getServiceImpl(IRestApiService.class);
-	pusherService = context.getServiceImpl(IFlowPusherService.class);
-	forwardingService = context.getServiceImpl(IForwardingService.class);
-	registryService = context.getServiceImpl(IControllerRegistryService.class);
-
-	this.init("","");
-    }
-
-    /**
-     * Startup module operation.
-     *
-     * @param context the module context to use for the startup.
-     */
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-	restApi.addRestletRoutable(new FlowWebRoutable());
-
-	//
-	// The thread to write to the database
-	//
-	flowDatabaseWriter = new FlowDatabaseWriter(this,
-						flowPathsToDatabaseQueue);
-	flowDatabaseWriter.start();
-
-	//
-	// The Flow Event Handler thread:
-	//  - create
-	//  - register with the Datagrid Service
-	//  - startup
-	//
-	flowEventHandler = new FlowEventHandler(this, datagridService,
-						registryService);
-	floodlightProvider.addOFSwitchListener(flowEventHandler);
-	datagridService.registerFlowEventHandlerService(flowEventHandler);
-	flowEventHandler.start();
-
-	//
-	// FlowManager cleanup if cluster leader
-	//
-	if (registryService.isClusterLeader()) {
-	    boolean reuseDatabaseFlowPath = false;
-
-	    //
-	    // Deal with leftover Flow state in the database: cleanup
-	    // or push it into the switches.
-	    //
-	    do {
-		Map<String, String> configMap = context.getConfigParams(this);
-		if (configMap == null)
-		    break;
-		String operation = configMap.get("reuseDatabaseFlowPath");
-		if (operation == null)
-		    break;
-		if (operation.equals("true"))
-		    reuseDatabaseFlowPath = true;
-	    } while (false);
-
-	    if (reuseDatabaseFlowPath) {
-		// Push all flows from the database into the switches
-		log.debug("Startup Cluster Leader FlowManager: push Flow Paths to Switches");
-		//
-		// NOTE: For simplicity, we explicitly re-add all flows
-		// from the database, even if this means we are re-adding
-		// them to the database.
-		// One of the reasons is because addFlow() contains a
-		// number of sanity checks and cleanups which we don't
-		// want to repeat here; e.g., truncating Shortest Path
-		// Flow Entries which might be obsoleted.
-		//
-		ArrayList<FlowPath> flowPaths = getAllFlows();
-		for (FlowPath flowPath : flowPaths)
-		    addFlow(flowPath);
-	    } else {
-		// Delete all flows in the database
-		log.debug("Startup Cluster Leader FlowManager: cleanup Flow Paths in database");
-		deleteAllFlows();
-	    }
-	}
-    }
-
-    /**
-     * Add a flow.
-     *
-     * @param flowPath the Flow Path to install.
-     * @return the Flow ID on success, otherwise null.
-     */
-    @Override
-    public FlowId addFlow(FlowPath flowPath) {
-
-	// Allocate the Flow ID if necessary
-	if (! flowPath.isValidFlowId()) {
-	    long id = registryService.getNextUniqueId();
-	    flowPath.setFlowId(new FlowId(id));
-	}
-
-	//
-	// NOTE: We need to explicitly initialize some of the state,
-	// in case the application didn't do it.
-	//
-	for (FlowEntry flowEntry : flowPath.flowEntries()) {
-	    // The Flow Entry switch state
-	    if (flowEntry.flowEntrySwitchState() ==
-		FlowEntrySwitchState.FE_SWITCH_UNKNOWN) {
-		flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
-	    }
-	    // The Flow Entry ID
-	    if (! flowEntry.isValidFlowEntryId()) {
-		long id = registryService.getNextUniqueId();
-		flowEntry.setFlowEntryId(new FlowEntryId(id));
-	    }
-	    // The Flow ID
-	    if (! flowEntry.isValidFlowId())
-		flowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
-	}
-
-	if (FlowDatabaseOperation.addFlow(dbHandlerApi, flowPath)) {
-	    if (enableOnrc2014MeasurementsFlows) {
-		datagridService.notificationSendFlowIdAdded(flowPath.flowId(),
-							    flowPath.dataPath().srcPort().dpid());
-	    } else {
-		datagridService.notificationSendFlowAdded(flowPath);
-	    }
-
-	    return flowPath.flowId();
-	}
-	return null;
-    }
-
-    /**
-     * Delete all previously added flows.
-     *
-     * @return true on success, otherwise false.
-     */
-    @Override
-    public boolean deleteAllFlows() {
-	if (FlowDatabaseOperation.deleteAllFlows(dbHandlerApi)) {
-	    if (enableOnrc2014MeasurementsFlows) {
-		datagridService.notificationSendAllFlowIdsRemoved();
-	    } else {
-		datagridService.notificationSendAllFlowsRemoved();
-	    }
-	    return true;
-	}
-	return false;
-    }
-
-    /**
-     * Delete a previously added flow.
-     *
-     * @param flowId the Flow ID of the flow to delete.
-     * @return true on success, otherwise false.
-     */
-    @Override
-    public boolean deleteFlow(FlowId flowId) {
-	if (FlowDatabaseOperation.deleteFlow(dbHandlerApi, flowId)) {
-	    if (enableOnrc2014MeasurementsFlows) {
-		datagridService.notificationSendFlowIdRemoved(flowId);
-	    } else {
-		datagridService.notificationSendFlowRemoved(flowId);
-	    }
-	    return true;
-	}
-	return false;
-    }
-
-    /**
-     * Get a previously added flow.
-     *
-     * @param flowId the Flow ID of the flow to get.
-     * @return the Flow Path if found, otherwise null.
-     */
-    @Override
-    public FlowPath getFlow(FlowId flowId) {
-	log.debug("FlowID: {}", flowId);
-	if(flowId.value() == -100) {
-	    log.debug("Printing results...");
-	    PerformanceMonitor.report();
-	    PerformanceMonitor.clear();
-	}
-	else if(flowId.value() == -200) {
-	    log.debug("Clearing results...");
-	    PerformanceMonitor.clear();
-	}
-	return FlowDatabaseOperation.getFlow(dbHandlerApi, flowId);
-    }
-
-    /**
-     * Get a previously added flow entry.
-     *
-     * @param flowEntryId the Flow Entry ID of the flow entry to get.
-     * @return the Flow Entry if found, otherwise null.
-     */
-    public FlowEntry getFlowEntry(FlowEntryId flowEntryId) {
-	return FlowDatabaseOperation.getFlowEntry(dbHandlerApi, flowEntryId);
-    }
-
-    /**
-     * Get the source switch DPID of a previously added flow.
-     *
-     * @param flowId the Flow ID of the flow to get.
-     * @return the source switch DPID if found, otherwise null.
-     */
-    public Dpid getFlowSourceDpid(FlowId flowId) {
-	return FlowDatabaseOperation.getFlowSourceDpid(dbHandlerApi, flowId);
-    }
-
-    /**
-     * Get all installed flows by all installers.
-     *
-     * @return the Flow Paths if found, otherwise null.
-     */
-    @Override
-    public ArrayList<FlowPath> getAllFlows() {
-	return FlowDatabaseOperation.getAllFlows(dbHandlerApi);
-    }
-
-    /**
-     * Get all installed flows whose Source Switch is controlled by this
-     * instance.
-     *
-     * @param mySwitches the collection of the switches controlled by this
-     * instance.
-     * @return the Flow Paths if found, otherwise null.
-     */
-    public ArrayList<FlowPath> getAllMyFlows(Map<Long, IOFSwitch> mySwitches) {
-	return FlowDatabaseOperation.getAllMyFlows(dbHandlerApi, mySwitches);
-    }
-
-    /**
-     * Get summary of all installed flows by all installers in a given range.
-     *
-     * @param flowId the Flow ID of the first flow in the flow range to get.
-     * @param maxFlows the maximum number of flows to be returned.
-     * @return the Flow Paths if found, otherwise null.
-     */
-    @Override
-    public ArrayList<FlowPath> getAllFlowsSummary(FlowId flowId,
-						  int maxFlows) {
-    	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-	SortedMap<Long, FlowPath> sortedFlowPaths =
-	    new TreeMap<Long, FlowPath>();
-
-	if (enableOnrc2014MeasurementsFlows) {
-	    Collection<FlowPath> databaseFlowPaths =
-		ParallelFlowDatabaseOperation.getAllFlows(dbHandlerApi);
-	    for (FlowPath flowPath : databaseFlowPaths) {
-		sortedFlowPaths.put(flowPath.flowId().value(), flowPath);
-	    }
-	} else {
-	    sortedFlowPaths = flowEventHandler.getAllFlowPathsCopy();
-	}
-
-	//
-	// Truncate each Flow Path and Flow Entry
-	//
-	for (FlowPath flowPath : sortedFlowPaths.values()) {
-	    //
-	    // TODO: Add only the Flow Paths that have been successfully
-	    // installed.
-	    //
-	    flowPath.setFlowEntryMatch(null);
-	    flowPath.setFlowEntryActions(null);
-	    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-		flowEntry.setFlowEntryMatch(null);
-		flowEntry.setFlowEntryActions(null);
-	    }
-	    flowPaths.add(flowPath);
-	}
-
-	return flowPaths;
-    }
-
-    /**
-     * Get the collection of my switches.
-     *
-     * @return the collection of my switches.
-     */
-    public Map<Long, IOFSwitch> getMySwitches() {
-	return floodlightProvider.getSwitches();
-    }
-
-    /**
-     * Get the network topology.
-     *
-     * @return the network topology.
-     */
-    @Override
-    public Topology getTopology() {
-	return flowEventHandler.getTopology();
-    }
-
-    /**
-     * Inform the Flow Manager that a Flow Entry on switch expired.
-     *
-     * @param sw the switch the Flow Entry expired on.
-     * @param flowEntryId the Flow Entry ID of the expired Flow Entry.
-     */
-    @Override
-    public void flowEntryOnSwitchExpired(IOFSwitch sw,
-					 FlowEntryId flowEntryId) {
-	// Find the Flow Entry
-	FlowEntry flowEntry = datagridService.getFlowEntry(flowEntryId);
-	if (flowEntry == null)
-	    return;		// Flow Entry not found
-
-	// Find the Flow Path
-	FlowPath flowPath = datagridService.getFlow(flowEntry.flowId());
-	if (flowPath == null)
-	    return;		// Flow Path not found
-
-	//
-	// Remove the Flow if the Flow Entry expired on the first switch
-	//
-	Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
-	if (srcDpid.value() != sw.getId())
-	    return;
-	deleteFlow(flowPath.flowId());
-	
-	// Send flow deleted notification to the Forwarding module
-	// TODO This is a quick fix for flow-removed notifications. We
-	// should think more about the design of these notifications.
-	notificationFlowPathRemoved(flowPath);
-    }
-
-    /**
-     * Inform the Flow Manager that a collection of Flow Entries have been
-     * pushed to a switch.
-     *
-     * @param entries the collection of <IOFSwitch, FlowEntry> pairs
-     * that have been pushed.
-     */
-    @Override
-    public void flowEntriesPushedToSwitch(
-		Collection<Pair<IOFSwitch, FlowEntry>> entries) {
-
-	if (enableOnrc2014MeasurementsFlows)
-	    return;
-
-	//
-	// Process all entries
-	//
-	// TODO: For now we have to create an explicit FlowEntry copy so
-	// we don't modify the original FlowEntry.
-	// This should go away after we start using the OpenFlow Barrier
-	// mechnanism in the FlowPusher.
-	//
-	Kryo kryo = kryoFactory.newKryo();
-	for (Pair<IOFSwitch, FlowEntry> entry : entries) {
-	    FlowEntry flowEntry = entry.second;
-
-	    //
-	    // Mark the Flow Entry that it has been pushed to the switch
-	    //
-	    FlowEntry copyFlowEntry = kryo.copy(flowEntry);
-	    copyFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
-
-	    //
-	    // Write the Flow Entry to the Datagrid
-	    //
-	    switch (copyFlowEntry.flowEntryUserState()) {
-	    case FE_USER_ADD:
-		datagridService.notificationSendFlowEntryAdded(copyFlowEntry);
-		break;
-	    case FE_USER_MODIFY:
-		datagridService.notificationSendFlowEntryUpdated(copyFlowEntry);
-		break;
-	    case FE_USER_DELETE:
-		datagridService.notificationSendFlowEntryRemoved(copyFlowEntry.flowEntryId());
-		break;
-	    case FE_USER_UNKNOWN:
-		assert(false);
-		break;
-	    }
-	}
-	kryoFactory.deleteKryo(kryo);
-    }
-
-    /**
-     * Generate a notification that a collection of Flow Paths has been
-     * installed in the network.
-     *
-     * @param flowPaths the collection of installed Flow Paths.
-     */
-    void notificationFlowPathsInstalled(Collection<FlowPath> flowPaths) {
-	//
-	// TODO: Add an explicit check for null pointer, because
-	// the IForwardingService is optional. Remove the "if" statement
-	// after hte Forwarding Module becomes mandatory.
-	//
-	if (forwardingService != null)
-	    forwardingService.flowsInstalled(flowPaths);
-    }
-
-    /**
-     * Generate a notification that a FlowPath has been removed from the 
-     * network. This means we've received an expiry message for the flow
-     * from the switch, and send flowmods to remove any remaining parts of
-     * the path.
-     * 
-     * @param flowPath FlowPath object that was removed from the network.
-     */
-    void notificationFlowPathRemoved(FlowPath flowPath) {
-	if (forwardingService != null) {
-		forwardingService.flowRemoved(flowPath);
-	}
-    }
-
-    /**
-     * Push modified Flow-related state as appropriate.
-     *
-     * @param modifiedFlowPaths the collection of modified Flow Paths.
-     * @param modifiedFlowEntries the collection of modified Flow Entries.
-     */
-    void pushModifiedFlowState(Collection<FlowPath> modifiedFlowPaths,
-			       Collection<FlowEntry> modifiedFlowEntries) {
-	//
-	// Push the modified Flow state:
-	//  - Flow Entries to switches and the datagrid
-	//  - Flow Paths to the database
-	//
-	pushModifiedFlowEntriesToSwitches(modifiedFlowEntries);
-	if (enableOnrc2014MeasurementsFlows) {
-	    writeModifiedFlowPathsToDatabase(modifiedFlowPaths);
-	} else {
-	    pushModifiedFlowPathsToDatabase(modifiedFlowPaths);
-	    cleanupDeletedFlowEntriesFromDatagrid(modifiedFlowEntries);
-	}
-    }
-
-    /**
-     * Push modified Flow Entries to switches.
-     *
-     * NOTE: Only the Flow Entries to switches controlled by this instance
-     * are pushed.
-     *
-     * @param modifiedFlowEntries the collection of modified Flow Entries.
-     */
-    void pushModifiedFlowEntriesToSwitches(
-			Collection<FlowEntry> modifiedFlowEntries) {
-	if (modifiedFlowEntries.isEmpty())
-	    return;
-
-	List<Pair<IOFSwitch, FlowEntry>> entries =
-	    new LinkedList<Pair<IOFSwitch, FlowEntry>>();
-
-	Map<Long, IOFSwitch> mySwitches = getMySwitches();
-
-	//
-	// Create a collection of my Flow Entries to push
-	//
-	for (FlowEntry flowEntry : modifiedFlowEntries) {
-	    IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
-	    if (mySwitch == null)
-		continue;
-
-	    if (flowEntry.flowEntrySwitchState() ==
-		FlowEntrySwitchState.FE_SWITCH_UPDATED) {
-		//
-		// Don't push again Flow Entries that were already already
-		// installed into the switches.
-		//
-		continue;
-	    }
-
-	    //
-	    // Assign Flow Entry IDs if missing.
-	    //
-	    // NOTE: This is an additional safeguard, in case the
-	    // mySwitches set has changed (after the Flow Entry IDs
-	    // assignments by the caller).
-	    //
-	    if (! flowEntry.isValidFlowEntryId()) {
-		long id = registryService.getNextUniqueId();
-		flowEntry.setFlowEntryId(new FlowEntryId(id));
-	    }
-
-	    log.debug("Pushing Flow Entry To Switch: {}", flowEntry);
-	    entries.add(new Pair<IOFSwitch, FlowEntry>(mySwitch, flowEntry));
-	}
-
-	pusherService.pushFlowEntries(entries);
-    }
-
-    /**
-     * Cleanup deleted Flow Entries from the datagrid.
-     *
-     * NOTE: We cleanup only the Flow Entries that are not for our switches.
-     * This is needed to handle the case a switch going down:
-     * It has no Master controller instance, hence no controller instance
-     * will cleanup its flow entries.
-     * This is sub-optimal: we need to elect a controller instance to handle
-     * the cleanup of such orphaned flow entries.
-     *
-     * @param modifiedFlowEntries the collection of modified Flow Entries.
-     */
-    private void cleanupDeletedFlowEntriesFromDatagrid(
-			Collection<FlowEntry> modifiedFlowEntries) {
-	if (modifiedFlowEntries.isEmpty())
-	    return;
-
-	Map<Long, IOFSwitch> mySwitches = getMySwitches();
-
-	for (FlowEntry flowEntry : modifiedFlowEntries) {
-	    //
-	    // Process only Flow Entries that should be deleted and have
-	    // a valid Flow Entry ID.
-	    //
-	    if (! flowEntry.isValidFlowEntryId())
-		continue;
-	    if (flowEntry.flowEntryUserState() !=
-		FlowEntryUserState.FE_USER_DELETE) {
-		continue;
-	    }
-
-	    //
-	    // NOTE: The deletion of Flow Entries for my switches is handled
-	    // elsewhere.
-	    //
-	    IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
-	    if (mySwitch != null)
-		continue;
-
-	    log.debug("Pushing cleanup of Flow Entry To Datagrid: {}", flowEntry);
-
-	    //
-	    // Write the Flow Entry to the Datagrid
-	    //
-	    datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
-	}
-    }
-
-    /**
-     * Class to implement writing to the database in a separate thread.
-     */
-    class FlowDatabaseWriter extends Thread {
-	private FlowManager flowManager;
-	private BlockingQueue<FlowPath> blockingQueue;
-
-	/**
-	 * Constructor.
-	 *
-	 * @param flowManager the Flow Manager to use.
-	 * @param blockingQueue the blocking queue to use.
-	 */
-	FlowDatabaseWriter(FlowManager flowManager,
-			   BlockingQueue<FlowPath> blockingQueue) {
-	    this.flowManager = flowManager;
-	    this.blockingQueue = blockingQueue;
-	}
-
-	/**
-	 * Run the thread.
-	 */
-	@Override
-	public void run() {
-	    //
-	    // The main loop
-	    //
-	    Collection<FlowPath> collection = new LinkedList<FlowPath>();
-	    this.setName("FlowDatabaseWriter " + this.getId() );
-	    try {
-		while (true) {
-		    FlowPath flowPath = blockingQueue.take();
-		    collection.add(flowPath);
-		    blockingQueue.drainTo(collection);
-		    flowManager.writeModifiedFlowPathsToDatabase(collection);
-		    collection.clear();
-		}
-	    } catch (Exception exception) {
-		log.debug("Exception writing to the Database: ", exception);
-	    }
-	}
-    }
-
-    /**
-     * Push Flow Paths to the Network MAP.
-     *
-     * NOTE: The complete Flow Paths are pushed only on the instance
-     * responsible for the first switch. This is to avoid database errors
-     * when multiple instances are writing Flow Entries for the same Flow Path.
-     *
-     * @param modifiedFlowPaths the collection of Flow Paths to push.
-     */
-    private void pushModifiedFlowPathsToDatabase(
-		Collection<FlowPath> modifiedFlowPaths) {
-	List<FlowPath> copiedFlowPaths = new LinkedList<FlowPath>();
-
-	//
-	// Create a copy of the Flow Paths to push, because the pushing
-	// itself will happen on a separate thread.
-	//
-	Kryo kryo = kryoFactory.newKryo();
-	for (FlowPath flowPath : modifiedFlowPaths) {
-	    FlowPath copyFlowPath = kryo.copy(flowPath);
-	    copiedFlowPaths.add(copyFlowPath);
-	}
-	kryoFactory.deleteKryo(kryo);
-
-	//
-	// We only add the Flow Paths to the Database Queue.
-	// The FlowDatabaseWriter thread is responsible for the actual writing.
-	//
-	flowPathsToDatabaseQueue.addAll(copiedFlowPaths);
-    }
-
-    /**
-     * Write Flow Paths to the Network MAP.
-     *
-     * NOTE: The complete Flow Paths are pushed only on the instance
-     * responsible for the first switch. This is to avoid database errors
-     * when multiple instances are writing Flow Entries for the same Flow Path.
-     *
-     * @param modifiedFlowPaths the collection of Flow Paths to write.
-     */
-    void writeModifiedFlowPathsToDatabase(
-		Collection<FlowPath> modifiedFlowPaths) {
-	if (modifiedFlowPaths.isEmpty())
-	    return;
-
-	Map<Long, IOFSwitch> mySwitches = getMySwitches();
-
-	for (FlowPath flowPath : modifiedFlowPaths) {
-	    //
-	    // Push the changes only on the instance responsible for the
-	    // first switch.
-	    //
-	    Dpid srcDpid = flowPath.dataPath().srcPort().dpid();
-	    IOFSwitch mySrcSwitch = mySwitches.get(srcDpid.value());
-	    if (mySrcSwitch == null)
-		continue;
-
-	    //
-	    // Delete the Flow Path from the Network Map
-	    //
-	    if (flowPath.flowPathUserState() ==
-		FlowPathUserState.FP_USER_DELETE) {
-		log.debug("Deleting Flow Path From Database: {}", flowPath);
-
-		boolean retry = false;
-		do {
-		    retry = false;
-		    try {
-			if (! FlowDatabaseOperation.deleteFlow(
-						dbHandlerInner,
-						flowPath.flowId())) {
-			    log.error("Cannot delete Flow Path {} from Network Map",
-				      flowPath.flowId());
-			    retry = true;
-			}
-		    } catch (TitanException te) {
-			log.error("Titan Exception deleting Flow Path from Network MAP: {}", te);
-			retry = true;
-		    } catch (Exception e) {
-			log.error("Exception deleting Flow Path from Network MAP: {}", e);
-		    }
-		} while (retry);
-
-		continue;
-	    }
-
-	    //
-	    // Test whether all Flow Entries are valid
-	    //
-	    boolean allValid = true;
-	    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-		if (flowEntry.flowEntryUserState() ==
-		    FlowEntryUserState.FE_USER_DELETE) {
-		    continue;
-		}
-		if (! flowEntry.isValidFlowEntryId()) {
-		    allValid = false;
-		    break;
-		}
-		if (! enableOnrc2014MeasurementsFlows) {
-		    if (flowEntry.flowEntrySwitchState() !=
-			FlowEntrySwitchState.FE_SWITCH_UPDATED) {
-			allValid = false;
-			break;
-		    }
-		}
-	    }
-	    if (! allValid)
-		continue;
-
-	    log.debug("Pushing Flow Path To Database: {}", flowPath);
-
-	    //
-	    // Write the Flow Path to the Network Map
-	    //
-	    boolean retry = false;
-	    do {
-		retry = false;
-		try {
-                    long startTime = System.nanoTime();
-		    if (! FlowDatabaseOperation.addFlow(dbHandlerInner, flowPath)) {
-			log.error("Cannot write to Network Map Flow Path {}", flowPath.flowId());
-			retry = true;
-		    }
- 		    // FIXME Flag to turn ON logging
-                    //long endTime = System.nanoTime();
-                    //log.error("Performance %% Flow path total time {} : {}", endTime - startTime, flowPath.toString());
-		} catch (TitanException te) {
-		    log.error("Titan Exception writing Flow Path to Network MAP: ", te);
-		    retry = true;
- 		    // FIXME Flag to turn ON logging
-                    //long endTime = System.nanoTime();
-                    //log.error("Performance %% Flow path total time {} : {}", endTime - startTime, flowPath.toString());
-		} catch (Exception e) {
-		    log.error("Exception writing Flow Path to Network MAP: ", e);
- 		    // FIXME Flag to turn ON logging
-                    //long endTime = System.nanoTime();
-                    //log.error("Performance %% Flow path total time {} : {}", endTime - startTime, flowPath.toString());
-		}
-	    } while (retry);
-
-	    if (enableOnrc2014MeasurementsFlows) {
-		// Send the notifications
-
-		for (FlowEntry flowEntry : flowPath.flowEntries()) {
-		    if (flowEntry.flowEntrySwitchState() !=
-			FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
-			continue;
-		    }
-		    // datagridService.notificationSendFlowEntryIdAdded(flowEntry.flowEntryId(), flowEntry.dpid());
-
-		    //
-		    // Write the Flow Entry to the Datagrid
-		    //
-		    switch (flowEntry.flowEntryUserState()) {
-		    case FE_USER_ADD:
-			datagridService.notificationSendFlowEntryAdded(flowEntry);
-			break;
-		    case FE_USER_MODIFY:
-			datagridService.notificationSendFlowEntryUpdated(flowEntry);
-			break;
-		    case FE_USER_DELETE:
-			datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
-			break;
-		    case FE_USER_UNKNOWN:
-			assert(false);
-			break;
-		    }
-		}
-	    }
-	}
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowPathProperty.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowPathProperty.java
deleted file mode 100644
index 3b74cbb..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowPathProperty.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
-
-public class FlowPathProperty {
-	private Map<String, Object> map = new HashMap<>();
-
-	public void setType(String typeStr) {
-		map.put("type", typeStr);
-	}
-
-	public void setFlowId(String flowId) {
-		map.put("flow_id", flowId);
-	}
-
-	public void setInstallerId(String installerId) {
-		map.put("installer_id", installerId);
-	}
-
-	public void setFlowPathType(String flowPathType) {
-		map.put("flow_path_type", flowPathType);
-	}
-
-	public void setFlowPathUserState(String userState) {
-		map.put("user_state", userState);
-	}
-
-	public void setFlowPathFlags(Long flowPathFlags) {
-		map.put("flow_path_flags", flowPathFlags);
-	}
-
-	public void setIdleTimeout(Integer idleTimeout) {
-		map.put("idle_timeout", idleTimeout);
-	}
-
-	public void setHardTimeout(Integer hardTimeout) {
-		map.put("hard_timeout", hardTimeout);
-	}
-
-	public void setPriority(Integer priority) {
-		map.put("priority", priority);
-	}
-
-	public void setSrcSwitch(String srcSwitch) {
-		map.put("src_switch", srcSwitch);
-	}
-
-	public void setSrcPort(Short srcPort) {
-		map.put("src_port", srcPort);
-	}
-
-	public void setDstSwitch(String dstSwitch) {
-		map.put("dst_switch", dstSwitch);
-	}
-
-	public void setDstPort(Short dstPort) {
-		map.put("dst_port", dstPort);
-	}
-
-	public void setMatchSrcMac(String matchSrcMac) {
-		map.put("matchSrcMac", matchSrcMac);
-	}
-
-	public void setMatchDstMac(String matchDstMac) {
-		map.put("matchDstMac", matchDstMac);
-	}
-
-	public void setMatchEthernetFrameType(Short matchEthernetFrameType) {
-		map.put("matchEthernetFrameType", matchEthernetFrameType);
-	}
-
-	public void setMatchVlanId(Short matchVlanId) {
-		map.put("matchVlanId", matchVlanId);
-	}
-
-	public void setMatchVlanPriority(Byte matchVlanPriority) {
-		map.put("matchVlanPriority", matchVlanPriority);
-	}
-
-	public void setMatchSrcIPv4Net(String matchSrcIPv4Net) {
-		map.put("matchSrcIPv4Net", matchSrcIPv4Net);
-	}
-
-	public void setMatchDstIPv4Net(String matchDstIPv4Net) {
-		map.put("matchDstIPv4Net", matchDstIPv4Net);
-	}
-
-	public void setMatchIpProto(Byte matchIpProto) {
-		map.put("matchIpProto", matchIpProto);
-	}
-
-	public void setMatchIpToS(Byte matchIpToS) {
-		map.put("matchIpToS", matchIpToS);
-	}
-
-	public void setMatchSrcTcpUdpPort(Short matchSrcTcpUdpPort) {
-		map.put("matchSrcTcpUdpPort", matchSrcTcpUdpPort);
-	}
-
-	public void setMatchDstTcpUdpPort(Short matchDstTcpUdpPort) {
-		map.put("matchDstTcpUdpPort", matchDstTcpUdpPort);
-	}
-
-	public void setActions(String actionsStr) {
-		map.put("actions", actionsStr);
-	}
-    
-    /**
-     *
-     * @param dbhandler
-     */
-    public void commitProperties(DBOperation dbhandler, IFlowPath flowPath) {
-        dbhandler.setVertexProperties(flowPath.asVertex() ,map);
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowEventHandlerService.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowEventHandlerService.java
deleted file mode 100644
index a44a898..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowEventHandlerService.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import net.onrc.onos.ofcontroller.topology.TopologyElement;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntryId;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-
-/**
- * Interface for providing Flow Event Handler Service to other modules.
- */
-public interface IFlowEventHandlerService {
-    /**
-     * Receive a notification that a Flow is added.
-     *
-     * @param flowPath the Flow that is added.
-     */
-    void notificationRecvFlowAdded(FlowPath flowPath);
-
-    /**
-     * Receive a notification that a Flow is removed.
-     *
-     * @param flowPath the Flow that is removed.
-     */
-    void notificationRecvFlowRemoved(FlowPath flowPath);
-
-    /**
-     * Receive a notification that a Flow is updated.
-     *
-     * @param flowPath the Flow that is updated.
-     */
-    void notificationRecvFlowUpdated(FlowPath flowPath);
-
-    /**
-     * Receive a notification that a FlowEntry is added.
-     *
-     * @param flowEntry the FlowEntry that is added.
-     */
-    void notificationRecvFlowEntryAdded(FlowEntry flowEntry);
-
-    /**
-     * Receive a notification that a FlowEntry is removed.
-     *
-     * @param flowEntry the FlowEntry that is removed.
-     */
-    void notificationRecvFlowEntryRemoved(FlowEntry flowEntry);
-
-    /**
-     * Receive a notification that a FlowEntry is updated.
-     *
-     * @param flowEntry the FlowEntry that is updated.
-     */
-    void notificationRecvFlowEntryUpdated(FlowEntry flowEntry);
-
-    /**
-     * Receive a notification that a FlowId is added.
-     *
-     * @param flowId the FlowId that is added.
-     * @param dpid the Source Switch Dpid for the corresponding Flow.
-     */
-    void notificationRecvFlowIdAdded(FlowId flowId, Dpid dpid);
-
-    /**
-     * Receive a notification that a FlowId is removed.
-     *
-     * @param flowId the FlowId that is removed.
-     * @param dpid the Source Switch Dpid for the corresponding Flow.
-     */
-    void notificationRecvFlowIdRemoved(FlowId flowId, Dpid dpid);
-
-    /**
-     * Receive a notification that a FlowId is updated.
-     *
-     * @param flowId the FlowId that is updated.
-     * @param dpid the Source Switch Dpid for the corresponding Flow.
-     */
-    void notificationRecvFlowIdUpdated(FlowId flowId, Dpid dpid);
-
-    /**
-     * Receive a notification that a FlowEntryId is added.
-     *
-     * @param flowEntryId the FlowEntryId that is added.
-     * @param dpid the Switch Dpid for the corresponding Flow Entry.
-     */
-    void notificationRecvFlowEntryIdAdded(FlowEntryId flowEntryId, Dpid dpid);
-
-    /**
-     * Receive a notification that a FlowEntryId is removed.
-     *
-     * @param flowEntryId the FlowEntryId that is removed.
-     * @param dpid the Switch Dpid for the corresponding Flow Entry.
-     */
-    void notificationRecvFlowEntryIdRemoved(FlowEntryId flowEntryId,
-					    Dpid dpid);
-
-    /**
-     * Receive a notification that a FlowEntryId is updated.
-     *
-     * @param flowEntryId the FlowEntryId that is updated.
-     * @param dpid the Switch Dpid for the corresponding Flow Entry.
-     */
-    void notificationRecvFlowEntryIdUpdated(FlowEntryId flowEntryId,
-					    Dpid dpid);
-
-    /**
-     * Receive a notification that a Topology Element is added.
-     *
-     * @param topologyElement the Topology Element that is added.
-     */
-    void notificationRecvTopologyElementAdded(TopologyElement topologyElement);
-
-    /**
-     * Receive a notification that a Topology Element is removed.
-     *
-     * @param topologyElement the Topology Element that is removed.
-     */
-    void notificationRecvTopologyElementRemoved(TopologyElement topologyElement);
-
-    /**
-     * Receive a notification that a Topology Element is updated.
-     *
-     * @param topologyElement the Topology Element that is updated.
-     */
-    void notificationRecvTopologyElementUpdated(TopologyElement topologyElement);
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
deleted file mode 100644
index d6a5db1..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.onrc.onos.ofcontroller.topology.Topology;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntryId;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.Pair;
-
-/**
- * Interface for providing Flow Service to other modules.
- */
-public interface IFlowService extends IFloodlightService {
-    /**
-     * Add a flow.
-     *
-     * @param flowPath the Flow Path to install.
-     * @return the Flow ID on success, otherwise null.
-     */
-    FlowId addFlow(FlowPath flowPath);
-
-    /**
-     * Delete all previously added flows.
-     *
-     * @return true on success, otherwise false.
-     */
-    boolean deleteAllFlows();
-
-    /**
-     * Delete a previously added flow.
-     *
-     * @param flowId the Flow ID of the flow to delete.
-     * @return true on success, otherwise false.
-     */
-    boolean deleteFlow(FlowId flowId);
-
-    /**
-     * Get a previously added flow.
-     *
-     * @param flowId the Flow ID of the flow to get.
-     * @return the Flow Path if found, otherwise null.
-     */
-    FlowPath getFlow(FlowId flowId);
-
-    /**
-     * Get all installed flows by all installers.
-     *
-     * @return the Flow Paths if found, otherwise null.
-     */
-    ArrayList<FlowPath> getAllFlows();
-
-    /**
-     * Get summary of all installed flows by all installers.
-     *
-     * @param flowId starting flow Id of the range
-     * @param maxFlows number of flows to return
-     * @return the Flow Paths if found, otherwise null.
-     */
-    ArrayList<FlowPath> getAllFlowsSummary(FlowId flowId, int maxFlows);
-
-    /**
-     * Get the network topology.
-     *
-     * @return the network topology.
-     */
-    Topology getTopology();
-
-    /**
-     * Inform the Flow Manager that a Flow Entry on switch expired.
-     *
-     * @param sw the switch the Flow Entry expired on.
-     * @param flowEntryId the Flow Entry ID of the expired Flow Entry.
-     */
-    public void flowEntryOnSwitchExpired(IOFSwitch sw, FlowEntryId flowEntryId);
-
-    /**
-     * Inform the Flow Manager that a collection of Flow Entries have been
-     * pushed to a switch.
-     *
-     * @param entries the collection of <IOFSwitch, FlowEntry> pairs
-     * that have been pushed.
-     */
-    public void flowEntriesPushedToSwitch(
-			Collection<Pair<IOFSwitch, FlowEntry>> entries);
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/ParallelFlowDatabaseOperation.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/ParallelFlowDatabaseOperation.java
deleted file mode 100644
index b5fd95d..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/ParallelFlowDatabaseOperation.java
+++ /dev/null
@@ -1,395 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CompletionService;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import net.onrc.onos.datagrid.IDatagridService;
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.PerformanceMonitor;
-import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
-
-import com.esotericsoftware.kryo.Kryo;
-
-/**
- * Class for performing parallel Flow-related operations on the Database.
- * 
- * This class is mostly a wrapper of FlowDatabaseOperation with a thread pool
- * for parallelization.
- * 
- * @author Brian O'Connor <brian@onlab.us>
- */
-public class ParallelFlowDatabaseOperation extends FlowDatabaseOperation {
-    private final static Logger log = LoggerFactory.getLogger(FlowDatabaseOperation.class);
-
-    private final static int numThreads = Integer.valueOf(System.getProperty("parallelFlowDatabase.numThreads", "32"));
-    private final static ExecutorService executor = Executors.newFixedThreadPool(numThreads);
-
-    private static KryoFactory kryoFactory = new KryoFactory();
-
-    /**
-     * Get all installed flows by first querying the database for all FlowPaths
-     * and then populating them from the database in parallel.
-     * 
-     * @param dbHandler the Graph Database handler to use.
-     * @return the Flow Paths if found, otherwise an empty list.
-     */
-    static ArrayList<FlowPath> getAllFlows(DBOperation dbHandler) {
-	Iterable<IFlowPath> flowPathsObj = null;
-	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
-	try {
-	    flowPathsObj = dbHandler.getAllFlowPaths();
-	} catch (Exception e) {
-	    // TODO: handle exceptions
-	    dbHandler.rollback();
-	    log.error(":getAllFlowPaths failed");
-	    return flowPaths;
-	}
-	if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
-	    dbHandler.commit();
-	    return flowPaths;	// No Flows found
-	}
-	
-	CompletionService<FlowPath> tasks = new ExecutorCompletionService<>(executor);
-	int numTasks = 0;
-	for(IFlowPath flowObj : flowPathsObj) {
-	    tasks.submit(new ExtractFlowTask(flowObj));
-	    numTasks++;
-	}
-	for(int i = 0; i < numTasks; i++) {
-	    try {
-		FlowPath flowPath = tasks.take().get();
-		if(flowPath != null) {
-		    flowPaths.add(flowPath);
-		}
-	    } catch (InterruptedException | ExecutionException e) {
-		log.error("Error reading FlowPath from IFlowPath object");
-	    }
-	}
-	dbHandler.commit();
-	return flowPaths;	
-    }
-    
-    /**
-     * Query the database for all flow paths that have their source switch
-     * in the provided collection
-     * 
-     * Note: this function is implemented naively and inefficiently
-     * 
-     * @param dbHandler the Graph Database handler to use.
-     * @param switches a collection of switches whose flow paths you want
-     * @return the Flow Paths if found, otherwise an empty list.
-     */
-    static ArrayList<FlowPath> getFlowsForSwitches(DBOperation dbHandler, Collection<Dpid> switches) {
-	Iterable<IFlowPath> flowPathsObj = null;
-	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
-	try {
-	    flowPathsObj = dbHandler.getAllFlowPaths();
-	} catch (Exception e) {
-	    // TODO: handle exceptions
-	    dbHandler.rollback();
-	    log.error(":getAllFlowPaths failed");
-	    return flowPaths;
-	}
-	if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
-	    dbHandler.commit();
-	    return flowPaths;	// No Flows found
-	}
-	
-	// convert the collection of switch dpids into a set of strings
-	Set<String> switchSet = new HashSet<>();
-	for(Dpid dpid : switches) {
-	    switchSet.add(dpid.toString());
-	}
-	
-	CompletionService<FlowPath> tasks = new ExecutorCompletionService<>(executor);
-	int numTasks = 0;
-	for(IFlowPath flowObj : flowPathsObj) {
-	    if(switchSet.contains(flowObj.getSrcSwitch())) {
-		tasks.submit(new ExtractFlowTask(flowObj));
-		numTasks++;
-	    }
-	}
-	for(int i = 0; i < numTasks; i++) {
-	    try {
-		FlowPath flowPath = tasks.take().get();
-		if(flowPath != null) {
-		    flowPaths.add(flowPath);
-		}
-	    } catch (InterruptedException | ExecutionException e) {
-		log.error("Error reading FlowPath from IFlowPath object");
-	    }
-	}
-	dbHandler.commit();
-	return flowPaths;	
-    }
-    
-    /**
-     * The basic parallelization unit for extracting FlowEntries from the database.
-     * 
-     * This is simply a wrapper for FlowDatabaseOperation.extractFlowPath()
-     */
-    private final static class ExtractFlowTask implements Callable<FlowPath> {
-	private final IFlowPath flowObj;
-	
-	ExtractFlowTask(IFlowPath flowObj){
-	    this.flowObj = flowObj;
-	}
-	@Override 
-	public FlowPath call() throws Exception {
-	    return extractFlowPath(flowObj);
-	}
-    }
-
-    /**
-     * Get a subset of installed flows in parallel.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowIds the collection of Flow IDs to get.
-     * @return the Flow Paths if found, otherwise an empty list.
-     */
-    static ArrayList<FlowPath> getFlows(DBOperation dbHandler,
-		  			Collection<FlowId> flowIds) {
-	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
-
-	CompletionService<FlowPath> tasks = new ExecutorCompletionService<>(executor);
-	int numTasks = 0;
-	for (FlowId flowId : flowIds) {
-	    tasks.submit(new GetFlowTask(dbHandler, flowId));
-	    numTasks++;
-	}
-	for(int i = 0; i < numTasks; i++) {
-	    try {
-		FlowPath flowPath = tasks.take().get();
-		if(flowPath != null) {
-		    flowPaths.add(flowPath);
-		}
-	    } catch (InterruptedException | ExecutionException e) {
-		log.error("Error reading FlowPath from database");
-	    }
-	}
-	// TODO: should we commit?
-	//dbHandler.commit();
-	return flowPaths;
-    }
-    
-    /**
-     * The basic parallelization unit for getting FlowEntries.
-     * 
-     * This is simply a wrapper for FlowDatabaseOperation.getFlow()
-     */
-    private final static class GetFlowTask implements Callable<FlowPath> {
-	private final DBOperation dbHandler;
-	private final FlowId flowId;
-
-	GetFlowTask(DBOperation dbHandler, FlowId flowId) {
-	    this.dbHandler = dbHandler;
-	    this.flowId = flowId;
-	}
-	@Override
-	public FlowPath call() throws Exception{
-	    return getFlow(dbHandler, flowId);
-	}
-    }
-    
-    /**
-     * Add a flow by creating a database task, then waiting for the result.
-     * Mostly, a wrapper for FlowDatabaseOperation.addFlow() which overs little
-     * performance benefit.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowPath the Flow Path to install.
-     * @return true on success, otherwise false.
-     */
-    static boolean addFlow(DBOperation dbHandler, FlowPath flowPath) {
-	Future<Boolean> result = executor.submit(new AddFlowTask(dbHandler, flowPath, null));
-	// NOTE: This function is blocking
-	try {
-	    return result.get();
-	} catch (InterruptedException | ExecutionException e) {
-	    return false;
-	}
-    }
-    
-    /**
-     * Add a flow asynchronously by creating a database task.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowPath the Flow Path to install.
-     * @param datagridService the notification service for when the task is completed
-     * @return true always
-     */
-    static boolean addFlow(DBOperation dbHandler, FlowPath flowPath, IDatagridService datagridService) {
-	executor.submit(new AddFlowTask(dbHandler, flowPath, datagridService));
-	// TODO: If we need the results, submit returns a Future that contains
-	// the result. 
-	return true;
-
-    }
-    
-    /**
-     * The basic parallelization unit for adding FlowPaths.
-     * 
-     * This is simply a wrapper for FlowDatabaseOperation.addFlow(), 
-     * which also sends a notification if a datagrid services is provided
-     */
-    private final static class AddFlowTask implements Callable<Boolean> {
-	private final DBOperation dbHandler;
-	private final FlowPath flowPath;
-	private final IDatagridService datagridService;
-
-	AddFlowTask(DBOperation dbHandler,
-		    FlowPath flowPath,
-		    IDatagridService datagridService) {
-	    this.dbHandler = dbHandler;
-
-	    // Create a copy of the FlowPath object
-	    Kryo kryo = kryoFactory.newKryo();
-	    this.flowPath = kryo.copy(flowPath);
-	    kryoFactory.deleteKryo(kryo);
-	    
-	    this.datagridService = datagridService;
-	}
-	
-	@Override
-	public Boolean call() throws Exception {
-//	    String tag1 = "FlowDatabaseOperation.AddFlow." + flowPath.flowId();
-	    String tag1 = "FlowDatabaseOperation.AddFlow";
-//	    String tag2 = "FlowDatabaseOperation.NotificationSend.FlowEntry." + flowPath.flowId();
-	    String tag2 = "FlowDatabaseOperation.NotificationSend.FlowEntry";
-	    PerformanceMonitor.Measurement m;
-	    m = PerformanceMonitor.start(tag1);
-	    boolean success = FlowDatabaseOperation.addFlow(dbHandler, flowPath);
-//	    PerformanceMonitor.stop(tag1);
-	    m.stop();
-	    m = PerformanceMonitor.start(tag2);
-	    if(success) {
-		if(datagridService != null) {
-		    // Send notifications for each Flow Entry
-		    for (FlowEntry flowEntry : flowPath.flowEntries()) {
-			if (flowEntry.flowEntrySwitchState() !=
-			    FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
-			    continue;
-			}
-			//
-			// Write the Flow Entry to the Datagrid
-			//
-			switch (flowEntry.flowEntryUserState()) {
-			case FE_USER_ADD:
-			    datagridService.notificationSendFlowEntryAdded(flowEntry);
-			    break;
-			case FE_USER_MODIFY:
-			    datagridService.notificationSendFlowEntryUpdated(flowEntry);
-			    break;
-			case FE_USER_DELETE:
-			    datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
-			    break;
-			case FE_USER_UNKNOWN:
-			    assert(false);
-			    break;
-			}
-		    }
-		}
-	    }
-	    else {
-		log.error("Error adding flow path {} to database", flowPath);
-	    }
-	    m.stop();
-//	    PerformanceMonitor.report(tag1);
-//	    PerformanceMonitor.report(tag2);
-	    return success;
-
-	}
-    }
-
-    /**
-     * Delete a previously added flow by creating a database task, then waiting 
-     * for the result.
-     * 
-     * Mostly, a wrapper for FlowDatabaseOperation.addFlow() which overs little
-     * performance benefit.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowId the Flow ID of the flow to delete.
-     * @return true on success, otherwise false.
-     */
-    static boolean deleteFlow(DBOperation dbHandler, FlowId flowId) {
-	Future<Boolean> result = executor.submit(new DeleteFlowTask(dbHandler, flowId, null));
-	// NOTE: This function is blocking
-	try {
-	    return result.get();
-	} catch (InterruptedException | ExecutionException e) {
-	    return false;
-	}
-    }    
-    
-    /**
-     * Delete a previously added flow asynchronously by creating a database task.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param flowId the Flow ID of the flow to delete.
-     * @param datagridService the notification service for when the task is completed
-     * @return true always
-     */
-    static boolean deleteFlow(DBOperation dbHandler, FlowId flowId, IDatagridService datagridService) {
-	executor.submit(new DeleteFlowTask(dbHandler, flowId, datagridService));
-	// TODO: If we need the results, submit returns a Future that contains
-	// the result. 
-	return true;
-    }
-    
-    /**
-     * The basic parallelization unit for deleting FlowPaths.
-     * 
-     * This is simply a wrapper for FlowDatabaseOperation.deleteFlow(),
-     * which also sends a notification if a datagrid services is provided
-     */
-    private final static class DeleteFlowTask implements Callable<Boolean> {
-	private final DBOperation dbHandler;
-	private final FlowId flowId;
-	private final IDatagridService datagridService;
-
-	DeleteFlowTask(DBOperation dbHandler, FlowId flowId, IDatagridService datagridService) {
-	    this.dbHandler = dbHandler;
-
-	    // Create a copy of the FlowId object
-	    Kryo kryo = kryoFactory.newKryo();
-	    this.flowId = kryo.copy(flowId);
-	    kryoFactory.deleteKryo(kryo);
-
-	    this.datagridService = datagridService;
-	}
-	@Override
-	public Boolean call() throws Exception{
-	    boolean success = FlowDatabaseOperation.deleteFlow(dbHandler, flowId);
-	    if(success) {
-		if(datagridService != null) {
-		    datagridService.notificationSendFlowIdRemoved(flowId);
-		}
-	    }
-	    else {
-		log.error("Error removing flow path {} from database", flowId);
-	    }
-	    return success;
-	}
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java
deleted file mode 100644
index 4f4c1e4..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager.web;
-
-import java.io.IOException;
-
-import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-
-import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.JsonMappingException;
-import org.restlet.resource.Post;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Flow Manager REST API implementation: Add a Flow with the Flow
- * Entries:
- *
- *   POST /wm/onos/flows/add/json
- */
-public class AddFlowResource extends ServerResource {
-
-    protected final static Logger log = LoggerFactory.getLogger(AddFlowResource.class);
-
-    /**
-     * Implement the API.
-     *
-     * @param flowJson a string with the JSON representation of the Flow to
-     * add.
-     * @return the Flow ID of the added flow.
-     */
-    @Post("json")
-    public FlowId store(String flowJson) {
-	FlowId result = new FlowId();
-
-        IFlowService flowService =
-                (IFlowService)getContext().getAttributes().
-                get(IFlowService.class.getCanonicalName());
-
-        if (flowService == null) {
-	    log.debug("ONOS Flow Service not found");
-            return result;
-	}
-
-	//
-	// Extract the arguments
-	// NOTE: The "flow" is specified in JSON format.
-	//
-	ObjectMapper mapper = new ObjectMapper();
-	String flowPathStr = flowJson;
-	FlowPath flowPath = null;
-	log.debug("Add Flow Path: {}", flowPathStr);
-	try {
-	    flowPath = mapper.readValue(flowPathStr, FlowPath.class);
-	} catch (JsonGenerationException e) {
-	    e.printStackTrace();
-	} catch (JsonMappingException e) {
-	    e.printStackTrace();
-	} catch (IOException e) {
-	    e.printStackTrace();
-	}
-
-	// Process the request
-	if (flowPath != null) {
-	    FlowId addedFlowId = flowService.addFlow(flowPath);
-	    if (addedFlowId != null)
-		result = addedFlowId;
-	}
-
-        return result;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DeleteFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DeleteFlowResource.java
deleted file mode 100644
index ab68584..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DeleteFlowResource.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager.web;
-
-import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
-import net.onrc.onos.ofcontroller.util.FlowId;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Flow Manager REST API implementation: Delete Flow state.
- *
- * The "{flow-id}" request attribute value can be either a specific Flow ID,
- * or the keyword "all" to delete all Flows:
- *
- *   GET /wm/onos/flows/delete/{flow-id}/json
- */
-public class DeleteFlowResource extends ServerResource {
-    protected final static Logger log = LoggerFactory.getLogger(DeleteFlowResource.class);
-
-    /**
-     * Implement the API.
-     *
-     * @return true on success, otehrwise false.
-     */
-    @Get("json")
-    public Boolean retrieve() {
-	Boolean result = false;
-
-        IFlowService flowService =
-                (IFlowService)getContext().getAttributes().
-                get(IFlowService.class.getCanonicalName());
-
-        if (flowService == null) {
-	    log.debug("ONOS Flow Service not found");
-            return result;
-	}
-
-	// Extract the arguments
-	String flowIdStr = (String) getRequestAttributes().get("flow-id");
-
-	// Process the request
-	if (flowIdStr.equals("all")) {
-	    log.debug("Delete All Flows");
-	    result = flowService.deleteAllFlows();
-	} else {
-	    FlowId flowId = new FlowId(flowIdStr);
-	    log.debug("Delete Flow Id: {}", flowIdStr);
-	    result = flowService.deleteFlow(flowId);
-	}
-	return result;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java
deleted file mode 100644
index 73a3936..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager.web;
-
-import net.floodlightcontroller.restserver.RestletRoutable;
-
-import org.restlet.Context;
-import org.restlet.Restlet;
-import org.restlet.routing.Router;
-
-/**
- * REST API implementation for the Flow Manager.
- */
-public class FlowWebRoutable implements RestletRoutable {
-    /**
-     * Create the Restlet router and bind to the proper resources.
-     */
-    @Override
-    public Restlet getRestlet(Context context) {
-        Router router = new Router(context);
-        router.attach("/add/json", AddFlowResource.class);
-        router.attach("/delete/{flow-id}/json", DeleteFlowResource.class);
-        router.attach("/get/{flow-id}/json", GetFlowByIdResource.class);
-        router.attach("/getall/json", GetAllFlowsResource.class);
-        router.attach("/getsummary/{flow-id}/{max-flows}/json", GetSummaryFlowsResource.class);
-        return router;
-    }
-
-    /**
-     * Set the base path for the Topology
-     */
-    @Override
-    public String basePath() {
-        return "/wm/onos/flows";
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsResource.java
deleted file mode 100644
index 91bd210..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsResource.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager.web;
-
-import java.util.ArrayList;
-
-import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Flow Manager REST API implementation: Get all Flow state.
- *
- *   GET /wm/onos/flows/getall/json"
- */
-public class GetAllFlowsResource extends ServerResource {
-    protected final static Logger log = LoggerFactory.getLogger(GetAllFlowsResource.class);
-
-    /**
-     * Implement the API.
-     *
-     * @return the collection of Flow states if any found, otherwise null.
-     */
-    @Get("json")
-    public ArrayList<FlowPath> retrieve() {
-	ArrayList<FlowPath> result = null;
-
-        IFlowService flowService =
-                (IFlowService)getContext().getAttributes().
-                get(IFlowService.class.getCanonicalName());
-
-        if (flowService == null) {
-	    log.debug("ONOS Flow Service not found");
-            return result;
-	}
-
-	// Extract the arguments
-	log.debug("Get All Flows Endpoints");
-
-	result = flowService.getAllFlows();
-
-        return result;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetFlowByIdResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetFlowByIdResource.java
deleted file mode 100644
index 1cbeece..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetFlowByIdResource.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager.web;
-
-import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
-import net.onrc.onos.ofcontroller.util.FlowId;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Flow Manager REST API implementation: Get a single Flow state.
- *
- * The "{flow-id}" request attribute value is the Flow ID of the flow to get:
- *
- *   GET /wm/onos/flows/get/{flow-id}/json
- */
-public class GetFlowByIdResource extends ServerResource {
-    protected final static Logger log = LoggerFactory.getLogger(GetFlowByIdResource.class);
-
-    /**
-     * Implement the API.
-     *
-     * @return the Flow state if the flow is found, otherwise null.
-     */
-    @Get("json")
-    public FlowPath retrieve() {
-	FlowPath result = null;
-
-        IFlowService flowService =
-                (IFlowService)getContext().getAttributes().
-                get(IFlowService.class.getCanonicalName());
-
-        if (flowService == null) {
-	    log.debug("ONOS Flow Service not found");
-            return result;
-	}
-
-	// Extract the arguments
-	String flowIdStr = (String) getRequestAttributes().get("flow-id");
-	FlowId flowId = new FlowId(flowIdStr);
-
-	log.debug("Get Flow Id: {}", flowIdStr);
-
-	result = flowService.getFlow(flowId);
-
-        return result;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetSummaryFlowsResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetSummaryFlowsResource.java
deleted file mode 100644
index aa31abd..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetSummaryFlowsResource.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package net.onrc.onos.ofcontroller.flowmanager.web;
-
-import java.util.ArrayList;
-
-import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.FlowId;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Flow Manager REST API implementation: Get summary of all installed
- * flows by all installers in a given range.
- *
- * The "{flow-id}" request attribute value is the Flow ID of the flow in the
- * flow range to get.
- * The "{max-flows}" request attribute value is the maximum number of flows
- * to be returned.
- *
- *   GET /wm/onos/flows/getsummary/{flow-id}/{max-flows}/json"
- */
-public class GetSummaryFlowsResource extends ServerResource {
-    protected final static Logger log = LoggerFactory.getLogger(GetSummaryFlowsResource.class);
-
-    /**
-     * Implement the API.
-     *
-     * @return the collection of Flow states if any found, otherwise null.
-     */
-    @Get("json")
-    public ArrayList<FlowPath> retrieve() {
-    	ArrayList<FlowPath> result = null;
-    	
-    	FlowId flowId;
-    	int maxFlows = 0;
-    	
-    	IFlowService flowService = (IFlowService)getContext().getAttributes().get(IFlowService.class.getCanonicalName());
-
-        if (flowService == null) {
-        	log.debug("ONOS Flow Service not found");
-        	return result;
-        }
-
-        // Extract the arguments
-    	String flowIdStr = (String) getRequestAttributes().get("flow-id");
-    	String maxFlowStr = (String) getRequestAttributes().get("max-flows");
-    	log.debug("Get Summary Flows starting flow-id: {} max-flows: {}" ,flowIdStr, maxFlowStr);
-
-    	flowId = new FlowId(flowIdStr);
-    	maxFlows = Integer.parseInt(maxFlowStr);
-    	if (maxFlows < 0) maxFlows = 0;
-
-        result = flowService.getAllFlowsSummary(flowId, maxFlows);
-
-        return result;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
index 3a0407f..b52bafc 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
@@ -59,7 +59,6 @@
     private final static Logger log = LoggerFactory.getLogger(FlowPusher.class);
     protected static final int DEFAULT_NUMBER_THREAD = 1;
 
-    // NOTE: Below are moved from FlowManager.
     // TODO: Values copied from elsewhere (class LearningSwitch).
     // The local copy should go away!
     //
diff --git a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
index e846155..884c717 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
@@ -353,7 +353,14 @@
 				if (existingFlow.installed) {
 					// Flow has been sent to the switches so it is safe to
 					// send a packet out now
-					FlowPath flow = datagrid.getFlow(new FlowId(existingFlow.flowId));
+
+					//
+					// TODO: The getFlow() call below needs
+					// to be updated to the new Path Intent
+					// framework.
+					//
+					// FlowPath flow = datagrid.getFlow(new FlowId(existingFlow.flowId));
+					FlowPath flow = null;
 					FlowEntry flowEntryForThisSwitch = null;
 					
 					if (flow != null) {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/forwarding/IForwardingService.java b/src/main/java/net/onrc/onos/ofcontroller/forwarding/IForwardingService.java
index 0e0d1da..92d3a18 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/forwarding/IForwardingService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/forwarding/IForwardingService.java
@@ -7,7 +7,7 @@
 
 /**
  * Temporary interface that allows the Forwarding module to be
- * notified when a flow has been installed by the FlowManager.
+ * notified when a flow has been installed.
  * 
  * This should be refactored to a listener framework in the future.
  * @author jono
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java b/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java
deleted file mode 100644
index 4269eac..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/ITopologyNetService.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package net.onrc.onos.ofcontroller.topology;
-
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.SwitchPort;
-
-/**
- * Interface for providing Topology Network Service to other modules.
- */
-public interface ITopologyNetService extends IFloodlightService {
-    /**
-     * Fetch the Switch and Ports info from the Titan Graph
-     * and return it for fast access during the shortest path
-     * computation.
-     *
-     * After fetching the state, method @ref getTopologyShortestPath()
-     * can be used for fast shortest path computation.
-     *
-     * Note: There is certain cost to fetch the state, hence it should
-     * be used only when there is a large number of shortest path
-     * computations that need to be done on the same topology.
-     * Typically, a single call to @ref newDatabaseTopology()
-     * should be followed by a large number of calls to
-     * method @ref getTopologyShortestPath().
-     * After the last @ref getTopologyShortestPath() call,
-     * method @ref dropTopology() should be used to release
-     * the internal state that is not needed anymore:
-     *
-     *       Topology topology = topologyManager.newDatabaseTopology();
-     *       for (int i = 0; i < 10000; i++) {
-     *           dataPath = topologyManager.getTopologyShortestPath(topology, ...);
-     *           ...
-     *        }
-     *        topologyManager.dropTopology(shortestPathTopo);
-     *
-     * @return the allocated topology handler.
-     */
-    Topology newDatabaseTopology();
-
-    /**
-     * Release the topology that was populated by
-     * method @ref newDatabaseTopology().
-     *
-     * See the documentation for method @ref newDatabaseTopology()
-     * for additional information and usage.
-     *
-     * @param topology the topology to release.
-     */
-    void dropTopology(Topology topology);
-
-    /**
-     * Get the shortest path from a source to a destination by
-     * using the pre-populated local topology state prepared
-     * by method @ref newDatabaseTopology().
-     *
-     * See the documentation for method @ref newDatabaseTopology()
-     * for additional information and usage.
-     *
-     * @param topology the topology handler to use.
-     * @param src the source in the shortest path computation.
-     * @param dest the destination in the shortest path computation.
-     * @return the data path with the computed shortest path if
-     * found, otherwise null.
-     */
-    DataPath getTopologyShortestPath(Topology topology,
-				     SwitchPort src, SwitchPort dest);
-
-    /**
-     * Get the shortest path from a source to a destination by using
-     * the underlying database.
-     *
-     * @param src the source in the shortest path computation.
-     * @param dest the destination in the shortest path computation.
-     * @return the data path with the computed shortest path if
-     * found, otherwise null.
-     */
-    DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest);
-
-    /**
-     * Test whether a route exists from a source to a destination.
-     *
-     * @param src the source node for the test.
-     * @param dest the destination node for the test.
-     * @return true if a route exists, otherwise false.
-     */
-    Boolean routeExists(SwitchPort src, SwitchPort dest);
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java b/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
deleted file mode 100644
index d9e1314..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
+++ /dev/null
@@ -1,329 +0,0 @@
-package net.onrc.onos.ofcontroller.topology;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
-
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
-import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.Port;
-import net.onrc.onos.ofcontroller.util.SwitchPort;
-
-import org.openflow.util.HexString;
-
-import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.Vertex;
-
-/**
- * Class to calculate a shortest DataPath between 2 SwitchPorts
- * based on hops in Network Topology.
- */
-public class ShortestPath {
-    /**
-     * Get the shortest path from a source to a destination by
-     * using the pre-populated local topology state prepared
-     * by method @ref TopologyManager.newDatabaseTopology().
-     *
-     * For additional documentation and usage, see method
-     * @ref TopologyManager.newDatabaseTopology()
-     *
-     * @param topology the topology handler to use.
-     * @param src the source in the shortest path computation.
-     * @param dest the destination in the shortest path computation.
-     * @return the data path with the computed shortest path if
-     * found, otherwise null.
-     */
-    public static DataPath getTopologyShortestPath(
-		Topology topology,
-		SwitchPort src, SwitchPort dest) {
-	DataPath result_data_path = new DataPath();
-
-	// Initialize the source and destination in the data path to return
-	result_data_path.setSrcPort(src);
-	result_data_path.setDstPort(dest);
-
-	String dpid_src = src.dpid().toString();
-	String dpid_dest = dest.dpid().toString();
-
-	// Get the source vertex
-	Node v_src = topology.getNode(src.dpid().value());
-	if (v_src == null) {
-	    return null;		// Source vertex not found
-	}
-
-	// Get the destination vertex
-	Node v_dest = topology.getNode(dest.dpid().value());
-	if (v_dest == null) {
-	    return null;		// Destination vertex not found
-	}
-
-	//
-	// Test whether we are computing a path from/to the same DPID.
-	// If "yes", then just add a single flow entry in the return result.
-	// However, if the "in" and "out" ports are same, return null.
-	//
-	if (dpid_src.equals(dpid_dest)) {
-	    if (src.port().value() == dest.port().value())
-		return null;		// "In" and "Out" ports are same
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(src.dpid());
-	    flowEntry.setInPort(src.port());
-	    flowEntry.setOutPort(dest.port());
-	    result_data_path.flowEntries().add(flowEntry);
-	    return result_data_path;
-	}
-
-	//
-	// Implement the Shortest Path computation by using Breath First Search
-	//
-	Set<Node> visitedSet = new HashSet<Node>();
-	Queue<Node> processingList = new LinkedList<Node>();
-	Map<Node, Node.Link> previousVertexMap = new HashMap<Node, Node.Link>();
-	processingList.add(v_src);
-	visitedSet.add(v_src);
-	Boolean path_found = false;
-	while (! processingList.isEmpty()) {
-	    Node nextVertex = processingList.poll();
-	    if (v_dest == nextVertex) {
-		path_found = true;
-		break;
-	    }
-	    for (Node.Link link : nextVertex.links.values()) {
-		Node child = link.neighbor;
-		if (! visitedSet.contains(child)) {
-		    previousVertexMap.put(child, link);
-		    visitedSet.add(child);
-		    processingList.add(child);
-		}
-	    }
-	}
-	if (! path_found)
-	    return null;		// No path found
-
-	// Collect the path as a list of links
-	List<Node.Link> resultPath = new LinkedList<Node.Link>();
-	Node previousVertex = v_dest;
-	while (! v_src.equals(previousVertex)) {
-	    Node.Link currentLink = previousVertexMap.get(previousVertex);
-	    resultPath.add(currentLink);
-	    previousVertex = currentLink.me;
-	}
-	Collections.reverse(resultPath);
-
-	//
-	// Loop through the result and prepare the return result
-	// as a list of Flow Entries.
-	//
-	Port inPort = new Port(src.port().value());
-	Port outPort;
-	for (Node.Link link: resultPath) {
-	    // Setup the outgoing port, and add the Flow Entry
-	    outPort = new Port((short)link.myPort);
-
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(new Dpid(link.me.nodeId));
-	    flowEntry.setInPort(inPort);
-	    flowEntry.setOutPort(outPort);
-	    result_data_path.flowEntries().add(flowEntry);
-
-	    // Setup the next incoming port
-	    inPort = new Port((short)link.neighborPort);
-	}
-	if (resultPath.size() > 0) {
-	    // Add the last Flow Entry
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(new Dpid(dest.dpid().value()));
-	    flowEntry.setInPort(inPort);
-	    flowEntry.setOutPort(dest.port());
-	    result_data_path.flowEntries().add(flowEntry);
-	}
-
-	if (result_data_path.flowEntries().size() > 0)
-	    return result_data_path;
-
-	return null;
-    }
-
-    /**
-     * Get the shortest path from a source to a destination by using
-     * the underlying Graph Database.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     * @param src the source in the shortest path computation.
-     * @param dest the destination in the shortest path computation.
-     * @return the data path with the computed shortest path if
-     * found, otherwise null.
-     */
-    public static DataPath getDatabaseShortestPath(DBOperation dbHandler,
-					     SwitchPort src, SwitchPort dest) {
-	DataPath result_data_path = new DataPath();
-
-	// Initialize the source and destination in the data path to return
-	result_data_path.setSrcPort(src);
-	result_data_path.setDstPort(dest);
-
-	String dpid_src = src.dpid().toString();
-	String dpid_dest = dest.dpid().toString();
-
-	// Get the source and destination switches
-	ISwitchObject srcSwitch =
-	    dbHandler.searchActiveSwitch(dpid_src);
-	ISwitchObject destSwitch =
-	    dbHandler.searchActiveSwitch(dpid_dest);
-	if (srcSwitch == null || destSwitch == null) {
-	    return null;
-	}
-
-	//
-	// Test whether we are computing a path from/to the same DPID.
-	// If "yes", then just add a single flow entry in the return result.
-	//
-	if (dpid_src.equals(dpid_dest)) {
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(src.dpid());
-	    flowEntry.setInPort(src.port());
-	    flowEntry.setOutPort(dest.port());
-	    result_data_path.flowEntries().add(flowEntry);
-	    dbHandler.commit();
-	    return result_data_path;
-	}
-
-	Vertex v_src = srcSwitch.asVertex();	
-	Vertex v_dest = destSwitch.asVertex();
-
-	//
-	// Implement the Shortest Path computation by using Breath First Search
-	//
-	Set<Vertex> visitedSet = new HashSet<Vertex>();
-	Queue<Vertex> processingList = new LinkedList<Vertex>();
-	Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
-
-	processingList.add(v_src);
-	visitedSet.add(v_src);
-	Boolean path_found = false;
-	while (! processingList.isEmpty()) {
-	    Vertex nextVertex = processingList.poll();
-	    if (v_dest.equals(nextVertex)) {
-		path_found = true;
-		break;
-	    }
-	    for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
-		// Ignore inactive ports
-		if (! parentPort.getProperty("state").toString().equals("ACTIVE"))
-			continue;
-
-		for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
-		    // Ignore inactive ports
-		    if (! childPort.getProperty("state").toString().equals("ACTIVE"))
-			continue;
-
-		    for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
-			// Ignore inactive switches
-			String state = child.getProperty("state").toString();
-			if (! state.equals(SwitchState.ACTIVE.toString()))
-			    continue;
-
-			if (! visitedSet.contains(child)) {
-			    previousVertexMap.put(parentPort, nextVertex);
-			    previousVertexMap.put(childPort, parentPort);
-			    previousVertexMap.put(child, childPort);
-			    visitedSet.add(child);
-			    processingList.add(child);
-			}
-		    }
-		}
-	    }
-	}
-	if (! path_found)
-	    return null;		// No path found
-
-	List<Vertex> resultPath = new LinkedList<Vertex>();
-	Vertex previousVertex = v_dest;
-	resultPath.add(v_dest);
-	while (! v_src.equals(previousVertex)) {
-	    Vertex currentVertex = previousVertexMap.get(previousVertex);
-	    resultPath.add(currentVertex);
-	    previousVertex = currentVertex;
-	}
-	Collections.reverse(resultPath);
-
-
-	//
-	// Loop through the result and prepare the return result
-	// as a list of Flow Entries.
-	//
-	long nodeId = 0;
-	short portId = 0;
-	Port inPort = new Port(src.port().value());
-	Port outPort = new Port();
-	int idx = 0;
-	for (Vertex v: resultPath) {
-	    String type = v.getProperty("type").toString();
-	    // System.out.println("type: " + type);
-	    if (type.equals("port")) {
-		//String number = v.getProperty("number").toString();
-		// System.out.println("number: " + number);
-
-		Object obj = v.getProperty("number");
-		// String class_str = obj.getClass().toString();
-		if (obj instanceof Short) {
-		    portId = (Short)obj;
-		} else if (obj instanceof Integer) {
-		    Integer int_nodeId = (Integer)obj;
-		    portId = int_nodeId.shortValue();
-		    // int int_nodeId = (Integer)obj;
-		    // portId = (short)int_nodeId.;
-		}
-	    } else if (type.equals("switch")) {
-		String dpid = v.getProperty("dpid").toString();
-		nodeId = HexString.toLong(dpid);
-
-		// System.out.println("dpid: " + dpid);
-	    }
-	    idx++;
-	    if (idx == 1) {
-		continue;
-	    }
-	    int mod = idx % 3;
-	    if (mod == 0) {
-		// Setup the incoming port
-		inPort = new Port(portId);
-		continue;
-	    }
-	    if (mod == 2) {
-		// Setup the outgoing port, and add the Flow Entry
-		outPort = new Port(portId);
-
-		FlowEntry flowEntry = new FlowEntry();
-		flowEntry.setDpid(new Dpid(nodeId));
-		flowEntry.setInPort(inPort);
-		flowEntry.setOutPort(outPort);
-		result_data_path.flowEntries().add(flowEntry);
-		continue;
-	    }
-	}
-	if (idx > 0) {
-	    // Add the last Flow Entry
-	    FlowEntry flowEntry = new FlowEntry();
-	    flowEntry.setDpid(new Dpid(nodeId));
-	    flowEntry.setInPort(inPort);
-	    flowEntry.setOutPort(dest.port());
-	    result_data_path.flowEntries().add(flowEntry);
-	}
-
-	dbHandler.commit();
-	if (result_data_path.flowEntries().size() > 0)
-	    return result_data_path;
-
-	return null;
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
deleted file mode 100644
index 37b6425..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
+++ /dev/null
@@ -1,617 +0,0 @@
-package net.onrc.onos.ofcontroller.topology;
-
-import java.util.List;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.TreeMap;
-
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.graph.IDBOperation;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
-
-import org.openflow.util.HexString;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.Vertex;
-
-/**
- * A class for storing Node and Link information for fast computation
- * of shortest paths.
- */
-class Node {
-    /**
-     * A class for storing Link information for fast computation of shortest
-     * paths.
-     */
-    class Link {
-        public Node me;                        // The node this link originates from
-        public Node neighbor;                // The neighbor node on the other side
-        public int myPort;                // Local port ID for the link
-        public int neighborPort;        // Neighbor port ID for the link
-
-        /**
-         * Link constructor.
-         *
-         * @param me the node this link originates from.
-         * @param the neighbor node on the other side of the link.
-         * @param myPort local port ID for the link.
-         * @param neighborPort neighbor port ID for the link.
-         */
-        public Link(Node me, Node neighbor, int myPort, int neighborPort) {
-        	this.me = me;
-        	this.neighbor = neighbor;
-        	this.myPort = myPort;
-        	this.neighborPort = neighborPort;
-        }
-    };
-
-    public long nodeId;				// The node ID
-    // TODO Change type of PortNumber to Short
-    public TreeMap<Integer, Link> links;	// The links from this node:
-						//     (src PortNumber -> Link)
-    private TreeMap<Integer, Link> reverseLinksMap; // The links to this node:
-						//     (dst PortNumber -> Link)
-    private TreeMap<Integer, Integer> portsMap;	// The ports on this node:
-						//     (PortNumber -> PortNumber)
-						// TODO: In the future will be:
-						//     (PortNumber -> Port)
-
-    /**
-     * Node constructor.
-     *
-     * @param nodeId the node ID.
-     */
-    public Node(long nodeId) {
-	this.nodeId = nodeId;
-	links = new TreeMap<Integer, Link>();
-	reverseLinksMap = new TreeMap<Integer, Link>();
-	portsMap = new TreeMap<Integer, Integer>();
-    }
-
-    /**
-     * Get all ports.
-     *
-     * @return all ports.
-     */
-    public Map<Integer, Integer> ports() {
-	return portsMap;
-    }
-
-    /**
-     * Get the port for a given Port ID.
-     *
-     * Note: For now the port itself is just the Port ID. In the future
-     * it might contain more information.
-     *
-     * @return the port if found, otherwise null.
-     */
-    public Integer getPort(int portId) {
-	return portsMap.get(portId);
-    }
-
-    /**
-     * Add a port for a given Port ID.
-     *
-     * Note: For now the port itself is just the Port ID. In the future
-     * it might contain more information.
-     *
-     * @param portId the Port ID of the port to add.
-     * @return the added Port.
-     */
-    Integer addPort(int portId) {
-	Integer port = new Integer(portId);
-	portsMap.put(portId, port);
-	return port;
-    }
-
-    /**
-     * Remove a port for a given Port ID.
-     *
-     * NOTE: The outgoing and incoming links using this port are removed as
-     * well.
-     */
-    void removePort(int portId) {
-	// Remove the outgoing link
-	Link link = getLink(portId);
-	if (link != null) {
-	    link.neighbor.removeReverseLink(link);
-	    removeLink(portId);
-	}
-
-	// Remove the incoming link
-	Link reverseLink = reverseLinksMap.get(portId);
-	if (reverseLink != null) {
-	    // NOTE: reverseLink.myPort is the neighbor's outgoing port
-	    reverseLink.me.removeLink(reverseLink.myPort);
-	    removeReverseLink(reverseLink);
-	}
-
-	portsMap.remove(portId);
-    }
-
-    /**
-     * Get a link on a port to a neighbor.
-     *
-     * @param myPortId the local port ID for the link to the neighbor.
-     * @return the link if found, otherwise null.
-     */
-    public Link getLink(int myPortId) {
-	return links.get(myPortId);
-    }
-
-    /**
-     * Add a link to a neighbor.
-     *
-     * @param myPortId the local port ID for the link to the neighbor.
-     * @param neighbor the neighbor for the link.
-     * @param neighborPortId the neighbor port ID for the link.
-     * @return the added Link.
-     */
-    public Link addLink(int myPortId, Node neighbor, int neighborPortId) {
-	Link link = new Link(this, neighbor, myPortId, neighborPortId);
-	links.put(myPortId, link);
-	neighbor.addReverseLink(link);
-	return link;
-    }
-
-    /**
-     * Add a reverse link from a neighbor.
-     *
-     * @param link the reverse link from a neighbor to add.
-     */
-    private void addReverseLink(Link link) {
-	// NOTE: link.neghborPort is my port
-	reverseLinksMap.put(link.neighborPort, link);
-    }
-
-    /**
-     * Remove a link to a neighbor.
-     *
-     * @param myPortId the local port ID for the link to the neighbor.
-     */
-    public void removeLink(int myPortId) {
-	links.remove(myPortId);
-    }
-
-    /**
-     * Remove a reverse link from a neighbor.
-     *
-     * @param link the reverse link from a neighbor to remove.
-     */
-    private void removeReverseLink(Link link) {
-	// NOTE: link.neghborPort is my port
-	reverseLinksMap.remove(link.neighborPort);
-    }
-};
-
-/**
- * A class for storing topology information.
- */
-public class Topology {
-    private final static Logger log = LoggerFactory.getLogger(Topology.class);
-    
-    // flag to use optimized readFromDatabase() method.
-    private static final boolean enableOptimizedRead = true;
-    
-    private Map<Long, Node> nodesMap;	// The dpid->Node mapping
-
-    /**
-     * Default constructor.
-     */
-    public Topology() {
-	nodesMap = new TreeMap<Long, Node>();
-    }
-
-    /**
-     * Add a topology element to the topology.
-     *
-     * @param topologyElement the topology element to add.
-     * @return true if the topology was modified, otherwise false.
-     */
-    public boolean addTopologyElement(TopologyElement topologyElement) {
-	boolean isModified = false;
-
-	switch (topologyElement.getType()) {
-	case ELEMENT_SWITCH: {
-	    // Add the switch
-	    Node node = getNode(topologyElement.getSwitch());
-	    if (node == null) {
-		node = addNode(topologyElement.getSwitch());
-		isModified = true;
-	    }
-	    break;
-	}
-	case ELEMENT_PORT: {
-	    // Add the switch
-	    Node node = getNode(topologyElement.getSwitch());
-	    if (node == null) {
-		node = addNode(topologyElement.getSwitch());
-		isModified = true;
-	    }
-	    // Add the port for the switch
-	    Integer port = node.getPort(topologyElement.getSwitchPort());
-	    if (port == null) {
-		node.addPort(topologyElement.getSwitchPort());
-		isModified = true;
-	    }
-	    break;
-	}
-	case ELEMENT_LINK: {
-	    // Add the "from" switch
-	    Node fromNode = getNode(topologyElement.getFromSwitch());
-	    if (fromNode == null) {
-		fromNode = addNode(topologyElement.getFromSwitch());
-		isModified = true;
-	    }
-	    // Add the "to" switch
-	    Node toNode = getNode(topologyElement.getToSwitch());
-	    if (toNode == null) {
-		toNode = addNode(topologyElement.getToSwitch());
-		isModified = true;
-	    }
-	    // Add the "from" port
-	    Integer fromPort = fromNode.getPort(topologyElement.getFromPort());
-	    if (fromPort == null) {
-		fromNode.addPort(topologyElement.getFromPort());
-		isModified = true;
-	    }
-	    // Add the "to" port
-	    Integer toPort = fromNode.getPort(topologyElement.getToPort());
-	    if (toPort == null) {
-		toNode.addPort(topologyElement.getToPort());
-		isModified = true;
-	    }
-	    Node.Link link = fromNode.getLink(topologyElement.getFromPort());
-	    if (link == null) {
-		fromNode.addLink(topologyElement.getFromPort(),
-				 toNode,
-				 topologyElement.getToPort());
-		isModified = true;
-	    }
-
-	    break;
-	}
-	case ELEMENT_UNKNOWN:
-	    // TODO: Adding "assert(false);" here can be dangerous
-	    break;
-	}
-
-	return isModified;
-    }
-
-    /**
-     * Remove a topology element from the topology.
-     *
-     * @param topologyElement the topology element to remove.
-     * @return true if the topology was modified, otherwise false.
-     */
-    public boolean removeTopologyElement(TopologyElement topologyElement) {
-	boolean isModified = false;
-
-	switch (topologyElement.getType()) {
-	case ELEMENT_SWITCH: {
-	    // Remove the switch
-	    Node node = getNode(topologyElement.getSwitch());
-	    if (node != null) {
-		removeNode(node);
-		isModified = true;
-	    }
-	    break;
-	}
-	case ELEMENT_PORT: {
-	    // Find the switch
-	    Node node = getNode(topologyElement.getSwitch());
-	    if (node == null)
-		break;
-	    // Remove the port for the switch
-	    Integer port = node.getPort(topologyElement.getSwitchPort());
-	    if (port != null) {
-		node.removePort(topologyElement.getSwitchPort());
-		isModified = true;
-	    }
-	    break;
-	}
-	case ELEMENT_LINK: {
-	    // Find the "from" switch
-	    Node fromNode = getNode(topologyElement.getFromSwitch());
-	    if (fromNode == null)
-		break;
-	    // Remove the link originating from the "from" port
-	    Node.Link link = fromNode.getLink(topologyElement.getFromPort());
-	    if (link != null) {
-		fromNode.removeLink(topologyElement.getFromPort());
-		isModified = true;
-	    }
-	    break;
-	}
-	case ELEMENT_UNKNOWN:
-	    // TODO: Adding "assert(false);" here can be dangerous
-	    break;
-	}
-
-	return isModified;
-    }
-
-    /**
-     * Get a node for a given Node ID.
-     *
-     * @param nodeId the Node ID to use.
-     * @return the corresponding Node if found, otherwise null.
-     */
-    Node getNode(long nodeId) {
-	return nodesMap.get(nodeId);
-    }
-
-    /**
-     * Add a node for a given Node ID.
-     *
-     * @param nodeId the Node ID to use.
-     * @return the added Node.
-     */
-    Node addNode(long nodeId) {
-	Node node = new Node(nodeId);
-	nodesMap.put(nodeId, node);
-	return node;
-    }
-
-    /**
-     * Remove an existing node.
-     *
-     * @param node the Node to remove.
-     */
-    void removeNode(Node node) {
-	//
-	// Remove all ports one-by-one. This operation will also remove the
-	// incoming links originating from the neighbors.
-	//
-	// NOTE: We have to extract all Port IDs in advance, otherwise we
-	// cannot loop over the Ports collection and remove entries at the
-	// same time.
-	// TODO: If there is a large number of ports, the implementation
-	// below can be sub-optimal. It should be refactored as follows:
-	//   1. Modify removePort() to perform all the cleanup, except
-	//     removing the Port entry from the portsMap
-	//   2. Call portsMap.clear() at the end of this method
-	//   3. In all other methods: if removePort() is called somewhere else,
-	//      add an explicit removal of the Port entry from the portsMap.
-	//
-	List<Integer> allPortIdKeys = new LinkedList<Integer>();
-	allPortIdKeys.addAll(node.ports().keySet());
-	for (Integer portId : allPortIdKeys)
-	    node.removePort(portId);
-
-	nodesMap.remove(node.nodeId);
-    }
-
-    /**
-     * Read topology state from the database.
-     *
-     * @param dbHandler the Graph Database handler to use.
-     */
-    public void readFromDatabase(DBOperation dbHandler) {
-    	if (enableOptimizedRead) {
-    		readFromDatabaseBodyOptimized(dbHandler);
-    	} else {
-    		readFromDatabaseBody(dbHandler);
-    	}
-
-    }
-
-    private void readFromDatabaseBody(DBOperation dbHandler) {
-    	//
-    	// Fetch the relevant info from the Switch and Port vertices
-    	// from the Titan Graph.
-    	//
-
-    	nodesMap.clear();
-    	Iterable<ISwitchObject> activeSwitches = dbHandler.getActiveSwitches();
-    	for (ISwitchObject switchObj : activeSwitches) {
-    	    Vertex nodeVertex = switchObj.asVertex();
-    	    //
-    	    // The Switch info
-    	    //
-	    Object obj = nodeVertex.getProperty("dpid");
-	    if (obj == null)
-		continue;	// Ignore vertices with empty attributes
-    	    String nodeDpid = obj.toString();
-    	    long nodeId = HexString.toLong(nodeDpid);
-    	    Node me = nodesMap.get(nodeId);
-    	    if (me == null)
-    		me = addNode(nodeId);
-
-    	    //
-    	    // The local Port info
-    	    //
-    	    for (Vertex myPortVertex : nodeVertex.getVertices(Direction.OUT, "on")) {
-		obj = myPortVertex.getProperty("state");
-		if (obj == null)
-		    continue;	// Ignore vertices with empty attributes
-    		// Ignore inactive ports
-    		if (! obj.toString().equals("ACTIVE"))
-    		    continue;
-
-    		int myPort = 0;
-    		obj = myPortVertex.getProperty("number");
-		if (obj == null)
-		    continue;	// Ignore vertices with empty attributes
-    		if (obj instanceof Short) {
-    		    myPort = (Short)obj;
-    		} else if (obj instanceof Integer) {
-    		    myPort = (Integer)obj;
-    		}
-    		me.addPort(myPort);
-
-    		for (Vertex neighborPortVertex : myPortVertex.getVertices(Direction.OUT, "link")) {
-		    obj = neighborPortVertex.getProperty("state");
-		    if (obj == null)
-			continue;    // Ignore vertices with empty attributes
-    		    // Ignore inactive ports
-    		    if (! obj.toString().equals("ACTIVE")) {
-    		    	continue;
-    		    }
-
-    		    int neighborPort = 0;
-    		    obj = neighborPortVertex.getProperty("number");
-		    if (obj == null)
-			continue;    // Ignore vertices with empty attributes
-    		    if (obj instanceof Short) {
-    			neighborPort = (Short)obj;
-    		    } else if (obj instanceof Integer) {
-    			neighborPort = (Integer)obj;
-    		    }
-    		    //
-    		    // The neighbor Switch info
-    		    //
-    		    for (Vertex neighborVertex : neighborPortVertex.getVertices(Direction.IN, "on")) {
-			obj = neighborVertex.getProperty("state");
-			if (obj == null)
-			    continue;  // Ignore vertices with empty attributes
-    			// Ignore inactive switches
-    			String state = obj.toString();
-    			if (! state.equals(SwitchState.ACTIVE.toString()))
-    			    continue;
-
-			obj = neighborVertex.getProperty("dpid");
-			if (obj == null)
-			    continue;  // Ignore vertices with empty attributes
-    			String neighborDpid = obj.toString();
-    			long neighborId = HexString.toLong(neighborDpid);
-    			Node neighbor = nodesMap.get(neighborId);
-    			if (neighbor == null)
-    			    neighbor = addNode(neighborId);
-    			neighbor.addPort(neighborPort);
-    			me.addLink(myPort, neighbor, neighborPort);
-    		    }
-    		}
-    	    }
-    	}
-    	dbHandler.commit();
-    }
-
-    private void readFromDatabaseBodyOptimized(DBOperation dbHandler) {
-	nodesMap.clear();
-
-	// Load all switches into Map
-	Iterable<ISwitchObject> switches = dbHandler.getAllSwitches();
-	for (ISwitchObject switchObj : switches) {
-	    String switchState = switchObj.getState();
-	    if (switchState == null)
-		continue;	// Ignore vertices with empty attributes
-	    // Ignore inactive ports
-	    if (!switchState.equals(SwitchState.ACTIVE.toString())) {
-		continue;
-	    }
-
-	    //
-	    // The Switch info
-	    //
-	    Vertex nodeVertex = switchObj.asVertex();
-	    Object obj = nodeVertex.getProperty("dpid");
-	    if (obj == null)
-		continue;	// Ignore vertices with empty attributes
-	    String nodeDpid = obj.toString();
-	    long nodeId = HexString.toLong(nodeDpid);
-
-	    addNode(nodeId);
-	}
-
-	//
-	// Get All Ports
-	//
-	Iterable<IPortObject> ports = dbHandler.getAllPorts(); //TODO: Add to DB operations
-	for (IPortObject myPortObj : ports) {
-	    Vertex myPortVertex = myPortObj.asVertex();
-
-	    Object obj = myPortVertex.getProperty("state");
-	    if (obj == null)
-		continue;	// Ignore vertices with empty attributes
-	    // Ignore inactive ports
-	    if (! obj.toString().equals("ACTIVE")) {
-		continue;
-	    }
-
-	    short myPort = 0;
-	    String idStr = myPortObj.getPortId();
-	    if (idStr == null)
-		continue;	// Ignore vertices with empty attributes
-	    String[] splitter = idStr.split(IDBOperation.PORT_ID_DELIM);
-	    if (splitter.length != 2) {
-		log.error("Invalid port_id : {}", idStr);
-		continue;
-	    }
-	    String myDpid = splitter[0];
-	    myPort = Short.parseShort(splitter[1]);
-	    long myId = HexString.toLong(myDpid);
-	    Node me = nodesMap.get(myId);
-
-	    if (me == null) {
-		// cannot proceed ports and switches are out of sync
-		//TODO: Restart the whole read
-		continue;
-	    }
-
-	    if (me.getPort((int)myPort) == null) {
-		me.addPort((int)myPort);
-	    } else if (me.getLink((int)myPort) != null) {
-		// Link already added..probably by neighbor
-		continue;
-	    }
-
-	    //
-	    // The neighbor Port info
-	    //
-	    for (Vertex neighborPortVertex : myPortVertex.getVertices(Direction.OUT, "link")) {
-		obj = neighborPortVertex.getProperty("state");
-		if (obj == null)
-		    continue;	// Ignore vertices with empty attributes
-		// Ignore inactive ports
-		if (! obj.toString().equals("ACTIVE")) {
-		    continue;
-		}
-
-		int neighborPort = 0;
-		obj = neighborPortVertex.getProperty("port_id");
-		if (obj == null)
-		    continue;	// Ignore vertices with empty attributes
-		idStr = obj.toString();
-		splitter = idStr.split(IDBOperation.PORT_ID_DELIM);
-		if (splitter.length != 2) {
-		    log.error("Invalid port_id : {}", idStr);
-		    continue;
-		}
-		String neighborDpid = splitter[0];
-		neighborPort = Short.parseShort(splitter[1]);
-		long neighborId = HexString.toLong(neighborDpid);
-		Node neighbor = nodesMap.get(neighborId);
-		if (neighbor == null) {
-		    continue;
-		}
-		if (neighbor.getPort(neighborPort) == null) {
-		    neighbor.addPort(neighborPort);
-		}
-		me.addLink(myPort, neighbor, neighborPort);
-	    }
-	}
-	dbHandler.commit();
-    }
-
-    // Only for debug use
-    @Override
-    public String toString() {
-    	long numNodes = nodesMap.size();
-    	long numLinks = 0;
-    	for (Map.Entry<Long, Node> entry : nodesMap.entrySet()) {
-	    Node n = entry.getValue();
-	    for (Map.Entry<Integer, Node.Link> linkEntry : n.links.entrySet()) {
-		if (n.nodeId > linkEntry.getValue().neighbor.nodeId) {
-		    ++numLinks;
-		}
-	    }
-    	}
-    	return "Topology has " + numNodes + " Nodes and " + numLinks + " Links.";
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyElement.java b/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyElement.java
deleted file mode 100644
index 0fefa3a..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyElement.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package net.onrc.onos.ofcontroller.topology;
-
-/**
- * Class for storing information about a Topology Element: Switch, Port or
- * Link.
- */
-public class TopologyElement {
-    /**
-     * The Element Type.
-     */
-    public enum Type {
-	ELEMENT_UNKNOWN,	// Unknown element
-	ELEMENT_SWITCH,		// Network Switch
-	ELEMENT_PORT,		// Switch Port
-	ELEMENT_LINK		// Unidirectional Link between Switch Ports
-    }
-
-    private Type elementType;		// The element type
-    private long fromSwitchDpid = 0;	// The Switch DPID
-    private int fromSwitchPort = 0;	// The Switch Port
-    private long toSwitchDpid = 0;	// The Neighbor Switch DPID
-    private int toSwitchPort = 0;	// The Neighbor Switch Port
-
-    /**
-     * Default constructor.
-     */
-    public TopologyElement() {
-	elementType = Type.ELEMENT_UNKNOWN;
-    }
-
-    /**
-     * Constructor to create a Topology Element for a Switch.
-     *
-     * @param switchDpid the Switch DPID.
-     */
-    public TopologyElement(long switchDpid) {
-	this.elementType = Type.ELEMENT_SWITCH;
-	this.fromSwitchDpid = switchDpid;
-    }
-
-    /**
-     * Constructor to create a Topology Element for a Switch Port.
-     *
-     * @param switchDpid the Switch DPID.
-     * @param switchPort the Switch Port.
-     */
-    public TopologyElement(long switchDpid, int switchPort) {
-	this.elementType = Type.ELEMENT_PORT;
-	this.fromSwitchDpid = switchDpid;
-	this.fromSwitchPort = switchPort;
-    }
-
-    /**
-     * Constructor to create a Topology Element for an unidirectional Link
-     * between Switch Ports.
-     *
-     * @param fromSwitchDpid the Switch DPID the Link begins from.
-     * @param fromSwitchPort the Switch Port the Link begins from.
-     * @param toSwitchDpid the Switch DPID the Link ends to.
-     * @param toSwitchPort the Switch Port the Link ends to.
-     */
-    public TopologyElement(long fromSwitchDpid, int fromSwitchPort,
-			   long toSwitchDpid, int toSwitchPort) {
-	this.elementType = Type.ELEMENT_LINK;
-	this.fromSwitchDpid = fromSwitchDpid;
-	this.fromSwitchPort = fromSwitchPort;
-	this.toSwitchDpid = toSwitchDpid;
-	this.toSwitchPort = toSwitchPort;
-    }
-
-    /**
-     * Get the Element type.
-     *
-     * @return the Element type.
-     */
-    public TopologyElement.Type getType() {
-	return elementType;
-    }
-
-    /**
-     * Get the Switch DPID.
-     *
-     * NOTE: Applies for Type.ELEMENT_SWITCH and Type.ELEMENT_PORT
-     *
-     * @return the Switch DPID.
-     */
-    public long getSwitch() {
-	return fromSwitchDpid;
-    }
-
-    /**
-     * Get the Switch Port.
-     *
-     * NOTE: Applies for Type.ELEMENT_PORT
-     *
-     * @return the Switch Port.
-     */
-    public int getSwitchPort() {
-	return fromSwitchPort;
-    }
-
-    /**
-     * Get the Switch DPID the Link begins from.
-     *
-     * NOTE: Applies for Type.ELEMENT_LINK
-     */
-    public long getFromSwitch() {
-	return fromSwitchDpid;
-    }
-
-    /**
-     * Get the Switch Port the Link begins from.
-     *
-     * NOTE: Applies for Type.ELEMENT_LINK
-     */
-    public int getFromPort() {
-	return fromSwitchPort;
-    }
-
-    /**
-     * Get the Switch DPID the Link ends to.
-     *
-     * NOTE: Applies for Type.ELEMENT_LINK
-     */
-    public long getToSwitch() {
-	return toSwitchDpid;
-    }
-
-    /**
-     * Get the Switch Port the Link ends to.
-     *
-     * NOTE: Applies for Type.ELEMENT_LINK
-     */
-    public int getToPort() {
-	return toSwitchPort;
-    }
-
-    /**
-     * Get the Topology Element ID.
-     *
-     * The Topology Element ID has the following format:
-     *   - Switch: "Switch=<HexLongDpid>"
-     *     Example: "Switch=101"
-     *   - Switch Port: "Port=<HexLongDpid>/<IntPortId>"
-     *     Example: "Port=102/1"
-     *   - Link: "Link=<FromHexLongDpid>/<FromIntPortId>/<ToHexLongDpid>/<ToIntPortId>"
-     *     Example: "Link=101/2/103/4"
-     *
-     * NOTE: The Topology Element ID has no syntax meaning. It is used only to
-     * uniquely identify a topology element.
-     *
-     * @return the Topology Element ID.
-     */
-    public String elementId() {
-	switch (elementType) {
-	case ELEMENT_SWITCH:
-	    return "Switch=" + Long.toHexString(fromSwitchDpid);
-	case ELEMENT_PORT:
-	    return "Port=" +
-		Long.toHexString(fromSwitchDpid) + "/" + fromSwitchPort;
-	case ELEMENT_LINK:
-	    return "Link=" +
-		Long.toHexString(fromSwitchDpid) + "/" + fromSwitchPort + "/" +
-		Long.toHexString(toSwitchDpid) + "/" + toSwitchPort;
-	case ELEMENT_UNKNOWN:
-	    return "Element=UNKNOWN";
-	}
-
-	assert(false);
-	return null;
-    }
-
-    /**
-     * Convert the Topology Element to a string.
-     *
-     * @return the Topology Element as a string.
-     */
-    @Override
-    public String toString() {
-	// For now, we just return the Element ID.
-	return elementId();
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java b/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java
deleted file mode 100644
index cae29ce..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyManager.java
+++ /dev/null
@@ -1,348 +0,0 @@
-package net.onrc.onos.ofcontroller.topology;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.onrc.onos.datagrid.IDatagridService;
-import net.onrc.onos.graph.DBOperation;
-import net.onrc.onos.graph.GraphDBManager;
-import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
-import net.onrc.onos.ofcontroller.topology.web.OnosTopologyWebRoutable;
-import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.Port;
-import net.onrc.onos.ofcontroller.util.SwitchPort;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A class for obtaining Topology Snapshot
- * and PathComputation.
- *
- * TODO: PathComputation part should be refactored out to separate class.
- */
-public class TopologyManager implements IFloodlightModule,
-					ITopologyNetService {
-    private final static Logger log = LoggerFactory.getLogger(TopologyManager.class);
-    protected IFloodlightProviderService floodlightProvider;
-
-    protected static final String DBConfigFile = "dbconf";
-    protected static final String GraphDBStore = "graph_db_store";
-
-    protected DBOperation dbHandler;
-    protected IRestApiService restApi;
-
-
-    /**
-     * Default constructor.
-     */
-    public TopologyManager() {
-    }
-
-    /**
-     * Constructor for given database configuration file.
-     *
-     * @param config the database configuration file to use for
-     * the initialization.
-     */
-    public TopologyManager(FloodlightModuleContext context) {
-	Map<String, String> configMap = context.getConfigParams(this);
-	String conf = configMap.get(DBConfigFile);
-        String dbStore = configMap.get(GraphDBStore);
-	this.init(dbStore,conf);
-    }
-
-    /**
-     * Constructor for a given database operation handler.
-     *
-     * @param dbHandler the database operation handler to use for the
-     * initialization.
-     */
-    public TopologyManager(DBOperation dbHandler) {
-	this.dbHandler = dbHandler;
-    }
-
-    /**
-     * Init the module.
-     *
-     * @param config the database configuration file to use for
-     * the initialization.
-     */
-    public void init(final String dbStore, String config) {
-	try {
-	    dbHandler = GraphDBManager.getDBOperation();
-	} catch (Exception e) {
-	    log.error(e.getMessage());
-	}
-    }
-
-    /**
-     * Shutdown the Topology Manager operation.
-     */
-    @Override
-    protected void finalize() {
-	close();
-    }
-
-    /**
-     * Close the service. It will close the corresponding database connection.
-     */
-    public void close() {
-	dbHandler.close();
-    }
-
-    /**
-     * Get the collection of offered module services.
-     *
-     * @return the collection of offered module services.
-     */
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l =
-            new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(ITopologyNetService.class);
-        return l;
-    }
-
-    /**
-     * Get the collection of implemented services.
-     *
-     * @return the collection of implemented services.
-     */
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-			       getServiceImpls() {
-        Map<Class<? extends IFloodlightService>,
-	    IFloodlightService> m =
-            new HashMap<Class<? extends IFloodlightService>,
-	    IFloodlightService>();
-        m.put(ITopologyNetService.class, this);
-        return m;
-    }
-
-    /**
-     * Get the collection of modules this module depends on.
-     *
-     * @return the collection of modules this module depends on.
-     */
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-                                                    getModuleDependencies() {
-	Collection<Class<? extends IFloodlightService>> l =
-	    new ArrayList<Class<? extends IFloodlightService>>();
-	l.add(IFloodlightProviderService.class);
-	l.add(IDatagridService.class);
-        return l;
-    }
-
-    /**
-     * Initialize the module.
-     *
-     * @param context the module context to use for the initialization.
-     */
-    @Override
-    public void init(FloodlightModuleContext context)
-	throws FloodlightModuleException {
-	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
-	restApi = context.getServiceImpl(IRestApiService.class);
-	Map<String, String> configMap = context.getConfigParams(this);
-	String conf = configMap.get(DBConfigFile);
-        String dbStore = configMap.get(GraphDBStore);
-	this.init(dbStore, conf);
-    }
-
-    /**
-     * Startup module operation.
-     *
-     * @param context the module context to use for the startup.
-     */
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-    	restApi.addRestletRoutable(new OnosTopologyWebRoutable());
-
-    }
-
-    /**
-     * Fetch the Switch and Ports info from the Titan Graph
-     * and return it for fast access during the shortest path
-     * computation.
-     *
-     * After fetching the state, method @ref getTopologyShortestPath()
-     * can be used for fast shortest path computation.
-     *
-     * Note: There is certain cost to fetch the state, hence it should
-     * be used only when there is a large number of shortest path
-     * computations that need to be done on the same topology.
-     * Typically, a single call to @ref newDatabaseTopology()
-     * should be followed by a large number of calls to
-     * method @ref getTopologyShortestPath().
-     * After the last @ref getTopologyShortestPath() call,
-     * method @ref dropTopology() should be used to release
-     * the internal state that is not needed anymore:
-     *
-     *       Topology topology = topologyManager.newDatabaseTopology();
-     *       for (int i = 0; i < 10000; i++) {
-     *           dataPath = topologyManager.getTopologyShortestPath(topology, ...);
-     *           ...
-     *        }
-     *        topologyManager.dropTopology(shortestPathTopo);
-     *
-     * @return the allocated topology handler.
-     */
-    @Override
-    public Topology newDatabaseTopology() {
-	Topology topology = new Topology();
-	topology.readFromDatabase(dbHandler);
-
-	return topology;
-    }
-
-    /**
-     * Release the topology that was populated by
-     * method @ref newDatabaseTopology().
-     *
-     * See the documentation for method @ref newDatabaseTopology()
-     * for additional information and usage.
-     *
-     * @param topology the topology to release.
-     */
-    @Override
-    public void dropTopology(Topology topology) {
-    // nothing to do
-    }
-
-    /**
-     * Compute the network path for a Flow.
-     *
-     * @param topology the topology handler to use.
-     * @param flowPath the Flow to compute the network path for.
-     * @return the data path with the computed path if found, otherwise null.
-     */
-    public static DataPath computeNetworkPath(Topology topology,
-					      FlowPath flowPath) {
-	//
-	// Compute the network path based on the desired Flow Path type
-	//
-	switch (flowPath.flowPathType()) {
-	case FP_TYPE_SHORTEST_PATH: {
-	    SwitchPort src = flowPath.dataPath().srcPort();
-	    SwitchPort dest = flowPath.dataPath().dstPort();
-	    return ShortestPath.getTopologyShortestPath(topology, src, dest);
-	}
-
-	case FP_TYPE_EXPLICIT_PATH:
-	    return flowPath.dataPath();
-
-	case FP_TYPE_UNKNOWN:
-	    return null;
-	}
-
-	return null;
-    }
-
-    /**
-     * Test whether two Flow Entries represent same points in a data path.
-     *
-     * NOTE: Two Flow Entries represent same points in a data path if
-     * the Switch DPID, incoming port and outgoing port are same.
-     *
-     * NOTE: This method is specialized for shortest-path unicast paths,
-     * and probably should be moved somewhere else.
-     *
-     * @param oldFlowEntry the first Flow Entry to compare.
-     * @param newFlowEntry the second Flow Entry to compare.
-     * @return true if the two Flow Entries represent same points in a
-     * data path, otherwise false.
-     */
-    public static boolean isSameFlowEntryDataPath(FlowEntry oldFlowEntry,
-						  FlowEntry newFlowEntry) {
-	// Test the DPID
-	if (oldFlowEntry.dpid().value() != newFlowEntry.dpid().value())
-	    return false;
-
-	// Test the inPort
-	do {
-	    Port oldPort = oldFlowEntry.inPort();
-	    Port newPort = newFlowEntry.inPort();
-	    if ((oldPort != null) && (newPort != null) &&
-		(oldPort.value() == newPort.value())) {
-		break;
-	    }
-	    if ((oldPort == null) && (newPort == null))
-		break;
-	    return false;		// inPort is different
-	} while (false);
-
-	// Test the outPort
-	do {
-	    Port oldPort = oldFlowEntry.outPort();
-	    Port newPort = newFlowEntry.outPort();
-	    if ((oldPort != null) && (newPort != null) &&
-		(oldPort.value() == newPort.value())) {
-		break;
-	    }
-	    if ((oldPort == null) && (newPort == null))
-		break;
-	    return false;		// outPort is different
-	} while (false);
-
-	return true;
-    }
-
-    /**
-     * Get the shortest path from a source to a destination by
-     * using the pre-populated local topology state prepared
-     * by method @ref newDatabaseTopology().
-     *
-     * See the documentation for method @ref newDatabaseTopology()
-     * for additional information and usage.
-     *
-     * @param topology the topology handler to use.
-     * @param src the source in the shortest path computation.
-     * @param dest the destination in the shortest path computation.
-     * @return the data path with the computed shortest path if
-     * found, otherwise null.
-     */
-    @Override
-    public DataPath getTopologyShortestPath(Topology topology,
-					    SwitchPort src, SwitchPort dest) {
-	return ShortestPath.getTopologyShortestPath(topology, src, dest);
-    }
-
-    /**
-     * Get the shortest path from a source to a destination by using
-     * the underlying database.
-     *
-     * @param src the source in the shortest path computation.
-     * @param dest the destination in the shortest path computation.
-     * @return the data path with the computed shortest path if
-     * found, otherwise null.
-     */
-    @Override
-    public DataPath getDatabaseShortestPath(SwitchPort src, SwitchPort dest) {
-	return ShortestPath.getDatabaseShortestPath(dbHandler, src, dest);
-    }
-
-    /**
-     * Test whether a route exists from a source to a destination.
-     *
-     * @param src the source node for the test.
-     * @param dest the destination node for the test.
-     * @return true if a route exists, otherwise false.
-     */
-    @Override
-    public Boolean routeExists(SwitchPort src, SwitchPort dest) {
-	DataPath dataPath = getDatabaseShortestPath(src, dest);
-	return (dataPath != null);
-    }
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/web/OnosTopologyWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/topology/web/OnosTopologyWebRoutable.java
deleted file mode 100644
index 987fd69..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/web/OnosTopologyWebRoutable.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package net.onrc.onos.ofcontroller.topology.web;
-
-import net.floodlightcontroller.restserver.RestletRoutable;
-import net.onrc.onos.graph.web.TopoDevicesResource;
-import net.onrc.onos.ofcontroller.networkgraph.web.NetworkGraphLinksResource;
-import net.onrc.onos.ofcontroller.networkgraph.web.NetworkGraphSwitchesResource;
-
-import org.restlet.Context;
-import org.restlet.Restlet;
-import org.restlet.routing.Router;
-
-public class OnosTopologyWebRoutable implements RestletRoutable {
-
-	@Override
-	public Restlet getRestlet(Context context) {
-        Router router = new Router(context);
-        router.attach("/route/{src-dpid}/{src-port}/{dst-dpid}/{dst-port}/json", RouteResource.class);
-        router.attach("/switches/json", NetworkGraphSwitchesResource.class);
-        router.attach("/links/json", NetworkGraphLinksResource.class);
-        router.attach("/devices/json", TopoDevicesResource.class);
-		return router;
-	}
-
-	@Override
-	public String basePath() {
-        return "/wm/onos/topology";
-	}
-
-}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
deleted file mode 100644
index 540c47d..0000000
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package net.onrc.onos.ofcontroller.topology.web;
-
-import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
-import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
-import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.Port;
-import net.onrc.onos.ofcontroller.util.SwitchPort;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class RouteResource extends ServerResource {
-
-    protected final static Logger log = LoggerFactory.getLogger(RouteResource.class);
-
-    @Get("json")
-    public DataPath retrieve() {
-	// Get the services that are needed for the computation
-	ITopologyNetService topologyNetService =
-	    (ITopologyNetService)getContext().getAttributes().
-	    get(ITopologyNetService.class.getCanonicalName());
-	IFlowService flowService =
-	    (IFlowService)getContext().getAttributes().
-	    get(IFlowService.class.getCanonicalName());
-
-	if (topologyNetService == null) {
-	    log.debug("Topology Net Service not found");
-	    return null;
-	}
-	if (flowService == null) {
-	    log.debug("Flow Service not found");
-	    return null;
-	}
-        
-        String srcDpidStr = (String) getRequestAttributes().get("src-dpid");
-        String srcPortStr = (String) getRequestAttributes().get("src-port");
-        String dstDpidStr = (String) getRequestAttributes().get("dst-dpid");
-        String dstPortStr = (String) getRequestAttributes().get("dst-port");
-
-        log.debug( "{}--{}--{}--{}", srcDpidStr, srcPortStr, dstDpidStr, dstPortStr);
-
-	Dpid srcDpid = new Dpid(srcDpidStr);
-	Port srcPort = new Port(Short.parseShort(srcPortStr));
-	Dpid dstDpid = new Dpid(dstDpidStr);
-	Port dstPort = new Port(Short.parseShort(dstPortStr));
-        
-	DataPath result =
-	    topologyNetService.getTopologyShortestPath(
-		flowService.getTopology(),
-		new SwitchPort(srcDpid, srcPort),
-		new SwitchPort(dstDpid, dstPort));
-	if (result != null) {
-	    return result;
-	} else {
-            log.debug("ERROR! no route found");
-            return null;
-        }
-    }
-}
diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
index 0d85407..61e21e1 100644
--- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
+++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
@@ -11,9 +11,7 @@
 net.floodlightcontroller.core.test.MockFloodlightProvider
 net.floodlightcontroller.core.test.MockThreadPoolService
 net.onrc.onos.datagrid.HazelcastDatagrid
-net.onrc.onos.ofcontroller.flowmanager.FlowManager
 net.onrc.onos.ofcontroller.flowprogrammer.FlowProgrammer
-net.onrc.onos.ofcontroller.topology.TopologyManager
 net.onrc.onos.ofcontroller.bgproute.BgpRoute
 net.onrc.onos.registry.controller.ZookeeperRegistry
 net.onrc.onos.registry.controller.StandaloneRegistry
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusherTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusherTest.java
index ae61707..7d6b1ec 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusherTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusherTest.java
@@ -418,8 +418,6 @@
 	@SuppressWarnings("unchecked")
 	@Test
 	public void testAddFlow() {
-		// Code below are copied from FlowManagerTest
-		
 		// instantiate required objects
 		FlowEntry flowEntry1 = new FlowEntry();
 		flowEntry1.setDpid(new Dpid(DPID_TO_VERIFY));
