* Added initial support for add/get/delete Flow state to the Network MAP via the REST API
  NOTE: The "add" REST API can't be used as-is.
* Added initial support for reading the Flow state from the Network MAP by the Controller
  and sending it to the switches.
  Currently, the Controller reads periodically the Flow entries (every 3 seconds)
  NOTE: The writing of the OpenFlow state to the switches is not tested.

The Python scripts for to add/delete/get flows are intentionally omitted until
the "add" REST API issue is resolved.

NOTE: Two new keys have been added to the database: "flow_id" and "flow_entry_id".
This requires that the older database should be deleted, because Cassandra
doesn't allow adding new keys to an existing database.
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java b/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
index 4af1deb..8788aa7 100644
--- a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
+++ b/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
@@ -132,4 +132,101 @@
 		@GremlinGroovy("_().in('host').in('on').path(){it.number}{it.dpid}")
 		public Iterable<SwitchPort> getAttachmentPoints();*/
 	}
+
+public interface IFlowPath extends IBaseObject {
+		@Property("flow_id")
+		public String getFlowId();
+
+		@Property("flow_id")
+		public void setFlowId(String flowId);
+
+		@Property("installer_id")
+		public String getInstallerId();
+
+		@Property("installer_id")
+		public void setInstallerId(String installerId);
+
+		@Property("src_switch")
+		public String getSrcSwitch();
+
+		@Property("src_switch")
+		public void setSrcSwitch(String srcSwitch);
+
+		@Property("src_port")
+		public Short getSrcPort();
+
+		@Property("src_port")
+		public void setSrcPort(Short srcPort);
+
+		@Property("dst_switch")
+		public String getDstSwitch();
+
+		@Property("dst_switch")
+		public void setDstSwitch(String dstSwitch);
+
+		@Property("dst_port")
+		public Short getDstPort();
+
+		@Property("dst_port")
+		public void setDstPort(Short dstPort);
+
+		@Adjacency(label="flow", direction=Direction.IN)
+		public Iterable<IFlowEntry> getFlowEntries();
+
+		@Adjacency(label="flow", direction=Direction.IN)
+		public void addFlowEntry(final IFlowEntry flowEntry);
+
+		@Adjacency(label="flow", direction=Direction.IN)
+		public void removeFlowEntry(final IFlowEntry flowEntry);
+	}
+
+public interface IFlowEntry extends IBaseObject {
+		@Property("flow_entry_id")
+		public String getFlowEntryId();
+
+		@Property("flow_entry_id")
+		public void setFlowEntryId(String flowEntryId);
+
+		@Property("switch_dpid")
+		public String getSwitchDpid();
+
+		@Property("switch_dpid")
+		public void setSwitchDpid(String switchDpid);
+
+		@Property("in_port")
+		public Short getInPort();
+
+		@Property("in_port")
+		public void setInPort(Short inPort);
+
+		@Property("out_port")
+		public Short getOutPort();
+
+		@Property("out_port")
+		public void setOutPort(Short outPort);
+
+		@Property("user_state")
+		public String getUserState();
+
+		@Property("user_state")
+		public void setUserState(String userState);
+
+		@Property("switch_state")
+		public String getSwitchState();
+
+		@Property("switch_state")
+		public void setSwitchState(String switchState);
+
+		@Property("error_state_type")
+		public String getErrorStateType();
+
+		@Property("error_state_type")
+		public void setErrorStateType(String errorStateType);
+
+		@Property("error_state_code")
+		public String getErrorStateCode();
+
+		@Property("error_state_code")
+		public void setErrorStateCode(String errorStateCode);
+	}
 }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 12ed505..11519b7 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -1,10 +1,22 @@
 package net.floodlightcontroller.flowcache;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.INetMapStorage;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
@@ -13,20 +25,178 @@
 import net.floodlightcontroller.flowcache.web.FlowWebRoutable;
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.util.CallerId;
+import net.floodlightcontroller.util.DataPath;
+import net.floodlightcontroller.util.Dpid;
 import net.floodlightcontroller.util.DataPathEndpoints;
+import net.floodlightcontroller.util.FlowEntry;
+import net.floodlightcontroller.util.FlowEntryId;
+import net.floodlightcontroller.util.FlowEntrySwitchState;
+import net.floodlightcontroller.util.FlowEntryUserState;
 import net.floodlightcontroller.util.FlowId;
 import net.floodlightcontroller.util.FlowPath;
+import net.floodlightcontroller.util.OFMessageDamper;
+import net.floodlightcontroller.util.Port;
+import net.onrc.onos.util.GraphDBConnection;
+import net.onrc.onos.util.GraphDBConnection.Transaction;
+
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionOutput;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class FlowManager implements IFloodlightModule, IFlowService {
+public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
+
+    public GraphDBConnection conn;
 
     protected IRestApiService restApi;
+    protected IFloodlightProviderService floodlightProvider;
+
+    protected OFMessageDamper messageDamper;
+
+    protected static int OFMESSAGE_DAMPER_CAPACITY = 50000; // TODO: find sweet spot
+    protected static int OFMESSAGE_DAMPER_TIMEOUT = 250;	// ms
+    public static short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 0;	// infinity
+    public static short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0;	// infinite
 
     /** The logger. */
-    private static Logger logger =
-	LoggerFactory.getLogger(FlowManager.class);
+    private static Logger log = LoggerFactory.getLogger(FlowManager.class);
+
+    // The periodic task(s)
+    private final ScheduledExecutorService scheduler =
+	Executors.newScheduledThreadPool(1);
+    final Runnable reader = new Runnable() {
+	    public void run() {
+		// log.debug("Reading Flow Entries from the Network Map...");
+		if (floodlightProvider == null) {
+		    log.debug("FloodlightProvider service not found!");
+		    return;
+		}
+
+		Map<Long, IOFSwitch> mySwitches = floodlightProvider.getSwitches();
+
+		// Fetch all Flow Entries
+		Iterable<IFlowEntry> flowEntries = conn.utils().getAllFlowEntries(conn);
+		for (IFlowEntry flowEntryObj : flowEntries) {
+		    FlowEntryId flowEntryId =
+			new FlowEntryId(flowEntryObj.getFlowEntryId());
+		    String userState = flowEntryObj.getUserState();
+		    String switchState = flowEntryObj.getSwitchState();
+
+		    log.debug("Found Flow Entry {}: ", flowEntryId.toString());
+		    log.debug("User State {}:", userState);
+		    log.debug("Switch State {}:", switchState);
+
+		    if (! switchState.equals("FE_SWITCH_NOT_UPDATED")) {
+			// Ignore the entry: nothing to do
+			continue;
+		    }
+
+		    Dpid dpid = new Dpid(flowEntryObj.getSwitchDpid());
+		    IOFSwitch mySwitch = mySwitches.get(dpid.value());
+		    if (mySwitch == null) {
+			log.debug("Flow Entry ignored: not my switch");
+			continue;
+		    }
+
+		    //
+		    // Create the Open Flow Flow Modification Entry to push
+		    //
+		    OFFlowMod fm =
+			(OFFlowMod) floodlightProvider.getOFMessageFactory()
+			.getMessage(OFType.FLOW_MOD);
+		    long cookie = flowEntryId.value();
+
+		    short flowModCommand = OFFlowMod.OFPFC_ADD;
+		    if (userState.equals("FE_USER_ADD")) {
+			flowModCommand = OFFlowMod.OFPFC_ADD;
+		    } else if (userState.equals("FE_USER_MODIFY")) {
+			flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
+		    } else if (userState.equals("FE_USER_DELETE")) {
+			flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
+		    } else {
+			// Unknown user state. Ignore the entry
+			continue;
+		    }
+
+		    OFMatch match = new OFMatch();
+		    match.setInputPort(flowEntryObj.getInPort());
+
+		    OFActionOutput action = new OFActionOutput();
+		    action.setMaxLength((short)0xffff);
+		    action.setPort(flowEntryObj.getOutPort());
+		    List<OFAction> actions = new ArrayList<OFAction>();
+		    actions.add(action);
+
+		    fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
+			.setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
+			.setBufferId(OFPacketOut.BUFFER_ID_NONE)
+			.setCookie(cookie)
+			.setCommand(flowModCommand)
+			.setMatch(match)
+			.setActions(actions)
+			.setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+		    //
+		    // TODO: Set the following flag
+		    // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
+		    // See method ForwardingBase::pushRoute()
+		    //
+		    try {
+			messageDamper.write(mySwitch, fm, null);
+			mySwitch.flush();
+			flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
+			if (userState.equals("FE_USER_DELETE")) {
+			    // Delete the entry
+			    IFlowPath flowObj = null;
+			    flowObj = conn.utils().getFlowPathByFlowEntry(conn,
+					flowEntryObj);
+			    if (flowObj != null)
+				log.debug("Found FlowPath to be deleted");
+			    else
+				log.debug("Did not find FlowPath to be deleted");
+			    flowObj.removeFlowEntry(flowEntryObj);
+			    conn.utils().removeFlowEntry(conn, flowEntryObj);
+
+			    // Test whether the last flow entry
+			    Iterable<IFlowEntry> tmpflowEntries =
+				flowObj.getFlowEntries();
+			    boolean found = false;
+			    for (IFlowEntry tmpflowEntryObj : tmpflowEntries) {
+				found = true;
+				break;
+			    }
+			    if (! found) {
+				// Remove the Flow Path as well
+				conn.utils().removeFlowPath(conn, flowObj);
+			    }
+			}
+		    } catch (IOException e) {
+			log.error("Failure writing flow mod from network map", e);
+		    }
+		}
+		conn.endTx(Transaction.COMMIT);
+	    }
+	};
+    final ScheduledFuture<?> readerHandle =
+	scheduler.scheduleAtFixedRate(reader, 3, 3, TimeUnit.SECONDS);
+
+    @Override
+    public void init(String conf) {
+	conn = GraphDBConnection.getInstance(conf);
+    }
+
+    public void finalize() {
+	close();
+    }
+
+    @Override
+    public void close() {
+	conn.close();
+    }
 
     @Override
     public Collection<Class<? extends IFloodlightService>> getModuleServices() {
@@ -52,6 +222,7 @@
                                                     getModuleDependencies() {
 	Collection<Class<? extends IFloodlightService>> l =
 	    new ArrayList<Class<? extends IFloodlightService>>();
+	l.add(IFloodlightProviderService.class);
 	l.add(IRestApiService.class);
         return l;
     }
@@ -59,7 +230,14 @@
     @Override
     public void init(FloodlightModuleContext context)
 	throws FloodlightModuleException {
+	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
 	restApi = context.getServiceImpl(IRestApiService.class);
+	messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
+					    EnumSet.of(OFType.FLOW_MOD),
+					    OFMESSAGE_DAMPER_TIMEOUT);
+	// TODO: An ugly hack!
+	String conf = "/tmp/cassandra.titan";
+	this.init(conf);
     }
 
     @Override
@@ -79,7 +257,135 @@
      */
     @Override
     public boolean addFlow(FlowPath flowPath, FlowId flowId) {
-	// TODO
+
+	//
+	// Assign the FlowEntry IDs
+	// TODO: This is an ugly hack!
+	// The Flow Entry IDs are set to 1000*FlowId + Index
+	//
+	int i = 1;
+	for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
+	    long id = flowPath.flowId().value() * 1000 + i;
+	    ++i;
+	    flowEntry.setFlowEntryId(new FlowEntryId(id));
+	}
+
+	IFlowPath flowObj = null;
+	try {
+	    if ((flowObj = conn.utils().searchFlowPath(conn, flowPath.flowId()))
+		!= null) {
+		log.debug("Adding FlowPath with FlowId {}: found existing FlowPath",
+			  flowPath.flowId().toString());
+	    } else {
+		flowObj = conn.utils().newFlowPath(conn);
+		log.debug("Adding FlowPath with FlowId {}: creating new FlowPath",
+			  flowPath.flowId().toString());
+	    }
+	} catch (Exception e) {
+	    // TODO: handle exceptions
+	    conn.endTx(Transaction.ROLLBACK);
+	    log.error(":addFlow FlowId:{} failed",
+		      flowPath.flowId().toString());
+	}
+	if (flowObj == null)
+	    return false;
+
+	//
+	// Set the Flow key:
+	// - flowId
+	//
+	flowObj.setFlowId(flowPath.flowId().toString());
+	flowObj.setType("flow");
+
+	//
+	// Set the Flow attributes:
+	// - flowPath.installerId()
+	// - flowPath.dataPath().srcPort()
+	// - flowPath.dataPath().dstPort()
+	//
+	flowObj.setInstallerId(flowPath.installerId().toString());
+	flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
+	flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
+	flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
+	flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
+
+	// Flow edges:
+	//   HeadFE
+
+
+	//
+	// Flow Entries:
+	// flowPath.dataPath().flowEntries()
+	//
+	for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
+	    IFlowEntry flowEntryObj = null;
+	    boolean found = false;
+	    try {
+		if ((flowEntryObj = conn.utils().searchFlowEntry(conn, flowEntry.flowEntryId())) != null) {
+		    log.debug("Adding FlowEntry with FlowEntryId {}: found existing FlowEntry",
+			      flowEntry.flowEntryId().toString());
+		    found = true;
+		} else {
+		    flowEntryObj = conn.utils().newFlowEntry(conn);
+		    log.debug("Adding FlowEntry with FlowEntryId {}: creating new FlowEntry",
+			      flowEntry.flowEntryId().toString());
+		}
+	    } catch (Exception e) {
+		// TODO: handle exceptions
+		conn.endTx(Transaction.ROLLBACK);
+		log.error(":addFlow FlowEntryId:{} failed",
+			  flowEntry.flowEntryId().toString());
+	    }
+	    if (flowEntryObj == null)
+		return false;
+
+	    //
+	    // Set the Flow Entry key:
+	    // - flowEntry.flowEntryId()
+	    //
+	    flowEntryObj.setFlowEntryId(flowEntry.flowEntryId().toString());
+	    flowEntryObj.setType("flow_entry");
+
+	    // 
+	    // Set the Flow Entry attributes:
+	    // - flowEntry.flowEntryMatch()
+	    // - flowEntry.flowEntryActions()
+	    // - flowEntry.dpid()
+	    // - flowEntry.inPort()
+	    // - flowEntry.outPort()
+	    // - flowEntry.flowEntryUserState()
+	    // - flowEntry.flowEntrySwitchState()
+	    // - flowEntry.flowEntryErrorState()
+	    //
+	    flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
+	    flowEntryObj.setInPort(flowEntry.inPort().value());
+	    flowEntryObj.setOutPort(flowEntry.outPort().value());
+	    // TODO: Hacks with hard-coded state names!
+	    if (found)
+		flowEntryObj.setUserState("FE_USER_MODIFY");
+	    else
+		flowEntryObj.setUserState("FE_USER_ADD");
+	    flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
+	    //
+	    // TODO: Take care of the FlowEntryMatch, FlowEntryActions,
+	    // and FlowEntryErrorState.
+	    //
+
+	    // Flow Entries edges:
+	    //   Flow
+	    //   NextFE
+	    //   InPort
+	    //   OutPort
+	    //   Switch
+	    if (! found)
+		flowObj.addFlowEntry(flowEntryObj);
+	}
+	conn.endTx(Transaction.COMMIT);
+
+	//
+	// TODO: We need a proper Flow ID allocation mechanism.
+	//
+	flowId.setValue(flowPath.flowId().value());
 	return true;
     }
 
@@ -91,7 +397,46 @@
      */
     @Override
     public boolean deleteFlow(FlowId flowId) {
-	// TODO
+	IFlowPath flowObj = null;
+	//
+	// We just mark the entries for deletion,
+	// and let the switches remove each individual entry after
+	// it has been removed from the switches.
+	//
+	try {
+	    if ((flowObj = conn.utils().searchFlowPath(conn, flowId))
+		!= null) {
+		log.debug("Deleting FlowPath with FlowId {}: found existing FlowPath",
+			  flowId.toString());
+	    } else {
+		log.debug("Deleting FlowPath with FlowId {}:  FlowPath not found",
+			  flowId.toString());
+	    }
+	} catch (Exception e) {
+	    // TODO: handle exceptions
+	    conn.endTx(Transaction.ROLLBACK);
+	    log.error(":deleteFlow FlowId:{} failed", flowId.toString());
+	}
+	if (flowObj == null)
+	    return true;		// OK: No such flow
+
+	//
+	// Find and mark for deletion all Flow Entries
+	//
+	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+	boolean empty = true;	// TODO: an ugly hack
+	for (IFlowEntry flowEntryObj : flowEntries) {
+	    empty = false;
+	    // flowObj.removeFlowEntry(flowEntryObj);
+	    // conn.utils().removeFlowEntry(conn, flowEntryObj);
+	    flowEntryObj.setUserState("FE_USER_DELETE");
+	    flowEntryObj.setSwitchState("FE_SWITCH_NOT_UPDATED");
+	}
+	// Remove from the database empty flows
+	if (empty)
+	    conn.utils().removeFlowPath(conn, flowObj);
+	conn.endTx(Transaction.COMMIT);
+
 	return true;
     }
 
@@ -99,13 +444,62 @@
      * Get a previously added flow.
      *
      * @param flowId the Flow ID of the flow to get.
-     * @param flowPath the return-by-reference flow path.
-     * @return true on success, otherwise false.
+     * @return the Flow Path if found, otherwise null.
      */
     @Override
-    public boolean getFlow(FlowId flowId, FlowPath flowPath) {
-	// TODO
-	return true;
+    public FlowPath getFlow(FlowId flowId) {
+	IFlowPath flowObj = null;
+	try {
+	    if ((flowObj = conn.utils().searchFlowPath(conn, flowId))
+		!= null) {
+		log.debug("Get FlowPath with FlowId {}: found existing FlowPath",
+			  flowId.toString());
+	    } else {
+		log.debug("Get FlowPath with FlowId {}:  FlowPath not found",
+			  flowId.toString());
+	    }
+	} catch (Exception e) {
+	    // TODO: handle exceptions
+	    conn.endTx(Transaction.ROLLBACK);
+	    log.error(":getFlow FlowId:{} failed", flowId.toString());
+	}
+	if (flowObj == null)
+	    return null;		// Flow not found
+
+	//
+	// Extract the Flow state
+	//
+	FlowPath flowPath = new FlowPath();
+	flowPath.setFlowId(new FlowId(flowObj.getFlowId()));
+	flowPath.setInstallerId(new CallerId(flowObj.getInstallerId()));
+	flowPath.dataPath().srcPort().setDpid(new Dpid(flowObj.getSrcSwitch()));
+	flowPath.dataPath().srcPort().setPort(new Port(flowObj.getSrcPort()));
+	flowPath.dataPath().dstPort().setDpid(new Dpid(flowObj.getDstSwitch()));
+	flowPath.dataPath().dstPort().setPort(new Port(flowObj.getDstPort()));
+
+	//
+	// Extract all Flow Entries
+	//
+	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+	for (IFlowEntry flowEntryObj : flowEntries) {
+	    FlowEntry flowEntry = new FlowEntry();
+	    flowEntry.setFlowEntryId(new FlowEntryId(flowEntryObj.getFlowEntryId()));
+	    flowEntry.setDpid(new Dpid(flowEntryObj.getSwitchDpid()));
+	    flowEntry.setInPort(new Port(flowEntryObj.getInPort()));
+	    flowEntry.setOutPort(new Port(flowEntryObj.getOutPort()));
+	    String userState = flowEntryObj.getUserState();
+	    flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
+	    String switchState = flowEntryObj.getSwitchState();
+	    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
+	    //
+	    // TODO: Take care of the FlowEntryMatch, FlowEntryActions,
+	    // and FlowEntryErrorState.
+	    //
+	    flowPath.dataPath().flowEntries().add(flowEntry);
+	}
+	conn.endTx(Transaction.COMMIT);
+
+	return flowPath;
     }
 
     /**
@@ -114,36 +508,35 @@
      *
      * @param installerId the Caller ID of the installer of the flow to get.
      * @param dataPathEndpoints the data path endpoints of the flow to get.
-     * @param flowPath the return-by-reference flow path.
-     * @return true on success, otherwise false.
+     * @return the Flow Path if found, otherwise null.
      */
     @Override
-    public boolean getFlow(CallerId installerId,
-			   DataPathEndpoints dataPathEndpoints,
-			   FlowPath flowPath) {
+    public FlowPath getFlow(CallerId installerId,
+			    DataPathEndpoints dataPathEndpoints) {
 	// TODO
-	return true;
+	return null;
     }
 
     /**
      * Get all installed flows by all installers for given data path endpoints.
      *
      * @param dataPathEndpoints the data path endpoints of the flows to get.
-     * @param flowPaths the return-by-reference list of flows.
+     * @return the Flow Paths if found, otherwise null.
      */
     @Override
-    public void getAllFlows(DataPathEndpoints dataPathEndpoints,
-			    ArrayList<FlowPath> flowPaths) {
+    public ArrayList<FlowPath> getAllFlows(DataPathEndpoints dataPathEndpoints) {
 	// TODO
+	return null;
     }
 
     /**
      * Get all installed flows by all installers.
      *
-     * @param flowPaths the return-by-reference list of flows.
+     * @return the Flow Paths if found, otherwise null.
      */
     @Override
-    public void getAllFlows(ArrayList<FlowPath> flowPaths) {
+    public ArrayList<FlowPath> getAllFlows() {
 	// TODO
+	return null;
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java b/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
index 956caab..c14c0c1 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
@@ -36,10 +36,9 @@
      * Get a previously added flow.
      *
      * @param flowId the Flow ID of the flow to get.
-     * @param flowPath the return-by-reference flow path.
-     * @return true on success, otherwise false.
+     * @return the Flow Path if found, otherwise null.
      */
-    boolean getFlow(FlowId flowId, FlowPath flowPath);
+    FlowPath getFlow(FlowId flowId);
 
     /**
      * Get a previously added flow by a specific installer for given
@@ -47,26 +46,23 @@
      *
      * @param installerId the Caller ID of the installer of the flow to get.
      * @param dataPathEndpoints the data path endpoints of the flow to get.
-     * @param flowPath the return-by-reference flow path.
-     * @return true on success, otherwise false.
+     * @return the Flow Path if found, otherwise null.
      */
-    boolean getFlow(CallerId installerId,
-		    DataPathEndpoints dataPathEndpoints,
-		    FlowPath flowPath);
+    FlowPath getFlow(CallerId installerId,
+		     DataPathEndpoints dataPathEndpoints);
 
     /**
      * Get all installed flows by all installers for given data path endpoints.
      *
      * @param dataPathEndpoints the data path endpoints of the flows to get.
-     * @param flowPaths the return-by-reference list of flows.
+     * @return the Flow Paths if found, otherwise null.
      */
-    void getAllFlows(DataPathEndpoints dataPathEndpoints,
-		     ArrayList<FlowPath> flowPaths);
+    ArrayList<FlowPath> getAllFlows(DataPathEndpoints dataPathEndpoints);
 
     /**
      * Get all installed flows by all installers.
      *
-     * @param flowPaths the return-by-reference list of flows.
+     * @return the Flow Paths if found, otherwise null.
      */
-    void getAllFlows(ArrayList<FlowPath> flowPaths);
+    ArrayList<FlowPath> getAllFlows();
 }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java
index feb43d3..1646012 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java
@@ -38,6 +38,9 @@
 	//
 	ObjectMapper mapper = new ObjectMapper();
 	String flowPathStr = (String) getRequestAttributes().get("flow");
+	// TODO: Remove it later
+	// String flowPathStr = "{\"flowId\":{\"value\":\"5\"},\"installerId\":{\"value\":\"FOOBAR\"},\"dataPath\":{\"srcPort\":{\"dpid\":{\"value\":\"00:00:00:00:00:00:00:01\"},\"port\":{\"value\":0}},\"dstPort\":{\"dpid\":{\"value\":\"00:00:00:00:00:00:00:02\"},\"port\":{\"value\":0}},\"flowEntries\":[{\"flowEntryId\":null,\"flowEntryMatch\":null,\"flowEntryActions\":null,\"dpid\":{\"value\":\"00:00:00:00:00:00:00:01\"},\"inPort\":{\"value\":0},\"outPort\":{\"value\":1},\"flowEntryUserState\":\"FE_USER_UNKNOWN\",\"flowEntrySwitchState\":\"FE_SWITCH_UNKNOWN\",\"flowEntryErrorState\":null},{\"flowEntryId\":null,\"flowEntryMatch\":null,\"flowEntryActions\":null,\"dpid\":{\"value\":\"00:00:00:00:00:00:00:02\"},\"inPort\":{\"value\":9},\"outPort\":{\"value\":0},\"flowEntryUserState\":\"FE_USER_UNKNOWN\",\"flowEntrySwitchState\":\"FE_SWITCH_UNKNOWN\",\"flowEntryErrorState\":null}]}}";
+
 	FlowPath flowPath = null;
 	log.debug("Add Flow Path: " + flowPathStr);
 	try {
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java
index c485d91..34d79c8 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java
@@ -19,7 +19,7 @@
 
     @Get("json")
     public ArrayList<FlowPath> retrieve() {
-	ArrayList<FlowPath> result = new ArrayList<FlowPath>();
+	ArrayList<FlowPath> result = null;
 
         IFlowService flowService =
                 (IFlowService)getContext().getAttributes().
@@ -48,7 +48,7 @@
 	DataPathEndpoints dataPathEndpoints =
 	    new DataPathEndpoints(srcSwitchPort, dstSwitchPort);
 
-	flowService.getAllFlows(dataPathEndpoints, result);
+	result = flowService.getAllFlows(dataPathEndpoints);
 
         return result;
     }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java
index deb4d04..92317cf 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java
@@ -15,7 +15,7 @@
 
     @Get("json")
     public ArrayList<FlowPath> retrieve() {
-	ArrayList<FlowPath> result = new ArrayList<FlowPath>();
+	ArrayList<FlowPath> result = null;
 
         IFlowService flowService =
                 (IFlowService)getContext().getAttributes().
@@ -29,9 +29,7 @@
 	// Extract the arguments
 	log.debug("Get All Flows Endpoints");
 
-	flowService.getAllFlows(result);
-	FlowPath flowPath = new FlowPath();
-	result.add(flowPath);
+	result = flowService.getAllFlows();
 
         return result;
     }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java
index d5b2730..85d5b7e 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java
@@ -31,7 +31,7 @@
 
 	log.debug("Get Flow Id: " + flowIdStr);
 
-	flowService.getFlow(flowId, result);
+	result = flowService.getFlow(flowId);
 
         return result;
     }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByInstallerIdResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByInstallerIdResource.java
index cb4e6ef..33eca0b 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByInstallerIdResource.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByInstallerIdResource.java
@@ -50,7 +50,7 @@
 	DataPathEndpoints dataPathEndpoints =
 	    new DataPathEndpoints(srcSwitchPort, dstSwitchPort);
 
-	flowService.getFlow(installerId, dataPathEndpoints, result);
+	result = flowService.getFlow(installerId, dataPathEndpoints);
 
         return result;
     }
diff --git a/src/main/java/net/floodlightcontroller/util/DataPath.java b/src/main/java/net/floodlightcontroller/util/DataPath.java
index 71e0a2f..b2dded6 100644
--- a/src/main/java/net/floodlightcontroller/util/DataPath.java
+++ b/src/main/java/net/floodlightcontroller/util/DataPath.java
@@ -19,6 +19,8 @@
      * Default constructor.
      */
     public DataPath() {
+	srcPort = new SwitchPort();
+	dstPort = new SwitchPort();
 	flowEntries = new ArrayList<FlowEntry>();
     }
 
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntry.java b/src/main/java/net/floodlightcontroller/util/FlowEntry.java
index dfb8f82..efab0cf 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntry.java
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntry.java
@@ -4,33 +4,13 @@
 import net.floodlightcontroller.util.FlowEntryActions;
 import net.floodlightcontroller.util.FlowEntryId;
 import net.floodlightcontroller.util.FlowEntryMatch;
+import net.floodlightcontroller.util.FlowEntrySwitchState;
+import net.floodlightcontroller.util.FlowEntryUserState;
 import net.floodlightcontroller.util.Port;
 
 import org.codehaus.jackson.annotate.JsonProperty;
 
 /**
- * The Flow Entry state as set by the user (via the ONOS API).
- */
-enum FlowEntryUserState {
-	FE_USER_UNKNOWN,		// Initialization value: state unknown
-	FE_USER_ADD,			// Flow entry that is added
-	FE_USER_MODIFY,			// Flow entry that is modified
-	FE_USER_DELETE			// Flow entry that is deleted
-}
-
-/**
- * The Flow Entry state as set by the controller.
- */
-enum FlowEntrySwitchState {
-	FE_SWITCH_UNKNOWN,		// Initialization value: state unknown
-	FE_SWITCH_NOT_UPDATED,		// Switch not updated with this entry
-	FE_SWITCH_UPDATE_IN_PROGRESS,	// Switch update in progress
-	FE_SWITCH_UPDATED,		// Switch updated with this entry
-	FE_SWITCH_UPDATE_FAILED	// Error updating the switch with this entry
-}
-
-
-/**
  * The class representing the Flow Entry.
  *
  * NOTE: The specification is incomplete. E.g., the entry needs to
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryId.java b/src/main/java/net/floodlightcontroller/util/FlowEntryId.java
index 0874bdb..d322f5e 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntryId.java
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntryId.java
@@ -63,6 +63,6 @@
      */
     @Override
     public String toString() {
-	return Long.toHexString(this.value);
+	return "0x" + Long.toHexString(this.value);
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntrySwitchState.java b/src/main/java/net/floodlightcontroller/util/FlowEntrySwitchState.java
new file mode 100644
index 0000000..4f9882a
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntrySwitchState.java
@@ -0,0 +1,12 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The Flow Entry state as set by the controller.
+ */
+public enum FlowEntrySwitchState {
+	FE_SWITCH_UNKNOWN,		// Initialization value: state unknown
+	FE_SWITCH_NOT_UPDATED,		// Switch not updated with this entry
+	FE_SWITCH_UPDATE_IN_PROGRESS,	// Switch update in progress
+	FE_SWITCH_UPDATED,		// Switch updated with this entry
+	FE_SWITCH_UPDATE_FAILED	// Error updating the switch with this entry
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryUserState.java b/src/main/java/net/floodlightcontroller/util/FlowEntryUserState.java
new file mode 100644
index 0000000..8637b4f
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntryUserState.java
@@ -0,0 +1,11 @@
+package net.floodlightcontroller.util;
+
+/**
+ * The Flow Entry state as set by the user (via the ONOS API).
+ */
+public enum FlowEntryUserState {
+	FE_USER_UNKNOWN,		// Initialization value: state unknown
+	FE_USER_ADD,			// Flow entry that is added
+	FE_USER_MODIFY,			// Flow entry that is modified
+	FE_USER_DELETE			// Flow entry that is deleted
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowPath.java b/src/main/java/net/floodlightcontroller/util/FlowPath.java
index 5b3bbd1..11f23fe 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowPath.java
+++ b/src/main/java/net/floodlightcontroller/util/FlowPath.java
@@ -18,6 +18,7 @@
      * Default constructor.
      */
     public FlowPath() {
+	dataPath = new DataPath();
     }
 
     /**
diff --git a/src/main/java/net/onrc/onos/util/GraphDBConnection.java b/src/main/java/net/onrc/onos/util/GraphDBConnection.java
index a2a8689..724095b 100644
--- a/src/main/java/net/onrc/onos/util/GraphDBConnection.java
+++ b/src/main/java/net/onrc/onos/util/GraphDBConnection.java
@@ -37,6 +37,13 @@
 		        if (!s.contains("dl_address")) {
 		        	graph.createKeyIndex("dl_address", Vertex.class);
 		        }
+		        if (!s.contains("flow_id")) {
+		        	graph.createKeyIndex("flow_id", Vertex.class);
+		        }
+		        if (!s.contains("flow_entry_id")) {
+		        	graph.createKeyIndex("flow_entry_id",
+						     Vertex.class);
+		        }
 		   }
 		   graph.stopTransaction(Conclusion.SUCCESS);
 		   if (utils == null) {
diff --git a/src/main/java/net/onrc/onos/util/GraphDBUtils.java b/src/main/java/net/onrc/onos/util/GraphDBUtils.java
index d01de21..ebc5942 100644
--- a/src/main/java/net/onrc/onos/util/GraphDBUtils.java
+++ b/src/main/java/net/onrc/onos/util/GraphDBUtils.java
@@ -7,8 +7,12 @@
 import com.tinkerpop.gremlin.java.GremlinPipeline;
 
 import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
 import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.floodlightcontroller.util.FlowEntryId;
+import net.floodlightcontroller.util.FlowId;
 
 public class GraphDBUtils implements IDBUtils {
 
@@ -60,4 +64,69 @@
 		return fg.getVertices("type","device",IDeviceObject.class);
 	}
 
+	@Override
+	public IFlowPath searchFlowPath(GraphDBConnection conn,
+					FlowId flowId) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		
+		return fg.getVertices("flow_id", flowId.toString()).iterator().hasNext() ? 
+		    fg.getVertices("flow_id", flowId.toString(),
+				   IFlowPath.class).iterator().next() : null;
+	}
+
+	@Override
+	public IFlowPath newFlowPath(GraphDBConnection conn) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		IFlowPath flowPath = fg.addVertex(null, IFlowPath.class);
+		return flowPath;
+	}
+
+	@Override
+	public void removeFlowPath(GraphDBConnection conn,
+				   IFlowPath flowPath) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		fg.removeVertex(flowPath.asVertex());
+	}
+
+	@Override
+	public IFlowPath getFlowPathByFlowEntry(GraphDBConnection conn,
+						IFlowEntry flowEntry) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		GremlinPipeline<Vertex, IFlowPath> pipe = new GremlinPipeline<Vertex, IFlowPath>();
+		pipe.start(flowEntry.asVertex());
+		pipe.out("flow");
+		FramedVertexIterable<IFlowPath> r = new FramedVertexIterable(conn.getFramedGraph(), pipe, IFlowPath.class);
+		return r.iterator().hasNext() ? r.iterator().next() : null;
+	}
+
+	@Override
+	public IFlowEntry searchFlowEntry(GraphDBConnection conn,
+					  FlowEntryId flowEntryId) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		
+		return fg.getVertices("flow_entry_id", flowEntryId.toString()).iterator().hasNext() ? 
+		    fg.getVertices("flow_entry_id", flowEntryId.toString(),
+				   IFlowEntry.class).iterator().next() : null;
+	}
+
+	@Override
+	public IFlowEntry newFlowEntry(GraphDBConnection conn) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		IFlowEntry flowEntry = fg.addVertex(null, IFlowEntry.class);
+		return flowEntry;
+	}
+
+	@Override
+	public void removeFlowEntry(GraphDBConnection conn,
+				    IFlowEntry flowEntry) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		fg.removeVertex(flowEntry.asVertex());
+	}
+
+	@Override
+        public Iterable<IFlowEntry> getAllFlowEntries(GraphDBConnection conn) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		
+		return fg.getVertices("type", "flow_entry", IFlowEntry.class);
+	}
 }
diff --git a/src/main/java/net/onrc/onos/util/IDBUtils.java b/src/main/java/net/onrc/onos/util/IDBUtils.java
index a27a261..4ff70f3 100644
--- a/src/main/java/net/onrc/onos/util/IDBUtils.java
+++ b/src/main/java/net/onrc/onos/util/IDBUtils.java
@@ -1,8 +1,12 @@
 package net.onrc.onos.util;
 
 import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
 import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.floodlightcontroller.util.FlowEntryId;
+import net.floodlightcontroller.util.FlowId;
 
 public interface IDBUtils {	
 	public ISwitchObject searchSwitch(GraphDBConnection conn, String dpid);
@@ -11,4 +15,15 @@
 	public void removeDevice(GraphDBConnection conn, IDeviceObject dev);
 	public IPortObject searchPort(GraphDBConnection conn, String dpid, short number);
 	public Iterable<IDeviceObject> getDevices(GraphDBConnection conn);
+	public IFlowPath searchFlowPath(GraphDBConnection conn, FlowId flowId);
+	public IFlowPath newFlowPath(GraphDBConnection conn);
+	public void removeFlowPath(GraphDBConnection conn, IFlowPath flowPath);
+        public IFlowPath getFlowPathByFlowEntry(GraphDBConnection conn,
+						IFlowEntry flowEntry);
+	public IFlowEntry searchFlowEntry(GraphDBConnection conn,
+					  FlowEntryId flowEntryId);
+	public IFlowEntry newFlowEntry(GraphDBConnection conn);
+	public void removeFlowEntry(GraphDBConnection conn,
+				    IFlowEntry flowEntry);
+	public Iterable<IFlowEntry> getAllFlowEntries(GraphDBConnection conn);
 }