Renamed networkgraph package to topology.
Moved NetworkGraphPublisher into new topology package.

net.onrc.onos.ofcontroller.networkgraph.* => net.onrc.onos.core.topology.*
net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher => net.onrc.onos.core.topology.NetworkGraphPublisher

Change-Id: I8b156d0fcbba520fee61e92ab659bb02cfa704ac
diff --git a/src/main/java/net/onrc/onos/core/topology/NetworkGraphDatastore.java b/src/main/java/net/onrc/onos/core/topology/NetworkGraphDatastore.java
new file mode 100644
index 0000000..446dd1e
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/NetworkGraphDatastore.java
@@ -0,0 +1,229 @@
+package net.onrc.onos.core.topology;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collection;
+
+import net.onrc.onos.core.datastore.DataStoreClient;
+import net.onrc.onos.core.datastore.IKVClient;
+import net.onrc.onos.core.datastore.topology.KVDevice;
+import net.onrc.onos.core.datastore.topology.KVLink;
+import net.onrc.onos.core.datastore.topology.KVPort;
+import net.onrc.onos.core.datastore.topology.KVSwitch;
+import net.onrc.onos.core.datastore.topology.KVPort.STATUS;
+import net.onrc.onos.core.datastore.utils.KVObject;
+import net.onrc.onos.core.datastore.utils.KVObject.WriteOp;
+import net.onrc.onos.core.topology.PortEvent.SwitchPort;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.net.InetAddresses;
+
+/**
+ * The southbound interface to the network graph which allows clients to
+ * mutate the graph. This class will maintain the invariants of the network
+ * graph. The southbound discovery modules will use this interface to update
+ * the network graph as they learn about the state of the network.
+ *
+ * Modification to the Network Map by this module will:
+ * 1. Writes to Cluster-wide DataStore.
+ * 2. Update ONOS instance In-memory Network Map.
+ * 3. Send-out Notification. (TBD)
+ *    (XXX: To update other instances In-memory Network Map,
+ *          notification should be triggered here.
+ *          But if we want to aggregate notification to minimize notification,
+ *          It might be better for the caller to trigger notification.)
+ *
+ */
+public class NetworkGraphDatastore {
+	private static final Logger log = LoggerFactory.getLogger(NetworkGraphDatastore.class);
+
+	/**
+	 * Add a switch to the database.
+	 *
+	 * @param sw the switch to add.
+	 * @param portEvents the corresponding switch ports to add.
+	 * @return true on success, otherwise false.
+	 */
+	public boolean addSwitch(SwitchEvent sw,
+				 Collection<PortEvent> portEvents) {
+		log.debug("Adding switch {}", sw);
+		ArrayList<WriteOp> groupOp = new ArrayList<>();
+
+		KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
+		rcSwitch.setStatus(KVSwitch.STATUS.ACTIVE);
+
+		IKVClient client = DataStoreClient.getClient();
+
+		// XXX Is ForceCreating Switch on DB OK here?
+		// If ForceCreating, who ever is calling this method needs
+		// to assure that DPID is unique cluster-wide, etc.
+		groupOp.add(rcSwitch.forceCreateOp(client));
+
+		for (PortEvent portEvent : portEvents) {
+			KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
+			rcPort.setStatus(KVPort.STATUS.ACTIVE);
+
+			groupOp.add(rcPort.forceCreateOp(client));
+		}
+
+		boolean failed = KVObject.multiWrite(groupOp);
+
+		if (failed) {
+		    log.error("Adding Switch {} and its ports failed.", sw.getDpid());
+		    for (WriteOp op : groupOp) {
+			log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
+
+			// If we changed the operation from ForceCreate to
+			// Conditional operation (Create/Update) then we should retry here.
+		    }
+		}
+		return !failed;
+	}
+
+	/**
+	 * Update a switch as inactive in the database.
+	 *
+	 * @param sw the switch to update.
+	 * @param portEvents the corresponding switch ports to update.
+	 * @return true on success, otherwise false.
+	 */
+	public boolean deactivateSwitch(SwitchEvent sw,
+					Collection<PortEvent> portEvents) {
+		log.debug("Deactivating switch {}", sw);
+		KVSwitch rcSwitch = new KVSwitch(sw.getDpid());
+
+		IKVClient client = DataStoreClient.getClient();
+
+		List<WriteOp> groupOp = new ArrayList<>();
+		rcSwitch.setStatus(KVSwitch.STATUS.INACTIVE);
+
+		groupOp.add(rcSwitch.forceCreateOp(client));
+
+		for (PortEvent portEvent : portEvents) {
+			KVPort rcPort = new KVPort(sw.getDpid(), portEvent.getNumber());
+			rcPort.setStatus(KVPort.STATUS.INACTIVE);
+
+			groupOp.add(rcPort.forceCreateOp(client));
+		}
+
+		boolean failed = KVObject.multiWrite(groupOp);
+
+		return !failed;
+	}
+
+	/**
+	 * Add a port to the database.
+	 *
+	 * @param port the port to add.
+	 * @return true on success, otherwise false.
+	 */
+	public boolean addPort(PortEvent port) {
+		log.debug("Adding port {}", port);
+
+		KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
+		rcPort.setStatus(KVPort.STATUS.ACTIVE);
+		rcPort.forceCreate();
+		// TODO add description into KVPort
+		//rcPort.setDescription(port.getDescription());
+
+		return true;
+	}
+
+	/**
+	 * Update a port as inactive in the database.
+	 *
+	 * @param port the port to update.
+	 * @return true on success, otherwise false.
+	 */
+	public boolean deactivatePort(PortEvent port) {
+		log.debug("Deactivating port {}", port);
+
+		KVPort rcPort = new KVPort(port.getDpid(), port.getNumber());
+		rcPort.setStatus(STATUS.INACTIVE);
+
+		rcPort.forceCreate();
+
+		return true;
+	}
+
+	/**
+	 * Add a link to the database.
+	 *
+	 * @param link the link to add.
+	 * @return true on success, otherwise false.
+	 */
+	public boolean addLink(LinkEvent link) {
+		log.debug("Adding link {}", link);
+
+		KVLink rcLink = new KVLink(link.getSrc().getDpid(),
+					   link.getSrc().getNumber(),
+					   link.getDst().getDpid(),
+					   link.getDst().getNumber());
+
+		// XXX This method is called only by discovery,
+		// which means what we are trying to write currently is the truth
+		// so we can force write here
+		//
+		// TODO: We need to check for errors
+		rcLink.setStatus(KVLink.STATUS.ACTIVE);
+		rcLink.forceCreate();
+
+		return true;					// Success
+	}
+
+	public boolean removeLink(LinkEvent linkEvent) {
+		log.debug("Removing link {}", linkEvent);
+
+		KVLink rcLink = new KVLink(linkEvent.getSrc().getDpid(), linkEvent.getSrc().getNumber(),
+				linkEvent.getDst().getDpid(), linkEvent.getDst().getNumber());
+		rcLink.forceDelete();
+
+		return true;
+	}
+
+	/**
+	 * Add a device to the database.
+	 *
+	 * @param device the device to add.
+	 * @return true on success, otherwise false.
+	 */
+	public boolean addDevice(DeviceEvent device) {
+		log.debug("Adding device into DB. mac {}", device.getMac());
+
+		KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
+		rcDevice.setLastSeenTime(device.getLastSeenTime());
+		
+		for(SwitchPort sp : device.getAttachmentPoints()) {
+			byte[] portId = KVPort.getPortID(sp.getDpid(), sp.getNumber());		
+			rcDevice.addPortId(portId);
+		}
+		
+		for(InetAddress addr : device.getIpAddresses()) {
+			//It assume only one ip on a device now.
+			rcDevice.setIp(InetAddresses.coerceToInteger(addr));	
+		}
+
+		rcDevice.forceCreate();
+		
+		return true;
+	}
+
+	/**
+	 * Remove a device from the database.
+	 *
+	 * @param device the device to remove.
+	 * @return true on success, otherwise false.
+	 */
+	public boolean removeDevice(DeviceEvent device) {
+		log.debug("Removing device into DB. mac {}", device.getMac());
+		
+		KVDevice rcDevice = new KVDevice(device.getMac().toBytes());
+		rcDevice.forceDelete();
+		
+		return true;
+	}
+}