diff --git a/conf/onos.properties b/conf/onos.properties
index 3dfa462..70f2d3c 100644
--- a/conf/onos.properties
+++ b/conf/onos.properties
@@ -3,9 +3,7 @@
 net.onrc.onos.ofcontroller.floodlightlistener.RCNetworkGraphPublisher, \
 net.floodlightcontroller.ui.web.StaticWebRoutable,\
 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.intent.runtime.PathCalcRuntimeModule,\
 net.onrc.onos.intent.runtime.PlanInstallModule,\
 net.onrc.onos.registry.controller.ZookeeperRegistry
@@ -14,7 +12,6 @@
 net.floodlightcontroller.core.FloodlightProvider.workerthreads = 16
 net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
 net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
-net.onrc.onos.ofcontroller.flowmanager.FlowManager.reuseDatabaseFlowPath = false
 net.onrc.onos.datagrid.HazelcastDatagrid.datagridConfig = conf/hazelcast.xml
 #net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = /tmp/ramcloud.conf
 #net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.graph_db_store = ramcloud
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));
