diff --git a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/TopologyManager.java b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/TopologyManager.java
index fc57b3b..25a322b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/TopologyManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/TopologyManager.java
@@ -54,12 +54,25 @@
     private final IControllerRegistryService registryService;
     private CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners;
 
-    public TopologyManager(IControllerRegistryService registryService, CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners) {
+    /**
+     * Constructor.
+     *
+     * @param registryService the Registry Service to use.
+     * @param networkGraphListeners the collection of Network Graph Listeners
+     * to use.
+     */
+    public TopologyManager(IControllerRegistryService registryService,
+			   CopyOnWriteArrayList<INetworkGraphListener> networkGraphListeners) {
 	datastore = new NetworkGraphDatastore(this);
 	this.registryService = registryService;
 	this.networkGraphListeners = networkGraphListeners;
     }
 
+    /**
+     * Get the Network Graph.
+     *
+     * @return the Network Graph.
+     */
     NetworkGraph getNetworkGraph() {
 	return networkGraph;
     }
@@ -213,9 +226,10 @@
     }
 
     /**
-     * Exception to be thrown when Modification to the Network Graph cannot be continued due to broken invariant.
+     * Exception to be thrown when Modification to the Network Graph cannot be
+     * continued due to broken invariant.
      *
-     * XXX Should this be checked exception or RuntimeException
+     * XXX Should this be checked exception or RuntimeException?
      */
     public static class BrokenInvariantException extends RuntimeException {
 	private static final long serialVersionUID = 1L;
@@ -233,858 +247,883 @@
      * NetworkGraphDiscoveryInterface methods
      * ******************************/
 
-	@Override
-	public void putSwitchEvent(SwitchEvent switchEvent) {
-		if (prepareForAddSwitchEvent(switchEvent)) {
-			datastore.addSwitch(switchEvent);
-			putSwitch(switchEvent);
-			// Send out notification
-			TopologyEvent topologyEvent =
-			    new TopologyEvent(switchEvent, registryService.getControllerId());
-			eventChannel.addEntry(topologyEvent.getID(),
-					      topologyEvent);
+    @Override
+    public void putSwitchEvent(SwitchEvent switchEvent) {
+	if (prepareForAddSwitchEvent(switchEvent)) {
+	    datastore.addSwitch(switchEvent);
+	    putSwitch(switchEvent);
+	    // Send out notification
+	    TopologyEvent topologyEvent =
+		new TopologyEvent(switchEvent, registryService.getControllerId());
+	    eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
+	}
+	// TODO handle invariant violation
+    }
+
+    @Override
+    public void removeSwitchEvent(SwitchEvent switchEvent) {
+	if (prepareForRemoveSwitchEvent(switchEvent)) {
+	    datastore.deactivateSwitch(switchEvent);
+	    removeSwitch(switchEvent);
+	    // Send out notification
+	    eventChannel.removeEntry(switchEvent.getID());
+	}
+	// TODO handle invariant violation
+    }
+
+    @Override
+    public void putPortEvent(PortEvent portEvent) {
+	if (prepareForAddPortEvent(portEvent)) {
+	    datastore.addPort(portEvent);
+	    putPort(portEvent);
+	    // Send out notification
+	    TopologyEvent topologyEvent =
+		new TopologyEvent(portEvent, registryService.getControllerId());
+	    eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
+	}
+	// TODO handle invariant violation
+    }
+
+    @Override
+    public void removePortEvent(PortEvent portEvent) {
+	if (prepareForRemovePortEvent(portEvent)) {
+	    datastore.deactivatePort(portEvent);
+	    removePort(portEvent);
+	    // Send out notification
+	    eventChannel.removeEntry(portEvent.getID());
+	}
+	// TODO handle invariant violation
+    }
+
+    @Override
+    public void putLinkEvent(LinkEvent linkEvent) {
+	if (prepareForAddLinkEvent(linkEvent)) {
+	    datastore.addLink(linkEvent);
+	    putLink(linkEvent);
+	    // Send out notification
+	    TopologyEvent topologyEvent =
+		new TopologyEvent(linkEvent, registryService.getControllerId());
+	    eventChannel.addEntry(topologyEvent.getID(), topologyEvent);
+	}
+	// TODO handle invariant violation
+    }
+
+    @Override
+    public void removeLinkEvent(LinkEvent linkEvent) {
+	removeLinkEvent(linkEvent, false);
+    }
+
+    private void removeLinkEvent(LinkEvent linkEvent,
+				 boolean dstCheckBeforeDBmodify) {
+	if (prepareForRemoveLinkEvent(linkEvent)) {
+	    if (dstCheckBeforeDBmodify) {
+		// write to DB only if it is owner of the dst dpid
+		if (registryService.hasControl(linkEvent.getDst().dpid)) {
+		    datastore.removeLink(linkEvent);
 		}
-		// TODO handle invariant violation
+	    } else {
+		datastore.removeLink(linkEvent);
+	    }
+	    removeLink(linkEvent);
+	    // Send out notification
+	    eventChannel.removeEntry(linkEvent.getID());
 	}
+	// TODO handle invariant violation
+    }
 
-	@Override
-	public void removeSwitchEvent(SwitchEvent switchEvent) {
-		if (prepareForRemoveSwitchEvent(switchEvent)) {
-			datastore.deactivateSwitch(switchEvent);
-			removeSwitch(switchEvent);
-			// Send out notification
-			eventChannel.removeEntry(switchEvent.getID());
-		}
-		// TODO handle invariant violation
+    @Override
+    public void putDeviceEvent(DeviceEvent deviceEvent) {
+	if (prepareForAddDeviceEvent(deviceEvent)) {
+//	    datastore.addDevice(deviceEvent);
+//	    putDevice(deviceEvent);
+	    // Send out notification
+	    TopologyEvent topologyEvent =
+		new TopologyEvent(deviceEvent,
+				  registryService.getControllerId());
+	    eventChannel.addEntry(topologyEvent.getID(),
+				  topologyEvent);
 	}
+	// TODO handle invariant violation
+	// XXX if prepareFor~ method returned false, event should be dropped
+    }
 
-	@Override
-	public void putPortEvent(PortEvent portEvent) {
-		if (prepareForAddPortEvent(portEvent)) {
-			datastore.addPort(portEvent);
-			putPort(portEvent);
-			// Send out notification
-			TopologyEvent topologyEvent =
-			    new TopologyEvent(portEvent, registryService.getControllerId());
-			eventChannel.addEntry(topologyEvent.getID(),
-					      topologyEvent);
-		}
-		// TODO handle invariant violation
+    @Override
+    public void removeDeviceEvent(DeviceEvent deviceEvent) {
+	if (prepareForRemoveDeviceEvent(deviceEvent)) {
+//	    datastore.removeDevice(deviceEvent);
+//	    removeDevice(deviceEvent);
+	    // Send out notification
+	    eventChannel.removeEntry(deviceEvent.getID());
 	}
+	// TODO handle invariant violation
+	// XXX if prepareFor~ method returned false, event should be dropped
+    }
 
-	@Override
-	public void removePortEvent(PortEvent portEvent) {
-		if (prepareForRemovePortEvent(portEvent)) {
-			datastore.deactivatePort(portEvent);
-			removePort(portEvent);
-			// Send out notification
-			eventChannel.removeEntry(portEvent.getID());
-		}
-		// TODO handle invariant violation
-	}
+    /* *****************
+     * Internal methods to maintain invariants of the network graph
+     * *****************/
 
-	@Override
-	public void putLinkEvent(LinkEvent linkEvent) {
-		if (prepareForAddLinkEvent(linkEvent)) {
-			datastore.addLink(linkEvent);
-			putLink(linkEvent);
-			// Send out notification
-			TopologyEvent topologyEvent =
-			    new TopologyEvent(linkEvent, registryService.getControllerId());
-			eventChannel.addEntry(topologyEvent.getID(),
-					      topologyEvent);
-		}
-		// TODO handle invariant violation
-	}
+    /**
+     *
+     * @param swEvent
+     * @return true if ready to accept event.
+     */
+    private boolean prepareForAddSwitchEvent(SwitchEvent swEvent) {
+	// No show stopping precondition
+	// Prep: remove(deactivate) Ports on Switch, which is not on event
+	removePortsNotOnEvent(swEvent);
+	return true;
+    }
 
-	@Override
-	public void removeLinkEvent(LinkEvent linkEvent) {
-	    removeLinkEvent(linkEvent, false);
+    private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvent) {
+	// No show stopping precondition
+	// Prep: remove(deactivate) Ports on Switch, which is not on event
+	// XXX may be remove switch should imply wipe all ports
+	removePortsNotOnEvent(swEvent);
+	return true;
+    }
 
-	}
-
-	private void removeLinkEvent(LinkEvent linkEvent, boolean dstCheckBeforeDBmodify) {
-		if (prepareForRemoveLinkEvent(linkEvent)) {
-			if (dstCheckBeforeDBmodify) {
-			    // write to DB only if it is owner of the dst dpid
-			    if (registryService.hasControl(linkEvent.getDst().dpid)) {
-				datastore.removeLink(linkEvent);
-			    }
-			} else {
-			    datastore.removeLink(linkEvent);
-			}
-			removeLink(linkEvent);
-			// Send out notification
-			eventChannel.removeEntry(linkEvent.getID());
-		}
-		// TODO handle invariant violation
-	}
-
-	@Override
-	public void putDeviceEvent(DeviceEvent deviceEvent) {
-		if (prepareForAddDeviceEvent(deviceEvent)) {
-//			datastore.addDevice(deviceEvent);
-//			putDevice(deviceEvent);
-			// Send out notification
-			TopologyEvent topologyEvent =
-			    new TopologyEvent(deviceEvent, registryService.getControllerId());
-			eventChannel.addEntry(topologyEvent.getID(),
-					      topologyEvent);
-		}
-		// TODO handle invariant violation
-		// XXX if prepareFor~ method returned false, event should be dropped
-	}
-
-	@Override
-	public void removeDeviceEvent(DeviceEvent deviceEvent) {
-		if (prepareForRemoveDeviceEvent(deviceEvent)) {
-//			datastore.removeDevice(deviceEvent);
-//			removeDevice(deviceEvent);
-			// Send out notification
-			eventChannel.removeEntry(deviceEvent.getID());
-		}
-		// TODO handle invariant violation
-		// XXX if prepareFor~ method returned false, event should be dropped
-	}
-
-	/* *****************
-	 * Internal methods to maintain invariants of the network graph
-	 * *****************/
-
-	/**
-	 *
-	 * @param swEvt
-	 * @return true if ready to accept event.
-	 */
-	private boolean prepareForAddSwitchEvent(SwitchEvent swEvt) {
-	    // No show stopping precondition
-	    // Prep: remove(deactivate) Ports on Switch, which is not on event
-	    removePortsNotOnEvent(swEvt);
-	    return true;
-	}
-
-	private boolean prepareForRemoveSwitchEvent(SwitchEvent swEvt) {
-	    // No show stopping precondition
-	    // Prep: remove(deactivate) Ports on Switch, which is not on event
-	    // XXX may be remove switch should imply wipe all ports
-	    removePortsNotOnEvent(swEvt);
-	    return true;
-	}
-
-	private void removePortsNotOnEvent(SwitchEvent swEvt) {
-	    Switch sw = networkGraph.getSwitch(swEvt.getDpid());
-	    if ( sw != null ) {
-		Set<Long> port_noOnEvent = new HashSet<>();
-		for( PortEvent portEvent : swEvt.getPorts()) {
-		    port_noOnEvent.add(portEvent.getNumber());
-		}
-		// Existing ports not on event should be removed.
-		// TODO Should batch eventually for performance?
-		List<Port> portsToRemove = new ArrayList<Port>();
-		for( Port p : sw.getPorts() ) {
-		    if ( !port_noOnEvent.contains(p.getNumber()) ) {
-			//PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
-			// calling Discovery removePort() API to wipe from DB, etc.
-			//removePortEvent(rmEvent);
+    private void removePortsNotOnEvent(SwitchEvent swEvent) {
+	Switch sw = networkGraph.getSwitch(swEvent.getDpid());
+	if (sw != null) {
+	    Set<Long> port_noOnEvent = new HashSet<>();
+	    for (PortEvent portEvent : swEvent.getPorts()) {
+		port_noOnEvent.add(portEvent.getNumber());
+	    }
+	    // Existing ports not on event should be removed.
+	    // TODO Should batch eventually for performance?
+	    List<Port> portsToRemove = new ArrayList<Port>();
+	    for (Port p : sw.getPorts()) {
+		if (!port_noOnEvent.contains(p.getNumber())) {
+		    //PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
+		    // calling Discovery removePort() API to wipe from DB, etc.
+		    //removePortEvent(rmEvent);
 
 		    // We can't remove ports here because this will trigger a remove
 		    // from the switch's port list, which we are currently iterating
 		    // over.
 		    portsToRemove.add(p);
-		    }
-		}
-		for (Port p : portsToRemove) {
-			PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(), p.getNumber());
-			// calling Discovery removePort() API to wipe from DB, etc.
-			removePortEvent(rmEvent);
 		}
 	    }
+	    for (Port p : portsToRemove) {
+		PortEvent rmEvent = new PortEvent(p.getSwitch().getDpid(),
+						  p.getNumber());
+		// calling Discovery removePort() API to wipe from DB, etc.
+		removePortEvent(rmEvent);
+	    }
+	}
+    }
+
+    private boolean prepareForAddPortEvent(PortEvent portEvent) {
+	// Parent Switch must exist
+	if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
+	    log.warn("Dropping add port event because switch doesn't exist: {}",
+		     portEvent);
+	    return false;
+	}
+	// Prep: None
+	return true;
+    }
+
+    private boolean prepareForRemovePortEvent(PortEvent portEvent) {
+	Port port = networkGraph.getPort(portEvent.getDpid(),
+					 portEvent.getNumber());
+	if (port == null) {
+	    log.debug("Port already removed? {}", portEvent);
+	    // let it pass
+	    return true;
 	}
 
-	private boolean prepareForAddPortEvent(PortEvent portEvt) {
-		// Parent Switch must exist
-		if ( networkGraph.getSwitch(portEvt.getDpid()) == null) {
-			log.warn("Dropping add port event because switch doesn't exist: {}",
-					portEvt);
-		    return false;
-		}
-		// Prep: None
-		return true;
+	// Prep: Remove Link and Device Attachment
+	ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
+	for (Device device : port.getDevices()) {
+	    log.debug("Removing Device {} on Port {}", device, portEvent);
+	    DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
+	    devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
+						     port.getNumber()));
+	    deviceEvents.add(devEvent);
+	}
+	for (DeviceEvent devEvent : deviceEvents) {
+	    // calling Discovery API to wipe from DB, etc.
+	    removeDeviceEvent(devEvent);
 	}
 
-	private boolean prepareForRemovePortEvent(PortEvent portEvt) {
-		Port port = networkGraph.getPort(portEvt.getDpid(),
-						 portEvt.getNumber());
-		if ( port == null ) {
-		    log.debug("Port already removed? {}", portEvt);
-		    // let it pass
-		    return true;
-		}
+	Set<Link> links = new HashSet<>();
+	links.add(port.getOutgoingLink());
+	links.add(port.getIncomingLink());
+	for (Link link : links) {
+	    if (link == null) {
+		continue;
+	    }
+	    log.debug("Removing Link {} on Port {}", link, portEvent);
+	    LinkEvent linkEvent =
+		new LinkEvent(link.getSourceSwitchDpid(),
+			      link.getSourcePortNumber(),
+			      link.getDestinationSwitchDpid(),
+			      link.getDestinationPortNumber());
+	    // calling Discovery API to wipe from DB, etc.
 
-		// Prep: Remove Link and Device Attachment
-		ArrayList<DeviceEvent> deviceEvts = new ArrayList<>();
-		for (Device device : port.getDevices()) {
-		    log.debug("Removing Device {} on Port {}", device, portEvt);
-		    DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
-		    devEvt.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(), port.getNumber()));
-		    deviceEvts.add(devEvt);
-		}
-		for (DeviceEvent devEvt : deviceEvts) {
-		    // calling Discovery API to wipe from DB, etc.
-		    removeDeviceEvent(devEvt);
-		}
-
-		Set<Link> links = new HashSet<>();
-		links.add(port.getOutgoingLink());
-		links.add(port.getIncomingLink());
-		for ( Link link : links) {
-		    if (link == null ) {
-			continue;
-		    }
-		    log.debug("Removing Link {} on Port {}", link, portEvt);
-		    LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(), link.getSourcePortNumber(), link.getDestinationSwitchDpid(), link.getDestinationPortNumber());
-		    // calling Discovery API to wipe from DB, etc.
-
-		    // Call internal remove Link, which will check
-		    // ownership of DST dpid and modify DB only if it is the owner
-		    removeLinkEvent(linkEvent, true);
-		}
-		return true;
+	    // Call internal remove Link, which will check
+	    // ownership of DST dpid and modify DB only if it is the owner
+	    removeLinkEvent(linkEvent, true);
 	}
+	return true;
+    }
 
-	private boolean prepareForAddLinkEvent(LinkEvent linkEvt) {
-	    // Src/Dst Port must exist
-	    Port srcPort = networkGraph.getPort(linkEvt.getSrc().dpid,
-						linkEvt.getSrc().number);
-	    Port dstPort = networkGraph.getPort(linkEvt.getDst().dpid,
-						linkEvt.getDst().number);
-	    if ( srcPort == null || dstPort == null ) {
+    private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
+	// Src/Dst Port must exist
+	Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
+					    linkEvent.getSrc().number);
+	Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
+					    linkEvent.getDst().number);
+	if (srcPort == null || dstPort == null) {
 	    log.warn("Dropping add link event because port doesn't exist: {}",
-	    		linkEvt);
-		return false;
-	    }
-
-	    // Prep: remove Device attachment on both Ports
-	    ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
-	    for (Device device : srcPort.getDevices()) {
-		DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
-		devEvt.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
-		deviceEvents.add(devEvt);
-	    }
-	    for (Device device : dstPort.getDevices()) {
-		DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
-		devEvt.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(), dstPort.getNumber()));
-		deviceEvents.add(devEvt);
-	    }
-	    for (DeviceEvent devEvt : deviceEvents) {
-		// calling Discovery API to wipe from DB, etc.
-		removeDeviceEvent(devEvt);
-	    }
-
-	    return true;
+		     linkEvent);
+	    return false;
 	}
 
-	private boolean prepareForRemoveLinkEvent(LinkEvent linkEvt) {
-	    // Src/Dst Port must exist
-	    Port srcPort = networkGraph.getPort(linkEvt.getSrc().dpid,
-						linkEvt.getSrc().number);
-	    Port dstPort = networkGraph.getPort(linkEvt.getDst().dpid,
-						linkEvt.getDst().number);
-	    if ( srcPort == null || dstPort == null ) {
-		log.warn("Dropping remove link event because port doesn't exist {}", linkEvt);
-		return false;
-	    }
-
-	    Link link = srcPort.getOutgoingLink();
-
-	    // Link is already gone, or different Link exist in memory
-	    // XXX Check if we should reject or just accept these cases.
-	    // it should be harmless to remove the Link on event from DB anyways
-	    if (link == null ||
-		    !link.getDestinationPortNumber().equals(linkEvt.getDst().number)
-		    || !link.getDestinationSwitchDpid().equals(linkEvt.getDst().dpid)) {
-		log.warn("Dropping remove link event because link doesn't exist: {}", linkEvt);
-		return false;
-	    }
-	    // Prep: None
-	    return true;
+	// Prep: remove Device attachment on both Ports
+	ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
+	for (Device device : srcPort.getDevices()) {
+	    DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
+	    devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
+	    deviceEvents.add(devEvent);
+	}
+	for (Device device : dstPort.getDevices()) {
+	    DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
+	    devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
+						     dstPort.getNumber()));
+	    deviceEvents.add(devEvent);
+	}
+	for (DeviceEvent devEvent : deviceEvents) {
+	    // calling Discovery API to wipe from DB, etc.
+	    removeDeviceEvent(devEvent);
 	}
 
-	/**
-	 *
-	 * @param deviceEvt Event will be modified to remove inapplicable attachemntPoints/ipAddress
-	 * @return false if this event should be dropped.
-	 */
-	private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvt) {
-	    boolean preconditionBroken = false;
-	    ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
-	    for ( PortEvent.SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
-		// Attached Ports must exist
-		Port port = networkGraph.getPort(swp.dpid, swp.number);
-		if ( port == null ) {
-		    preconditionBroken = true;
-		    failedSwitchPort.add(swp);
-		    continue;
-		}
-		// Attached Ports must not have Link
-		if ( port.getOutgoingLink() != null || port.getIncomingLink() != null ) {
-		    preconditionBroken = true;
-		    failedSwitchPort.add(swp);
-		    continue;
-		}
-	    }
+	return true;
+    }
 
-	    // Rewriting event to exclude failed attachmentPoint
-	    // XXX Assumption behind this is that inapplicable device event should
-	    // be dropped, not deferred. If we decide to defer Device event,
-	    // rewriting can become a problem
-	    List<SwitchPort>  attachmentPoints = deviceEvt.getAttachmentPoints();
-	    attachmentPoints.removeAll(failedSwitchPort);
-	    deviceEvt.setAttachmentPoints(attachmentPoints);
+    private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
+	// Src/Dst Port must exist
+	Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
+					    linkEvent.getSrc().number);
+	Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
+					    linkEvent.getDst().number);
+	if (srcPort == null || dstPort == null) {
+	    log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
+	    return false;
+	}
 
-	    if ( deviceEvt.getAttachmentPoints().isEmpty() && deviceEvt.getIpAddresses().isEmpty() ) {
-		// return false to represent: Nothing left to do for this event. Caller should drop event
-		return false;
+	Link link = srcPort.getOutgoingLink();
+
+	// Link is already gone, or different Link exist in memory
+	// XXX Check if we should reject or just accept these cases.
+	// it should be harmless to remove the Link on event from DB anyways
+	if (link == null ||
+	    !link.getDestinationPortNumber().equals(linkEvent.getDst().number)
+	    || !link.getDestinationSwitchDpid().equals(linkEvent.getDst().dpid)) {
+	    log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
+	    return false;
+	}
+	// Prep: None
+	return true;
+    }
+
+    /**
+     *
+     * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
+     * @return false if this event should be dropped.
+     */
+    private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
+	boolean preconditionBroken = false;
+	ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
+	for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
+	    // Attached Ports must exist
+	    Port port = networkGraph.getPort(swp.dpid, swp.number);
+	    if (port == null) {
+		preconditionBroken = true;
+		failedSwitchPort.add(swp);
+		continue;
 	    }
+	    // Attached Ports must not have Link
+	    if (port.getOutgoingLink() != null ||
+		port.getIncomingLink() != null) {
+		preconditionBroken = true;
+		failedSwitchPort.add(swp);
+		continue;
+	    }
+	}
+
+	// Rewriting event to exclude failed attachmentPoint
+	// XXX Assumption behind this is that inapplicable device event should
+	// be dropped, not deferred. If we decide to defer Device event,
+	// rewriting can become a problem
+	List<SwitchPort>  attachmentPoints = deviceEvent.getAttachmentPoints();
+	attachmentPoints.removeAll(failedSwitchPort);
+	deviceEvent.setAttachmentPoints(attachmentPoints);
+
+	if (deviceEvent.getAttachmentPoints().isEmpty() &&
+	    deviceEvent.getIpAddresses().isEmpty()) {
+	    // return false to represent: Nothing left to do for this event.
+	    // Caller should drop event
+	    return false;
+	}
 
 	// Should we return false to tell caller that the event was trimmed?
 	// if ( preconditionBroken ) {
 	//     return false;
 	// }
 
-	    return true;
+	return true;
+    }
+
+    private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
+	// No show stopping precondition?
+	// Prep: none
+	return true;
+    }
+
+    /* ******************************
+     * NetworkGraphReplicationInterface methods
+     * ******************************/
+
+    @Override
+    public void putSwitchReplicationEvent(SwitchEvent switchEvent) {
+	if (prepareForAddSwitchEvent(switchEvent)) {
+	    putSwitch(switchEvent);
+	}
+	// TODO handle invariant violation
+	// trigger instance local topology event handler
+	dispatchPutSwitchEvent(switchEvent);
+    }
+
+    @Override
+    public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
+	if (prepareForRemoveSwitchEvent(switchEvent)) {
+	    removeSwitch(switchEvent);
+	}
+	// TODO handle invariant violation
+	// trigger instance local topology event handler
+	dispatchRemoveSwitchEvent(switchEvent);
+    }
+
+    @Override
+    public void putPortReplicationEvent(PortEvent portEvent) {
+	if (prepareForAddPortEvent(portEvent)) {
+	    putPort(portEvent);
+	}
+	// TODO handle invariant violation
+	// trigger instance local topology event handler
+	dispatchPutPortEvent(portEvent);
+    }
+
+    @Override
+    public void removePortReplicationEvent(PortEvent portEvent) {
+	if (prepareForRemovePortEvent(portEvent)) {
+	    removePort(portEvent);
+	}
+	// TODO handle invariant violation
+	// trigger instance local topology event handler
+	dispatchRemovePortEvent(portEvent);
+    }
+
+    @Override
+    public void putLinkReplicationEvent(LinkEvent linkEvent) {
+	if (prepareForAddLinkEvent(linkEvent)) {
+	    putLink(linkEvent);
+	}
+	// TODO handle invariant violation
+	// trigger instance local topology event handler
+	dispatchPutLinkEvent(linkEvent);
+    }
+
+    @Override
+    public void removeLinkReplicationEvent(LinkEvent linkEvent) {
+	if (prepareForRemoveLinkEvent(linkEvent)) {
+	    removeLink(linkEvent);
+	}
+	// TODO handle invariant violation
+	// trigger instance local topology event handler
+	dispatchRemoveLinkEvent(linkEvent);
+    }
+
+    @Override
+    public void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
+	if (prepareForAddDeviceEvent(deviceEvent)) {
+	    putDevice(deviceEvent);
+	}
+	// TODO handle invariant violation
+	// trigger instance local topology event handler
+	dispatchPutDeviceEvent(deviceEvent);
+    }
+
+    @Override
+    public void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
+	if (prepareForRemoveDeviceEvent(deviceEvent)) {
+	    removeDevice(deviceEvent);
+	}
+	// TODO handle invariant violation
+	// trigger instance local topology event handler
+	dispatchRemoveDeviceEvent(deviceEvent);
+    }
+
+    /* ************************************************
+     * Internal In-memory object mutation methods.
+     * ************************************************/
+
+    void putSwitch(SwitchEvent swEvent) {
+	if (swEvent == null) {
+	    throw new IllegalArgumentException("Switch cannot be null");
 	}
 
-	private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvt) {
-		// No show stopping precondition?
-		// Prep: none
-		return true;
+	Switch sw = networkGraph.getSwitch(swEvent.getDpid());
+
+	if (sw == null) {
+	    sw = new SwitchImpl(networkGraph, swEvent.getDpid());
+	    networkGraph.putSwitch(sw);
 	}
 
-	/* ******************************
-	 * NetworkGraphReplicationInterface methods
-	 * ******************************/
+	// Update when more attributes are added to Event object
+	// no attribute to update for now
 
-	@Override
-	public void putSwitchReplicationEvent(SwitchEvent switchEvent) {
-	    if (prepareForAddSwitchEvent(switchEvent)) {
-		putSwitch(switchEvent);
-	    }
-	    // TODO handle invariant violation
-	    // trigger instance local topology event handler
-	    dispatchPutSwitchEvent(switchEvent);
+	// TODO handle child Port event properly for performance
+	for (PortEvent portEvent : swEvent.getPorts() ) {
+	    putPort(portEvent);
+	}
+    }
+
+    void removeSwitch(SwitchEvent swEvent) {
+	if (swEvent == null) {
+	    throw new IllegalArgumentException("Switch cannot be null");
 	}
 
-	@Override
-	public void removeSwitchReplicationEvent(SwitchEvent switchEvent) {
-	    if (prepareForRemoveSwitchEvent(switchEvent)) {
-		removeSwitch(switchEvent);
-	    }
-	    // TODO handle invariant violation
-	    // trigger instance local topology event handler
-	    dispatchRemoveSwitchEvent(switchEvent);
+	// TODO handle child Port event properly for performance
+	for (PortEvent portEvent : swEvent.getPorts() ) {
+	    removePort(portEvent);
 	}
 
-	@Override
-	public void putPortReplicationEvent(PortEvent portEvent) {
-	    if (prepareForAddPortEvent(portEvent)) {
-		putPort(portEvent);
-	    }
-	    // TODO handle invariant violation
-	    // trigger instance local topology event handler
-	    dispatchPutPortEvent(portEvent);
+	Switch sw = networkGraph.getSwitch(swEvent.getDpid());
+	if (sw == null) {
+	    log.warn("Switch {} already removed, ignoring", swEvent);
+	    return;
 	}
 
-	@Override
-	public void removePortReplicationEvent(PortEvent portEvent) {
-	    if (prepareForRemovePortEvent(portEvent)) {
-		removePort(portEvent);
-	    }
-	    // TODO handle invariant violation
-	    // trigger instance local topology event handler
-	    dispatchRemovePortEvent(portEvent);
+	// remove all ports if there still exist
+	ArrayList<PortEvent> portsToRemove = new ArrayList<>();
+	for (Port port : sw.getPorts()) {
+	    log.warn("Port {} on Switch {} should be removed prior to removing Switch. Removing Port now",
+		     port, swEvent);
+	    PortEvent portEvent = new PortEvent(port.getDpid(),
+						port.getNumber());
+	    portsToRemove.add(portEvent);
+	}
+	for (PortEvent portEvent : portsToRemove) {
+	    // XXX calling removePortEvent() may trigger duplicate event,
+	    // once at prepare phase, second time here
+	    // If event can be squashed, ignored etc. at receiver side it
+	    // shouldn't be a problem, but if not need to re-visit this issue.
+
+	    // Note: removePortEvent() implies removal of attached Device, etc.
+	    // if we decide not to call removePortEvent(), Device needs to be
+	    // handled properly
+	    removePortEvent(portEvent);
 	}
 
-	@Override
-	public void putLinkReplicationEvent(LinkEvent linkEvent) {
-	    if (prepareForAddLinkEvent(linkEvent)) {
-		putLink(linkEvent);
-	    }
-	    // TODO handle invariant violation
-	    // trigger instance local topology event handler
-	    dispatchPutLinkEvent(linkEvent);
+	networkGraph.removeSwitch(swEvent.getDpid());
+    }
+
+    void putPort(PortEvent portEvent) {
+	if (portEvent == null) {
+	    throw new IllegalArgumentException("Port cannot be null");
 	}
-
-	@Override
-	public void removeLinkReplicationEvent(LinkEvent linkEvent) {
-	    if (prepareForRemoveLinkEvent(linkEvent)) {
-		removeLink(linkEvent);
-	    }
-	    // TODO handle invariant violation
-	    // trigger instance local topology event handler
-	    dispatchRemoveLinkEvent(linkEvent);
-	}
-
-	@Override
-	public void putDeviceReplicationEvent(DeviceEvent deviceEvent) {
-	    if (prepareForAddDeviceEvent(deviceEvent)) {
-		putDevice(deviceEvent);
-	    }
-	    // TODO handle invariant violation
-	    // trigger instance local topology event handler
-	    dispatchPutDeviceEvent(deviceEvent);
-	}
-
-	@Override
-	public void removeDeviceReplicationEvent(DeviceEvent deviceEvent) {
-	    if (prepareForRemoveDeviceEvent(deviceEvent)) {
-		removeDevice(deviceEvent);
-	    }
-	    // TODO handle invariant violation
-	    // trigger instance local topology event handler
-	    dispatchRemoveDeviceEvent(deviceEvent);
-	}
-
-	/* ************************************************
-	 * Internal In-memory object mutation methods.
-	 * ************************************************/
-
-	void putSwitch(SwitchEvent swEvt) {
-	    if (swEvt == null) {
-		throw new IllegalArgumentException("Switch cannot be null");
-	    }
-
-	    Switch sw = networkGraph.getSwitch(swEvt.getDpid());
-
-	    if (sw == null) {
-		sw = new SwitchImpl(networkGraph, swEvt.getDpid());
-		networkGraph.putSwitch(sw);
-	    }
-
-	    // Update when more attributes are added to Event object
-	    // no attribute to update for now
-
-	    // TODO handle child Port event properly for performance
-	    for (PortEvent portEvt : swEvt.getPorts() ) {
-		putPort(portEvt);
-	    }
-
-	}
-
-	void removeSwitch(SwitchEvent swEvt) {
-	    if (swEvt == null) {
-		throw new IllegalArgumentException("Switch cannot be null");
-	    }
-
-	    // TODO handle child Port event properly for performance
-	    for (PortEvent portEvt : swEvt.getPorts() ) {
-		removePort(portEvt);
-	    }
-
-	    Switch sw = networkGraph.getSwitch(swEvt.getDpid());
-
-	    if (sw == null) {
-		log.warn("Switch {} already removed, ignoring", swEvt);
-		return;
-	    }
-
-	    // remove all ports if there still exist
-	    ArrayList<PortEvent> portsToRemove = new ArrayList<>();
-	    for (Port port : sw.getPorts()) {
-		log.warn(
-			"Port {} on Switch {} should be removed prior to removing Switch. Removing Port now",
-			port, swEvt);
-		PortEvent portEvt = new PortEvent(port.getDpid(), port.getNumber());
-		portsToRemove.add(portEvt);
-	    }
-	    for (PortEvent portEvt : portsToRemove) {
-		// XXX calling removePortEvent() may trigger duplicate event, once at prepare phase, second time here
-		// If event can be squashed, ignored etc. at receiver side it shouldn't be a problem, but if not
-		// need to re-visit this issue.
-
-		// Note: removePortEvent() implies removal of attached Device, etc.
-		// if we decide not to call removePortEvent(), Device needs to be handled properly
-		removePortEvent(portEvt);
-	    }
-
-	    networkGraph.removeSwitch(swEvt.getDpid());
-	}
-
-	void putPort(PortEvent portEvt) {
-	    if (portEvt == null) {
-		throw new IllegalArgumentException("Port cannot be null");
-	    }
-	    Switch sw = networkGraph.getSwitch(portEvt.getDpid());
-	    if (sw == null) {
-		throw new BrokenInvariantException(String.format(
+	Switch sw = networkGraph.getSwitch(portEvent.getDpid());
+	if (sw == null) {
+	    throw new BrokenInvariantException(String.format(
 			"Switch with dpid %s did not exist.",
-			new Dpid(portEvt.getDpid())));
-	    }
-	    Port p = sw.getPort(portEvt.getNumber());
-	    PortImpl port = null;
-	    if (p != null) {
-		port = getPortImpl(p);
-	    }
-
-	    if (port == null) {
-		port = new PortImpl(networkGraph, sw, portEvt.getNumber());
-	    }
-
-	    // TODO update attributes
-
-	    SwitchImpl s = getSwitchImpl(sw);
-	    s.addPort(port);
+			new Dpid(portEvent.getDpid())));
+	}
+	Port p = sw.getPort(portEvent.getNumber());
+	PortImpl port = null;
+	if (p != null) {
+	    port = getPortImpl(p);
 	}
 
-	void removePort(PortEvent portEvt) {
-	    if (portEvt == null) {
-		throw new IllegalArgumentException("Port cannot be null");
-	    }
-
-	    Switch sw = networkGraph.getSwitch(portEvt.getDpid());
-	    if (sw == null) {
-		log.warn("Parent Switch for Port {} already removed, ignoring", portEvt);
-		return;
-	    }
-
-	    Port p = sw.getPort(portEvt.getNumber());
-	    if (p == null) {
-		log.warn("Port {} already removed, ignoring", portEvt);
-		return;
-	    }
-
-	    // Remove Link and Device Attachment
-	    for (Device device : p.getDevices()) {
-		log.debug("Removing Device {} on Port {}", device, portEvt);
-		DeviceEvent devEvt = new DeviceEvent(device.getMacAddress());
-		devEvt.addAttachmentPoint(new SwitchPort(p.getSwitch().getDpid(), p.getNumber()));
-
-		// XXX calling removeDeviceEvent() may trigger duplicate event, once at prepare phase, second time here
-		// If event can be squashed, ignored etc. at receiver side it shouldn't be a problem, but if not
-		// need to re-visit
-
-		// calling Discovery API to wipe from DB, etc.
-		removeDeviceEvent(devEvt);
-	    }
-	    Set<Link> links = new HashSet<>();
-	    links.add(p.getOutgoingLink());
-	    links.add(p.getIncomingLink());
-	    ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
-	    for (Link link : links) {
-		if (link == null) {
-		    continue;
-		}
-		log.debug("Removing Link {} on Port {}", link, portEvt);
-		LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(), link.getSourcePortNumber(), link.getDestinationSwitchDpid(), link.getDestinationPortNumber());
-		linksToRemove.add(linkEvent);
-	    }
-	    for (LinkEvent linkEvent : linksToRemove) {
-		// XXX calling removeLinkEvent() may trigger duplicate event, once at prepare phase, second time here
-		// If event can be squashed, ignored etc. at receiver side it shouldn't be a problem, but if not
-		// need to re-visit
-
-		// calling Discovery API to wipe from DB, etc.
-		removeLinkEvent(linkEvent);
-	    }
-
-	    // remove Port from Switch
-	    SwitchImpl s = getSwitchImpl(sw);
-	    s.removePort(p);
+	if (port == null) {
+	    port = new PortImpl(networkGraph, sw, portEvent.getNumber());
 	}
 
-	void putLink(LinkEvent linkEvt) {
-	    if (linkEvt == null) {
-		throw new IllegalArgumentException("Link cannot be null");
-	    }
+	// TODO update attributes
 
-	    Port srcPort = networkGraph.getPort(linkEvt.getSrc().dpid,
-						linkEvt.getSrc().number);
-	    if (srcPort == null) {
-		throw new BrokenInvariantException(
+	SwitchImpl s = getSwitchImpl(sw);
+	s.addPort(port);
+    }
+
+    void removePort(PortEvent portEvent) {
+	if (portEvent == null) {
+	    throw new IllegalArgumentException("Port cannot be null");
+	}
+
+	Switch sw = networkGraph.getSwitch(portEvent.getDpid());
+	if (sw == null) {
+	    log.warn("Parent Switch for Port {} already removed, ignoring",
+		     portEvent);
+	    return;
+	}
+
+	Port p = sw.getPort(portEvent.getNumber());
+	if (p == null) {
+	    log.warn("Port {} already removed, ignoring", portEvent);
+	    return;
+	}
+
+	// Remove Link and Device Attachment
+	for (Device device : p.getDevices()) {
+	    log.debug("Removing Device {} on Port {}", device, portEvent);
+	    DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
+	    devEvent.addAttachmentPoint(new SwitchPort(p.getSwitch().getDpid(),
+						       p.getNumber()));
+
+	    // XXX calling removeDeviceEvent() may trigger duplicate event,
+	    // once at prepare phase, second time here
+	    // If event can be squashed, ignored etc. at receiver side it
+	    // shouldn't be a problem, but if not need to re-visit
+
+	    // calling Discovery API to wipe from DB, etc.
+	    removeDeviceEvent(devEvent);
+	}
+	Set<Link> links = new HashSet<>();
+	links.add(p.getOutgoingLink());
+	links.add(p.getIncomingLink());
+	ArrayList<LinkEvent> linksToRemove = new ArrayList<>();
+	for (Link link : links) {
+	    if (link == null) {
+		continue;
+	    }
+	    log.debug("Removing Link {} on Port {}", link, portEvent);
+	    LinkEvent linkEvent = new LinkEvent(link.getSourceSwitchDpid(),
+						link.getSourcePortNumber(),
+						link.getDestinationSwitchDpid(),
+						link.getDestinationPortNumber());
+	    linksToRemove.add(linkEvent);
+	}
+	for (LinkEvent linkEvent : linksToRemove) {
+	    // XXX calling removeLinkEvent() may trigger duplicate event,
+	    // once at prepare phase, second time here
+	    // If event can be squashed, ignored etc. at receiver side it
+	    // shouldn't be a problem, but if not need to re-visit
+
+	    // calling Discovery API to wipe from DB, etc.
+	    removeLinkEvent(linkEvent);
+	}
+
+	// remove Port from Switch
+	SwitchImpl s = getSwitchImpl(sw);
+	s.removePort(p);
+    }
+
+    void putLink(LinkEvent linkEvent) {
+	if (linkEvent == null) {
+	    throw new IllegalArgumentException("Link cannot be null");
+	}
+
+	Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
+					    linkEvent.getSrc().number);
+	if (srcPort == null) {
+	    throw new BrokenInvariantException(
 			String.format(
 				"Src Port %s of a Link did not exist.",
-				linkEvt.getSrc() ));
-	    }
+				linkEvent.getSrc() ));
+	}
 
-	    Port dstPort = networkGraph.getPort(linkEvt.getDst().dpid,
-						linkEvt.getDst().number);
-	    if (dstPort == null) {
-		throw new BrokenInvariantException(
+	Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
+					    linkEvent.getDst().number);
+	if (dstPort == null) {
+	    throw new BrokenInvariantException(
 			String.format(
 				"Dst Port %s of a Link did not exist.",
-				linkEvt.getDst() ));
-	    }
-
-	    // getting Link instance from destination port incoming Link
-	    Link l = dstPort.getIncomingLink();
-	    LinkImpl link = null;
-	    assert( l == srcPort.getOutgoingLink() );
-	    if (l != null) {
-		link = getLinkImpl(l);
-	    }
-
-	    if (link == null) {
-		link = new LinkImpl(networkGraph, srcPort, dstPort);
-	    }
-
-
-	    PortImpl dstPortMem = getPortImpl(dstPort);
-	    PortImpl srcPortMem = getPortImpl(srcPort);
-
-	    // Add Link first to avoid further Device addition
-
-	    // add Link to Port
-	    dstPortMem.setIncomingLink(link);
-	    srcPortMem.setOutgoingLink(link);
-
-	    // remove Device Pointing to Port if any
-	    for(Device d : dstPortMem.getDevices() ) {
-		log.error("Device {} on Port {} should have been removed prior to adding Link {}", d, dstPort, linkEvt);
-		DeviceImpl dev = getDeviceImpl(d);
-		dev.removeAttachmentPoint(dstPort);
-		// This implies that change is made to Device Object.
-		// sending Device attachment point removed event
-		DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
-		rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(), dstPort.getNumber()));
-		removeDeviceEvent(rmEvent);
-	    }
-	    dstPortMem.removeAllDevice();
-	    for(Device d : srcPortMem.getDevices() ) {
-		log.error("Device {} on Port {} should have been removed prior to adding Link {}", d, srcPort, linkEvt);
-		DeviceImpl dev = getDeviceImpl(d);
-		dev.removeAttachmentPoint(srcPort);
-		// This implies that change is made to Device Object.
-		// sending Device attachment point removed event
-		DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
-		rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(), dstPort.getNumber()));
-		removeDeviceEvent(rmEvent);
-	    }
-	    srcPortMem.removeAllDevice();
-
+				linkEvent.getDst()));
 	}
 
-	void removeLink(LinkEvent linkEvt) {
-	    if (linkEvt == null) {
-		throw new IllegalArgumentException("Link cannot be null");
-	    }
-
-	    Port srcPort = networkGraph.getPort(linkEvt.getSrc().dpid,
-						linkEvt.getSrc().number);
-	    if (srcPort == null) {
-		log.warn("Src Port for Link {} already removed, ignoring", linkEvt);
-		return;
-	    }
-
-	    Port dstPort = networkGraph.getPort(linkEvt.getDst().dpid,
-						linkEvt.getDst().number);
-	    if (dstPort == null) {
-		log.warn("Dst Port for Link {} already removed, ignoring", linkEvt);
-		return;
-	    }
-
-	    Link l = dstPort.getIncomingLink();
-	    if (  l == null ) {
-		log.warn("Link {} already removed on destination Port", linkEvt);
-	    }
-	    l = srcPort.getOutgoingLink();
-	    if (  l == null ) {
-		log.warn("Link {} already removed on src Port", linkEvt);
-	    }
-
-	    getPortImpl(dstPort).setIncomingLink(null);
-	    getPortImpl(srcPort).setOutgoingLink(null);
+	// getting Link instance from destination port incoming Link
+	Link l = dstPort.getIncomingLink();
+	LinkImpl link = null;
+	assert(l == srcPort.getOutgoingLink());
+	if (l != null) {
+	    link = getLinkImpl(l);
 	}
 
-	// XXX Need to rework Device related
-	void putDevice(DeviceEvent deviceEvt) {
-	    if (deviceEvt == null) {
-		throw new IllegalArgumentException("Device cannot be null");
-	    }
-
-	    Device device = networkGraph.getDeviceByMac(deviceEvt.getMac());
-	    if ( device == null ) {
-		device = new DeviceImpl(networkGraph, deviceEvt.getMac());
-	    }
-	    DeviceImpl memDevice = getDeviceImpl(device);
-
-	    // for each IP address
-	    for( InetAddress ipAddr : deviceEvt.getIpAddresses() ) {
-		memDevice.addIpAddress(ipAddr);
-	    }
-
-	    networkGraph.putDevice(device);
-
-	    // for each attachment point
-	    for (SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
-		// Attached Ports must exist
-		Port port = networkGraph.getPort(swp.dpid, swp.number);
-		if ( port == null ) {
-		    log.warn("Port for the attachment point {} did not exist. skipping mutation", swp);
-		    continue;
-		}
-		// Attached Ports must not have Link
-		if ( port.getOutgoingLink() != null || port.getIncomingLink() != null ) {
-		    log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.", port.getOutgoingLink(), port.getIncomingLink());
-		    continue;
-		}
-
-		// finally add Device <-> Port on In-memory structure
-		PortImpl memPort = getPortImpl(port);
-		memPort.addDevice(device);
-		memDevice.addAttachmentPoint(port);
-	    }
+	if (link == null) {
+	    link = new LinkImpl(networkGraph, srcPort, dstPort);
 	}
 
-	void removeDevice(DeviceEvent deviceEvt) {
-	    if (deviceEvt == null) {
-		throw new IllegalArgumentException("Device cannot be null");
-	    }
+	PortImpl dstPortMem = getPortImpl(dstPort);
+	PortImpl srcPortMem = getPortImpl(srcPort);
 
-	    Device device = networkGraph.getDeviceByMac(deviceEvt.getMac());
-	    if ( device == null ) {
-		log.warn("Device {} already removed, ignoring", deviceEvt);
-		return;
-	    }
-	    DeviceImpl memDevice = getDeviceImpl(device);
+	// Add Link first to avoid further Device addition
 
-	    // for each attachment point
-	    for (SwitchPort swp : deviceEvt.getAttachmentPoints() ) {
-		// Attached Ports must exist
-		Port port = networkGraph.getPort(swp.dpid, swp.number);
-		if ( port == null ) {
-		    log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
-		    continue;
-		}
+	// add Link to Port
+	dstPortMem.setIncomingLink(link);
+	srcPortMem.setOutgoingLink(link);
 
-		// finally remove Device <-> Port on In-memory structure
-		PortImpl memPort = getPortImpl(port);
-		memPort.removeDevice(device);
-		memDevice.removeAttachmentPoint(port);
-	    }
-	    networkGraph.removeDevice(device);
+	// remove Device Pointing to Port if any
+	for (Device d : dstPortMem.getDevices() ) {
+	    log.error("Device {} on Port {} should have been removed prior to adding Link {}",
+		      d, dstPort, linkEvent);
+	    DeviceImpl dev = getDeviceImpl(d);
+	    dev.removeAttachmentPoint(dstPort);
+	    // This implies that change is made to Device Object.
+	    // sending Device attachment point removed event
+	    DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
+	    rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
+						      dstPort.getNumber()));
+	    removeDeviceEvent(rmEvent);
+	}
+	dstPortMem.removeAllDevice();
+	for (Device d : srcPortMem.getDevices() ) {
+	    log.error("Device {} on Port {} should have been removed prior to adding Link {}",
+		      d, srcPort, linkEvent);
+	    DeviceImpl dev = getDeviceImpl(d);
+	    dev.removeAttachmentPoint(srcPort);
+	    // This implies that change is made to Device Object.
+	    // sending Device attachment point removed event
+	    DeviceEvent rmEvent = new DeviceEvent(d.getMacAddress());
+	    rmEvent.addAttachmentPoint(new SwitchPort(dstPort.getDpid(),
+						      dstPort.getNumber()));
+	    removeDeviceEvent(rmEvent);
+	}
+	srcPortMem.removeAllDevice();
+    }
+
+    void removeLink(LinkEvent linkEvent) {
+	if (linkEvent == null) {
+	    throw new IllegalArgumentException("Link cannot be null");
 	}
 
-	private void dispatchPutSwitchEvent(SwitchEvent switchEvent) {
-	    for (INetworkGraphListener listener : this.networkGraphListeners) {
-		// TODO Should copy before handing them over to listener
-		listener.putSwitchEvent(switchEvent);
-	    }
+	Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
+					    linkEvent.getSrc().number);
+	if (srcPort == null) {
+	    log.warn("Src Port for Link {} already removed, ignoring",
+		     linkEvent);
+	    return;
 	}
 
-	private void dispatchRemoveSwitchEvent(SwitchEvent switchEvent) {
-	    for (INetworkGraphListener listener : this.networkGraphListeners) {
-		// TODO Should copy before handing them over to listener
-		listener.removeSwitchEvent(switchEvent);
-	    }
+	Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
+					    linkEvent.getDst().number);
+	if (dstPort == null) {
+	    log.warn("Dst Port for Link {} already removed, ignoring",
+		     linkEvent);
+	    return;
 	}
 
-	private void dispatchPutPortEvent(PortEvent portEvent) {
-	    for (INetworkGraphListener listener : this.networkGraphListeners) {
-		// TODO Should copy before handing them over to listener
-		listener.putPortEvent(portEvent);
-	    }
+	Link l = dstPort.getIncomingLink();
+	if ( l == null) {
+	    log.warn("Link {} already removed on destination Port", linkEvent);
+	}
+	l = srcPort.getOutgoingLink();
+	if (l == null) {
+	    log.warn("Link {} already removed on src Port", linkEvent);
 	}
 
-	private void dispatchRemovePortEvent(PortEvent portEvent) {
-	    for (INetworkGraphListener listener : this.networkGraphListeners) {
-		// TODO Should copy before handing them over to listener
-		listener.removePortEvent(portEvent);
-	    }
+	getPortImpl(dstPort).setIncomingLink(null);
+	getPortImpl(srcPort).setOutgoingLink(null);
+    }
+
+    // XXX Need to rework Device related
+    void putDevice(DeviceEvent deviceEvent) {
+	if (deviceEvent == null) {
+	    throw new IllegalArgumentException("Device cannot be null");
 	}
 
-	private void dispatchPutLinkEvent(LinkEvent linkEvent) {
-	    for (INetworkGraphListener listener : this.networkGraphListeners) {
-		// TODO Should copy before handing them over to listener
-		listener.putLinkEvent(linkEvent);
-	    }
+	Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
+	if (device == null) {
+	    device = new DeviceImpl(networkGraph, deviceEvent.getMac());
+	}
+	DeviceImpl memDevice = getDeviceImpl(device);
+
+	// for each IP address
+	for (InetAddress ipAddr : deviceEvent.getIpAddresses()) {
+	    memDevice.addIpAddress(ipAddr);
 	}
 
-	private void dispatchRemoveLinkEvent(LinkEvent linkEvent) {
-	    for (INetworkGraphListener listener : this.networkGraphListeners) {
-		// TODO Should copy before handing them over to listener
-		listener.removeLinkEvent(linkEvent);
+	networkGraph.putDevice(device);
+
+	// for each attachment point
+	for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
+	    // Attached Ports must exist
+	    Port port = networkGraph.getPort(swp.dpid, swp.number);
+	    if (port == null) {
+		log.warn("Port for the attachment point {} did not exist. skipping mutation", swp);
+		continue;
 	    }
+	    // Attached Ports must not have Link
+	    if (port.getOutgoingLink() != null ||
+		port.getIncomingLink() != null) {
+		log.warn("Link (Out:{},In:{}) exist on the attachment point, skipping mutation.",
+			 port.getOutgoingLink(),
+			 port.getIncomingLink());
+		continue;
+	    }
+
+	    // finally add Device <-> Port on In-memory structure
+	    PortImpl memPort = getPortImpl(port);
+	    memPort.addDevice(device);
+	    memDevice.addAttachmentPoint(port);
+	}
+    }
+
+    void removeDevice(DeviceEvent deviceEvent) {
+	if (deviceEvent == null) {
+	    throw new IllegalArgumentException("Device cannot be null");
 	}
 
-	private void dispatchPutDeviceEvent(DeviceEvent deviceEvent) {
-	    for (INetworkGraphListener listener : this.networkGraphListeners) {
-		// TODO Should copy before handing them over to listener
-		listener.putDeviceEvent(deviceEvent);;
+	Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
+	if (device == null) {
+	    log.warn("Device {} already removed, ignoring", deviceEvent);
+	    return;
+	}
+	DeviceImpl memDevice = getDeviceImpl(device);
+
+	// for each attachment point
+	for (SwitchPort swp : deviceEvent.getAttachmentPoints()) {
+	    // Attached Ports must exist
+	    Port port = networkGraph.getPort(swp.dpid, swp.number);
+	    if (port == null) {
+		log.warn("Port for the attachment point {} did not exist. skipping attachment point mutation", swp);
+		continue;
 	    }
+
+	    // finally remove Device <-> Port on In-memory structure
+	    PortImpl memPort = getPortImpl(port);
+	    memPort.removeDevice(device);
+	    memDevice.removeAttachmentPoint(port);
+	}
+	networkGraph.removeDevice(device);
+    }
+
+    private void dispatchPutSwitchEvent(SwitchEvent switchEvent) {
+	for (INetworkGraphListener listener : this.networkGraphListeners) {
+	    // TODO Should copy before handing them over to listener
+	    listener.putSwitchEvent(switchEvent);
+	}
+    }
+
+    private void dispatchRemoveSwitchEvent(SwitchEvent switchEvent) {
+	for (INetworkGraphListener listener : this.networkGraphListeners) {
+	    // TODO Should copy before handing them over to listener
+	    listener.removeSwitchEvent(switchEvent);
+	}
+    }
+
+    private void dispatchPutPortEvent(PortEvent portEvent) {
+	for (INetworkGraphListener listener : this.networkGraphListeners) {
+	    // TODO Should copy before handing them over to listener
+	    listener.putPortEvent(portEvent);
+	}
+    }
+
+    private void dispatchRemovePortEvent(PortEvent portEvent) {
+	for (INetworkGraphListener listener : this.networkGraphListeners) {
+	    // TODO Should copy before handing them over to listener
+	    listener.removePortEvent(portEvent);
+	}
+    }
+
+    private void dispatchPutLinkEvent(LinkEvent linkEvent) {
+	for (INetworkGraphListener listener : this.networkGraphListeners) {
+	    // TODO Should copy before handing them over to listener
+	    listener.putLinkEvent(linkEvent);
+	}
+    }
+
+    private void dispatchRemoveLinkEvent(LinkEvent linkEvent) {
+	for (INetworkGraphListener listener : this.networkGraphListeners) {
+	    // TODO Should copy before handing them over to listener
+	    listener.removeLinkEvent(linkEvent);
+	}
+    }
+
+    private void dispatchPutDeviceEvent(DeviceEvent deviceEvent) {
+	for (INetworkGraphListener listener : this.networkGraphListeners) {
+	    // TODO Should copy before handing them over to listener
+	    listener.putDeviceEvent(deviceEvent);;
+	}
+    }
+
+    private void dispatchRemoveDeviceEvent(DeviceEvent deviceEvent) {
+	for (INetworkGraphListener listener : this.networkGraphListeners) {
+	    // TODO Should copy before handing them over to listener
+	    listener.removeDeviceEvent(deviceEvent);
+	}
+    }
+
+    private SwitchImpl getSwitchImpl(Switch sw) {
+	if (sw instanceof SwitchImpl) {
+	    return (SwitchImpl) sw;
+	}
+	throw new ClassCastException("SwitchImpl expected, but found: " + sw);
+    }
+
+    private PortImpl getPortImpl(Port p) {
+	if (p instanceof PortImpl) {
+	    return (PortImpl) p;
+	}
+	throw new ClassCastException("PortImpl expected, but found: " + p);
+    }
+
+    private LinkImpl getLinkImpl(Link l) {
+	if (l instanceof LinkImpl) {
+	    return (LinkImpl) l;
+	}
+	throw new ClassCastException("LinkImpl expected, but found: " + l);
+    }
+
+    private DeviceImpl getDeviceImpl(Device d) {
+	if (d instanceof DeviceImpl) {
+	    return (DeviceImpl) d;
+	}
+	throw new ClassCastException("DeviceImpl expected, but found: " + d);
+    }
+
+    @Deprecated
+    public void loadWholeTopologyFromDB() {
+	// XXX May need to clear whole topology first, depending on
+	// how we initially subscribe to replication events
+
+	for (RCSwitch sw : RCSwitch.getAllSwitches()) {
+	    if (sw.getStatus() != RCSwitch.STATUS.ACTIVE) {
+		continue;
+	    }
+	    putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
 	}
 
-	private void dispatchRemoveDeviceEvent(DeviceEvent deviceEvent) {
-	    for (INetworkGraphListener listener : this.networkGraphListeners) {
-		// TODO Should copy before handing them over to listener
-		listener.removeDeviceEvent(deviceEvent);
+	for (RCPort p : RCPort.getAllPorts()) {
+	    if (p.getStatus() != RCPort.STATUS.ACTIVE) {
+		continue;
 	    }
+	    putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber()));
 	}
 
-	private SwitchImpl getSwitchImpl(Switch sw) {
-	    if (sw instanceof SwitchImpl) {
-		return (SwitchImpl) sw;
+	// TODO Is Device going to be in DB? If so, read from DB.
+	//	for (RCDevice d : RCDevice.getAllDevices()) {
+	//	    DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
+	//	    for (byte[] portId : d.getAllPortIds() ) {
+	//		devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
+	//	    }
+	//	}
+
+	for (RCLink l : RCLink.getAllLinks()) {
+	    // check if src/dst switch/port exist before triggering event
+	    Port srcPort = networkGraph.getPort(l.getSrc().dpid,
+						l.getSrc().number);
+	    Port dstPort = networkGraph.getPort(l.getDst().dpid,
+						l.getDst().number);
+	    if (srcPort == null || dstPort == null) {
+		continue;
 	    }
-	    throw new ClassCastException("SwitchImpl expected, but found: " + sw);
+	    putLinkReplicationEvent(new LinkEvent(l.getSrc().dpid,
+						  l.getSrc().number,
+						  l.getDst().dpid,
+						  l.getDst().number));
 	}
-
-	private PortImpl getPortImpl(Port p) {
-	    if (p instanceof PortImpl) {
-		return (PortImpl) p;
-	    }
-	    throw new ClassCastException("PortImpl expected, but found: " + p);
-	}
-
-	private LinkImpl getLinkImpl(Link l) {
-	    if (l instanceof LinkImpl) {
-		return (LinkImpl) l;
-	    }
-	    throw new ClassCastException("LinkImpl expected, but found: " + l);
-	}
-
-	private DeviceImpl getDeviceImpl(Device d) {
-	    if (d instanceof DeviceImpl) {
-		return (DeviceImpl) d;
-	    }
-	    throw new ClassCastException("DeviceImpl expected, but found: " + d);
-	}
-
-	@Deprecated
-	public void loadWholeTopologyFromDB() {
-	    // XXX May need to clear whole topology first, depending on
-	    // how we initially subscribe to replication events
-
-	    for (RCSwitch sw : RCSwitch.getAllSwitches()) {
-		if ( sw.getStatus() != RCSwitch.STATUS.ACTIVE ) {
-		    continue;
-		}
-		putSwitchReplicationEvent(new SwitchEvent(sw.getDpid()));
-	    }
-
-	    for (RCPort p : RCPort.getAllPorts()) {
-		if (p.getStatus() != RCPort.STATUS.ACTIVE) {
-		    continue;
-		}
-		putPortReplicationEvent(new PortEvent(p.getDpid(), p.getNumber() ));
-	    }
-
-	    // TODO Is Device going to be in DB? If so, read from DB.
-	    //	for (RCDevice d : RCDevice.getAllDevices()) {
-	    //	    DeviceEvent devEvent = new DeviceEvent( MACAddress.valueOf(d.getMac()) );
-	    //	    for (byte[] portId : d.getAllPortIds() ) {
-	    //		devEvent.addAttachmentPoint( new SwitchPort( RCPort.getDpidFromKey(portId), RCPort.getNumberFromKey(portId) ));
-	    //	    }
-	    //	}
-
-	    for (RCLink l : RCLink.getAllLinks()) {
-		// check if src/dst switch/port exist before triggering event
-		Port srcPort = networkGraph.getPort(l.getSrc().dpid,
-						    l.getSrc().number);
-		Port dstPort = networkGraph.getPort(l.getDst().dpid,
-						    l.getDst().number);
-		if ( srcPort == null || dstPort == null ) {
-		    continue;
-		}
-		putLinkReplicationEvent( new LinkEvent(l.getSrc().dpid, l.getSrc().number, l.getDst().dpid, l.getDst().number));
-	    }
-	}
+    }
 }
