diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
index 1f426b3..12df976 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
@@ -34,8 +34,8 @@
  * In addition to IFlowSyncService, FlowSynchronizer periodically reads flow
  * tables from switches and compare them with GraphDB to drop unnecessary
  * flows and/or to install missing flows.
- * @author Brian
  *
+ * @author Brian
  */
 public class FlowSynchronizer implements IFlowSyncService {
 
@@ -44,337 +44,344 @@
     // TODO: fix when FlowSynchronizer is refactored
     // private DBOperation dbHandler;
     protected IFlowPusherService pusher;
-    private Map<IOFSwitch, FutureTask<SyncResult>> switchThreads; 
+    private Map<IOFSwitch, FutureTask<SyncResult>> switchThreads;
 
     public FlowSynchronizer() {
-	// TODO: fix when FlowSynchronizer is refactored
-	// dbHandler = GraphDBManager.getDBOperation();
-	switchThreads = new HashMap<IOFSwitch, FutureTask<SyncResult>>();
+        // TODO: fix when FlowSynchronizer is refactored
+        // dbHandler = GraphDBManager.getDBOperation();
+        switchThreads = new HashMap<IOFSwitch, FutureTask<SyncResult>>();
     }
 
     @Override
     public Future<SyncResult> synchronize(IOFSwitch sw) {
-	Synchronizer sync = new Synchronizer(sw);
-	FutureTask<SyncResult> task = new FutureTask<SyncResult>(sync);
-	switchThreads.put(sw, task);
-	task.run();
-	return task;
+        Synchronizer sync = new Synchronizer(sw);
+        FutureTask<SyncResult> task = new FutureTask<SyncResult>(sync);
+        switchThreads.put(sw, task);
+        task.run();
+        return task;
     }
-    
+
     @Override
     public void interrupt(IOFSwitch sw) {
-	FutureTask<SyncResult> t = switchThreads.remove(sw);
-	if(t != null) {
-		t.cancel(true);
-	}	
+        FutureTask<SyncResult> t = switchThreads.remove(sw);
+        if (t != null) {
+            t.cancel(true);
+        }
     }
 
     /**
      * Initialize Synchronizer.
+     *
      * @param pusherService FlowPusherService used for sending messages.
      */
     public void init(IFlowPusherService pusherService) {
-	pusher = pusherService;
+        pusher = pusherService;
     }
 
     /**
      * Synchronizer represents main thread of synchronization.
-     * @author Brian
      *
+     * @author Brian
      */
-	protected class Synchronizer implements Callable<SyncResult> {
-	IOFSwitch sw;
-	// TODO: fix when FlowSynchronizer is refactored
-	// ISwitchObject swObj;
+    protected class Synchronizer implements Callable<SyncResult> {
+        IOFSwitch sw;
+        // TODO: fix when FlowSynchronizer is refactored
+        // ISwitchObject swObj;
 
-	public Synchronizer(IOFSwitch sw) {
-	    this.sw = sw;
-	    Dpid dpid = new Dpid(sw.getId());
-	    // TODO: fix when FlowSynchronizer is refactored
-	    // this.swObj = dbHandler.searchSwitch(dpid.toString());
-	}
+        public Synchronizer(IOFSwitch sw) {
+            this.sw = sw;
+            Dpid dpid = new Dpid(sw.getId());
+            // TODO: fix when FlowSynchronizer is refactored
+            // this.swObj = dbHandler.searchSwitch(dpid.toString());
+        }
 
-	double graphIDTime, switchTime, compareTime, graphEntryTime, extractTime, pushTime, totalTime;
-	@Override
-	public SyncResult call() {
-	    pusher.suspend(sw);
-	    try {
-		    long start = System.nanoTime();
-		    Set<FlowEntryWrapper> graphEntries = getFlowEntriesFromGraph();
-		    long step1 = System.nanoTime();
-		    Set<FlowEntryWrapper> switchEntries = getFlowEntriesFromSwitch();
-		    if (switchEntries == null) {
-		    	log.debug("getFlowEntriesFromSwitch() failed");
-		    	return null;
-		    }
-		    long step2 = System.nanoTime();
-		    SyncResult result = compare(graphEntries, switchEntries);
-		    long step3 = System.nanoTime();
-		    graphIDTime = (step1 - start); 
-		    switchTime = (step2 - step1);
-		    compareTime = (step3 - step2);
-		    totalTime = (step3 - start);
-		    outputTime();
-		    
-		    return result;
-	    } finally {
-		    pusher.resume(sw);
-	    }
-	}
-	
-	private void outputTime() {
-	    double div = Math.pow(10, 6); //convert nanoseconds to ms
-	    graphIDTime /= div;
-	    switchTime /= div;
-	    compareTime = (compareTime - graphEntryTime - extractTime - pushTime) / div;
-	    graphEntryTime /= div;
-	    extractTime /= div;
-	    pushTime /= div;
-	    totalTime /= div;
-	    log.debug("Sync time (ms):{},{},{},{},{},{},{}"
-	              , graphIDTime
-	              , switchTime
-	              , compareTime
-	              , graphEntryTime
-	              , extractTime
-	              , pushTime
-	              , totalTime);
-	}
+        double graphIDTime, switchTime, compareTime, graphEntryTime, extractTime, pushTime, totalTime;
 
-	/**
-	 * Compare flows entries in GraphDB and switch to pick up necessary
-	 * messages.
-	 * After picking up, picked messages are added to FlowPusher.
-	 * @param graphEntries Flow entries in GraphDB.
-	 * @param switchEntries Flow entries in switch.
-	 */
-	private SyncResult compare(Set<FlowEntryWrapper> graphEntries, Set<FlowEntryWrapper> switchEntries) {
-	    int added = 0, removed = 0, skipped = 0;
-	    for(FlowEntryWrapper entry : switchEntries) {
-		if(graphEntries.contains(entry)) {
-		    graphEntries.remove(entry);
-		    skipped++;
-		}
-		else {
-		    // remove flow entry from the switch
-		    entry.removeFromSwitch(sw);
-		    removed++;
-		}
-	    }
-	    for(FlowEntryWrapper entry : graphEntries) {
-		// add flow entry to switch
-		entry.addToSwitch(sw);
-		graphEntryTime += entry.dbTime;
-		extractTime += entry.extractTime;
-		pushTime += entry.pushTime;
-		added++;
-	    }
-	    log.debug("Flow entries added {}, " +
-		      "Flow entries removed {}, " +
-		      "Flow entries skipped {}"
-		      , added
-		      , removed
-		      , skipped );
+        @Override
+        public SyncResult call() {
+            pusher.suspend(sw);
+            try {
+                long start = System.nanoTime();
+                Set<FlowEntryWrapper> graphEntries = getFlowEntriesFromGraph();
+                long step1 = System.nanoTime();
+                Set<FlowEntryWrapper> switchEntries = getFlowEntriesFromSwitch();
+                if (switchEntries == null) {
+                    log.debug("getFlowEntriesFromSwitch() failed");
+                    return null;
+                }
+                long step2 = System.nanoTime();
+                SyncResult result = compare(graphEntries, switchEntries);
+                long step3 = System.nanoTime();
+                graphIDTime = (step1 - start);
+                switchTime = (step2 - step1);
+                compareTime = (step3 - step2);
+                totalTime = (step3 - start);
+                outputTime();
 
-	    return new SyncResult(added, removed, skipped);
-	}
+                return result;
+            } finally {
+                pusher.resume(sw);
+            }
+        }
 
-	/**
-	 * Read GraphDB to get FlowEntries associated with a switch.
-	 * @return set of FlowEntries
-	 */
-	private Set<FlowEntryWrapper> getFlowEntriesFromGraph() {
-	    Set<FlowEntryWrapper> entries = new HashSet<FlowEntryWrapper>();
+        private void outputTime() {
+            double div = Math.pow(10, 6); //convert nanoseconds to ms
+            graphIDTime /= div;
+            switchTime /= div;
+            compareTime = (compareTime - graphEntryTime - extractTime - pushTime) / div;
+            graphEntryTime /= div;
+            extractTime /= div;
+            pushTime /= div;
+            totalTime /= div;
+            log.debug("Sync time (ms):{},{},{},{},{},{},{}"
+                    , graphIDTime
+                    , switchTime
+                    , compareTime
+                    , graphEntryTime
+                    , extractTime
+                    , pushTime
+                    , totalTime);
+        }
 
-	    // TODO: fix when FlowSynchronizer is refactored
-	    /*
-	    for(IFlowEntry entry : swObj.getFlowEntries()) {
-		FlowEntryWrapper fe = new FlowEntryWrapper(entry);
-		entries.add(fe);
-	    }
-	    */
-	    return entries;	    
-	}
+        /**
+         * Compare flows entries in GraphDB and switch to pick up necessary
+         * messages.
+         * After picking up, picked messages are added to FlowPusher.
+         *
+         * @param graphEntries  Flow entries in GraphDB.
+         * @param switchEntries Flow entries in switch.
+         */
+        private SyncResult compare(Set<FlowEntryWrapper> graphEntries, Set<FlowEntryWrapper> switchEntries) {
+            int added = 0, removed = 0, skipped = 0;
+            for (FlowEntryWrapper entry : switchEntries) {
+                if (graphEntries.contains(entry)) {
+                    graphEntries.remove(entry);
+                    skipped++;
+                } else {
+                    // remove flow entry from the switch
+                    entry.removeFromSwitch(sw);
+                    removed++;
+                }
+            }
+            for (FlowEntryWrapper entry : graphEntries) {
+                // add flow entry to switch
+                entry.addToSwitch(sw);
+                graphEntryTime += entry.dbTime;
+                extractTime += entry.extractTime;
+                pushTime += entry.pushTime;
+                added++;
+            }
+            log.debug("Flow entries added {}, " +
+                    "Flow entries removed {}, " +
+                    "Flow entries skipped {}"
+                    , added
+                    , removed
+                    , skipped);
 
-	/**
-	 * Read flow table from switch and derive FlowEntries from table.
-	 * @return set of FlowEntries
-	 */
-	private Set<FlowEntryWrapper> getFlowEntriesFromSwitch() {
+            return new SyncResult(added, removed, skipped);
+        }
 
-	    int lengthU = 0;
-	    OFMatch match = new OFMatch();
-	    match.setWildcards(OFMatch.OFPFW_ALL);
+        /**
+         * Read GraphDB to get FlowEntries associated with a switch.
+         *
+         * @return set of FlowEntries
+         */
+        private Set<FlowEntryWrapper> getFlowEntriesFromGraph() {
+            Set<FlowEntryWrapper> entries = new HashSet<FlowEntryWrapper>();
 
-	    OFFlowStatisticsRequest stat = new OFFlowStatisticsRequest();
-	    stat.setOutPort((short) 0xffff); //TODO: OFPort.OFPP_NONE
-	    stat.setTableId((byte) 0xff); // TODO: fix this with enum (ALL TABLES)
-	    stat.setMatch(match);
-	    List<OFStatistics> stats = new ArrayList<OFStatistics>();
-	    stats.add(stat);
-	    lengthU += stat.getLength();
+            // TODO: fix when FlowSynchronizer is refactored
+        /*
+        for(IFlowEntry entry : swObj.getFlowEntries()) {
+        FlowEntryWrapper fe = new FlowEntryWrapper(entry);
+        entries.add(fe);
+        }
+        */
+            return entries;
+        }
 
-	    OFStatisticsRequest req = new OFStatisticsRequest();
-	    req.setStatisticType(OFStatisticsType.FLOW);
-	    req.setStatistics(stats);
-	    lengthU += req.getLengthU();
-	    req.setLengthU(lengthU);
+        /**
+         * Read flow table from switch and derive FlowEntries from table.
+         *
+         * @return set of FlowEntries
+         */
+        private Set<FlowEntryWrapper> getFlowEntriesFromSwitch() {
 
-	    List<OFStatistics> entries = null;
-	    try {
-		Future<List<OFStatistics>> dfuture = sw.getStatistics(req);
-		entries = dfuture.get();
-	    } catch (IOException e) {
-		// TODO Auto-generated catch block
-		e.printStackTrace();
-		return null;
-	    } catch (InterruptedException e) {
-		// TODO Auto-generated catch block
-		e.printStackTrace();
-		return null;
-	    } catch (ExecutionException e) {
-		// TODO Auto-generated catch block
-		e.printStackTrace();
-		return null;
-	    }
+            int lengthU = 0;
+            OFMatch match = new OFMatch();
+            match.setWildcards(OFMatch.OFPFW_ALL);
 
-	    Set<FlowEntryWrapper> results = new HashSet<FlowEntryWrapper>();
-	    for(OFStatistics result : entries){
-		OFFlowStatisticsReply entry = (OFFlowStatisticsReply) result;
-		FlowEntryWrapper fe = new FlowEntryWrapper(entry);
-		results.add(fe);
-	    }
-	    return results;
-	}
+            OFFlowStatisticsRequest stat = new OFFlowStatisticsRequest();
+            stat.setOutPort((short) 0xffff); //TODO: OFPort.OFPP_NONE
+            stat.setTableId((byte) 0xff); // TODO: fix this with enum (ALL TABLES)
+            stat.setMatch(match);
+            List<OFStatistics> stats = new ArrayList<OFStatistics>();
+            stats.add(stat);
+            lengthU += stat.getLength();
+
+            OFStatisticsRequest req = new OFStatisticsRequest();
+            req.setStatisticType(OFStatisticsType.FLOW);
+            req.setStatistics(stats);
+            lengthU += req.getLengthU();
+            req.setLengthU(lengthU);
+
+            List<OFStatistics> entries = null;
+            try {
+                Future<List<OFStatistics>> dfuture = sw.getStatistics(req);
+                entries = dfuture.get();
+            } catch (IOException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                return null;
+            } catch (InterruptedException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                return null;
+            } catch (ExecutionException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                return null;
+            }
+
+            Set<FlowEntryWrapper> results = new HashSet<FlowEntryWrapper>();
+            for (OFStatistics result : entries) {
+                OFFlowStatisticsReply entry = (OFFlowStatisticsReply) result;
+                FlowEntryWrapper fe = new FlowEntryWrapper(entry);
+                results.add(fe);
+            }
+            return results;
+        }
 
     }
 
     /**
      * FlowEntryWrapper represents abstract FlowEntry which is embodied
      * by FlowEntryId (from GraphDB) or OFFlowStatisticsReply (from switch).
-     * @author Brian
      *
+     * @author Brian
      */
     class FlowEntryWrapper {
-    FlowEntryId flowEntryId;
-    // TODO: fix when FlowSynchronizer is refactored
-    // IFlowEntry iFlowEntry;
-    OFFlowStatisticsReply statisticsReply;
+        FlowEntryId flowEntryId;
+        // TODO: fix when FlowSynchronizer is refactored
+        // IFlowEntry iFlowEntry;
+        OFFlowStatisticsReply statisticsReply;
 
 
-	// TODO: fix when FlowSynchronizer is refactored
-	/*
-	public FlowEntryWrapper(IFlowEntry entry) {
-	    flowEntryId = new FlowEntryId(entry.getFlowEntryId());
-	    iFlowEntry = entry;
-	}
-	*/
+        // TODO: fix when FlowSynchronizer is refactored
+    /*
+    public FlowEntryWrapper(IFlowEntry entry) {
+        flowEntryId = new FlowEntryId(entry.getFlowEntryId());
+        iFlowEntry = entry;
+    }
+    */
 
-	public FlowEntryWrapper(OFFlowStatisticsReply entry) {
-	    flowEntryId = new FlowEntryId(entry.getCookie());
-	    statisticsReply = entry;
-	}
+        public FlowEntryWrapper(OFFlowStatisticsReply entry) {
+            flowEntryId = new FlowEntryId(entry.getCookie());
+            statisticsReply = entry;
+        }
 
-	/**
-	 * Install this FlowEntry to a switch via FlowPusher.
-	 * @param sw Switch to which flow will be installed.
-	 */
-	double dbTime, extractTime, pushTime;
-	public void addToSwitch(IOFSwitch sw) {
-	    if (statisticsReply != null) {
-		log.error("Error adding existing flow entry {} to sw {}",
-			  statisticsReply.getCookie(), sw.getId());
-		return;
-	    }
+        /**
+         * Install this FlowEntry to a switch via FlowPusher.
+         *
+         * @param sw Switch to which flow will be installed.
+         */
+        double dbTime, extractTime, pushTime;
 
-	    double startDB = System.nanoTime();
-	    // Get the Flow Entry state from the Network Graph
-	    // TODO: fix when FlowSynchronizer is refactored
-	    /*
-	    if (iFlowEntry == null) {
-            try {
-		// TODO: fix when FlowSynchronizer is refactored
-            	iFlowEntry = dbHandler.searchFlowEntry(flowEntryId);
-            } catch (Exception e) {
-            	log.error("Error finding flow entry {} in Network Graph",
-            			flowEntryId);
-            	return;
+        public void addToSwitch(IOFSwitch sw) {
+            if (statisticsReply != null) {
+                log.error("Error adding existing flow entry {} to sw {}",
+                        statisticsReply.getCookie(), sw.getId());
+                return;
             }
-	    }
-	    */
-	    dbTime = System.nanoTime() - startDB;
 
-	    //
-	    // TODO: The old FlowDatabaseOperation class is gone, so the code
-	    //
-	    /*
-	    double startExtract = System.nanoTime();
-	    FlowEntry flowEntry =
-		FlowDatabaseOperation.extractFlowEntry(iFlowEntry);
-	    if (flowEntry == null) {
-		log.error("Cannot add flow entry {} to sw {} : flow entry cannot be extracted",
-			  flowEntryId, sw.getId());
-		return;
-	    }
-	    extractTime = System.nanoTime() - startExtract;
+            double startDB = System.nanoTime();
+            // Get the Flow Entry state from the Network Graph
+            // TODO: fix when FlowSynchronizer is refactored
+        /*
+        if (iFlowEntry == null) {
+            try {
+        // TODO: fix when FlowSynchronizer is refactored
+                iFlowEntry = dbHandler.searchFlowEntry(flowEntryId);
+            } catch (Exception e) {
+                log.error("Error finding flow entry {} in Network Graph",
+                        flowEntryId);
+                return;
+            }
+        }
+        */
+            dbTime = System.nanoTime() - startDB;
 
-	    double startPush = System.nanoTime();
-	    pusher.pushFlowEntry(sw, flowEntry, MsgPriority.HIGH);
-	    pushTime = System.nanoTime() - startPush;
-	    */
-	}
+            //
+            // TODO: The old FlowDatabaseOperation class is gone, so the code
+            //
+        /*
+        double startExtract = System.nanoTime();
+        FlowEntry flowEntry =
+        FlowDatabaseOperation.extractFlowEntry(iFlowEntry);
+        if (flowEntry == null) {
+        log.error("Cannot add flow entry {} to sw {} : flow entry cannot be extracted",
+              flowEntryId, sw.getId());
+        return;
+        }
+        extractTime = System.nanoTime() - startExtract;
 
-	/**
-	 * Remove this FlowEntry from a switch via FlowPusher.
-	 * @param sw Switch from which flow will be removed.
-	 */
-	public void removeFromSwitch(IOFSwitch sw) {
-	    if (statisticsReply == null) {
-		log.error("Error removing non-existent flow entry {} from sw {}",
-			  flowEntryId, sw.getId());
-		return;
-	    }
+        double startPush = System.nanoTime();
+        pusher.pushFlowEntry(sw, flowEntry, MsgPriority.HIGH);
+        pushTime = System.nanoTime() - startPush;
+        */
+        }
 
-	    // Convert Statistics Reply to Flow Mod, then write it
-	    OFFlowMod fm = new OFFlowMod();
-	    fm.setCookie(statisticsReply.getCookie());
-	    fm.setCommand(OFFlowMod.OFPFC_DELETE_STRICT);
-	    fm.setLengthU(OFFlowMod.MINIMUM_LENGTH);
-	    fm.setMatch(statisticsReply.getMatch());
-	    fm.setPriority(statisticsReply.getPriority());
-	    fm.setOutPort(OFPort.OFPP_NONE);
+        /**
+         * Remove this FlowEntry from a switch via FlowPusher.
+         *
+         * @param sw Switch from which flow will be removed.
+         */
+        public void removeFromSwitch(IOFSwitch sw) {
+            if (statisticsReply == null) {
+                log.error("Error removing non-existent flow entry {} from sw {}",
+                        flowEntryId, sw.getId());
+                return;
+            }
 
-	    pusher.add(sw, fm, MsgPriority.HIGH);
-	}
+            // Convert Statistics Reply to Flow Mod, then write it
+            OFFlowMod fm = new OFFlowMod();
+            fm.setCookie(statisticsReply.getCookie());
+            fm.setCommand(OFFlowMod.OFPFC_DELETE_STRICT);
+            fm.setLengthU(OFFlowMod.MINIMUM_LENGTH);
+            fm.setMatch(statisticsReply.getMatch());
+            fm.setPriority(statisticsReply.getPriority());
+            fm.setOutPort(OFPort.OFPP_NONE);
 
-	/**
-	 * Return the hash code of the Flow Entry ID
-	 */
-	@Override
-	public int hashCode() {
-	    return flowEntryId.hashCode();
-	}
+            pusher.add(sw, fm, MsgPriority.HIGH);
+        }
 
-	/**
-	 * Returns true of the object is another Flow Entry ID with 
-	 * the same value; otherwise, returns false.
-	 * 
-	 * @param Object to compare
-	 * @return true if the object has the same Flow Entry ID.
-	 */
-	@Override
-	public boolean equals(Object obj){
-	    if(obj != null && obj.getClass() == this.getClass()) {
-		FlowEntryWrapper entry = (FlowEntryWrapper) obj;
-		// TODO: we need to actually compare the match + actions
-		return this.flowEntryId.equals(entry.flowEntryId);
-	    }
-	    return false;
-	}
+        /**
+         * Return the hash code of the Flow Entry ID
+         */
+        @Override
+        public int hashCode() {
+            return flowEntryId.hashCode();
+        }
 
-	@Override
-	public String toString() {
-	    return flowEntryId.toString();
-	}
+        /**
+         * Returns true of the object is another Flow Entry ID with
+         * the same value; otherwise, returns false.
+         *
+         * @param Object to compare
+         * @return true if the object has the same Flow Entry ID.
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (obj != null && obj.getClass() == this.getClass()) {
+                FlowEntryWrapper entry = (FlowEntryWrapper) obj;
+                // TODO: we need to actually compare the match + actions
+                return this.flowEntryId.equals(entry.flowEntryId);
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return flowEntryId.toString();
+        }
     }
 }
