Fixing topology related internal interface/class tree

- Moved TopologyInternal to more appropriate place

 --- BaseInternalTopology (was TopologyInternal)
  |
  +-- ImmutableInternalTopology (new)
  |
  +-- MutableInternalTopology (new)

- Updated TopologyImpl, etc. to implement appropriate
  *InternalTopology interface

- Added interface adaptor BaseTopologyAdaptor
   BaseInternalTopology (self-contained) -> BaseTopology (object handle)

- TopologyObjects ({Switch,Port,Link,Host}Impl) is now common
  between Mutable and Immutable variant of Topology.
   There were locks for whole Topology, but there weren't any locks
   per TopologyObject. If these instances were on MutableTopology,
   then locking should happen outside these instance method calls.

ONOS-1925

Change-Id: I0a13b4ed4b5a66b7ea8c42212c9504e6bc83d853
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyInternal.java b/src/main/java/net/onrc/onos/core/topology/BaseInternalTopology.java
similarity index 77%
rename from src/main/java/net/onrc/onos/core/topology/TopologyInternal.java
rename to src/main/java/net/onrc/onos/core/topology/BaseInternalTopology.java
index 292e260..6f9d9bf 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyInternal.java
+++ b/src/main/java/net/onrc/onos/core/topology/BaseInternalTopology.java
@@ -8,13 +8,11 @@
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
 
-// FIXME This Class hierarchy is wrong.
-// - We need BaseTopology + access to self-contained *Event objects.
-//   abstract class implementing BaseTopology?
 /**
  * Interface to reference internal self-contained elements.
  */
-public interface TopologyInternal extends MutableTopology {
+public interface BaseInternalTopology {
+
     /**
      * Gets a SwitchEvent.
      *
@@ -80,6 +78,22 @@
     public LinkEvent getLinkEvent(final LinkTuple linkId, final String type);
 
     /**
+     * Gets all the LinkEvent departing from specified port.
+     *
+     * @param srcPort source port identifier
+     * @return Collection of LinkEvent entries
+     */
+    public Collection<LinkEvent> getLinkEventsFrom(final SwitchPort srcPort);
+
+    /**
+     * Gets all the LinkEvent pointing toward specified port.
+     *
+     * @param dstPort destination port identifier
+     * @return Collection of LinkEvent entries
+     */
+    public Collection<LinkEvent> getLinkEventsTo(final SwitchPort dstPort);
+
+    /**
      * Gets a collection of LinkEvent entries.
      *
      * @param linkId Link identifier
@@ -103,6 +117,14 @@
     public HostEvent getHostEvent(MACAddress mac);
 
     /**
+     * Gets all HostEvent entries attached to specified port.
+     *
+     * @param port attachment point identifier
+     * @return Collection of HostEvent entries.
+     */
+    public Collection<HostEvent> getHostEvents(SwitchPort port);
+
+    /**
      * Gets all HostEvent entries.
      *
      * @return all HostEvent entries.
diff --git a/src/main/java/net/onrc/onos/core/topology/BaseTopologyAdaptor.java b/src/main/java/net/onrc/onos/core/topology/BaseTopologyAdaptor.java
new file mode 100644
index 0000000..3c6317e
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/BaseTopologyAdaptor.java
@@ -0,0 +1,271 @@
+package net.onrc.onos.core.topology;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.SwitchPort;
+
+/**
+ * Adaptor to access {@link BaseInternalTopology} as {@link BaseTopology}.
+ */
+public class BaseTopologyAdaptor implements BaseTopology {
+
+    private final BaseInternalTopology internal;
+
+    /**
+     * Constructor.
+     *
+     * @param internal {@link BaseInternalTopology} to use internally
+     */
+    public BaseTopologyAdaptor(BaseInternalTopology internal) {
+        this.internal = checkNotNull(internal);
+    }
+
+
+    @Override
+    public Switch getSwitch(Dpid dpid) {
+        final SwitchEvent sw = internal.getSwitchEvent(dpid);
+        if (sw != null) {
+            return new SwitchImpl(internal, dpid);
+        }
+        return null;
+    }
+
+    @Override
+    public Iterable<Switch> getSwitches() {
+        final Collection<SwitchEvent> switches = internal.getAllSwitchEvents();
+        List<Switch> list = new ArrayList<>(switches.size());
+        for (SwitchEvent elm : switches) {
+            list.add(new SwitchImpl(internal, elm.getDpid()));
+        }
+        return list;
+    }
+
+    @Override
+    public Port getPort(Dpid dpid, PortNumber portNumber) {
+        final PortEvent port = internal.getPortEvent(dpid, portNumber);
+        if (port != null) {
+            return new PortImpl(internal, port.getSwitchPort());
+        }
+        return null;
+    }
+
+    @Override
+    public Port getPort(SwitchPort port) {
+        return getPort(port.getDpid(), port.getPortNumber());
+    }
+
+    @Override
+    public Collection<Port> getPorts(Dpid dpid) {
+        final Collection<PortEvent> ports = internal.getPortEvents(dpid);
+        List<Port> list = new ArrayList<>(ports.size());
+        for (PortEvent elm : ports) {
+            list.add(new PortImpl(internal, elm.getSwitchPort()));
+        }
+        return list;
+    }
+
+    @Override
+    public Link getOutgoingLink(Dpid dpid, PortNumber number) {
+        return getOutgoingLink(new SwitchPort(dpid, number));
+    }
+
+    @Override
+    public Link getIncomingLink(Dpid dpid, PortNumber number) {
+        return getIncomingLink(new SwitchPort(dpid, number));
+    }
+
+
+    @Override
+    public Link getOutgoingLink(SwitchPort port) {
+        final Collection<LinkEvent> links = internal.getLinkEventsFrom(port);
+        LinkEvent link = getPacketLinkEventIfExists(links);
+        if (link != null) {
+            return new LinkImpl(internal, link.getLinkTuple());
+        }
+        return null;
+    }
+
+    @Override
+    public Link getIncomingLink(SwitchPort port) {
+        final Collection<LinkEvent> links = internal.getLinkEventsTo(port);
+        LinkEvent link = getPacketLinkEventIfExists(links);
+        if (link != null) {
+            return new LinkImpl(internal, link.getLinkTuple());
+        }
+        return null;
+    }
+
+    /**
+     * Gets the "packet" link if such exists,
+     * otherwise return whichever link is found first.
+     *
+     * @param links Collection of links to search from
+     * @return Link instance found or null if no link exists
+     */
+    private static LinkEvent getPacketLinkEventIfExists(Collection<LinkEvent> links) {
+        for (LinkEvent link : links) {
+            if (TopologyElement.TYPE_PACKET_LAYER.equals(link.getType())) {
+                return link;
+            }
+        }
+        if (!links.isEmpty()) {
+            return links.iterator().next();
+        }
+        return null;
+    }
+
+    @Override
+    public Link getOutgoingLink(Dpid dpid, PortNumber number, String type) {
+        return getOutgoingLink(new SwitchPort(dpid, number), type);
+    }
+
+    @Override
+    public Link getIncomingLink(Dpid dpid, PortNumber number, String type) {
+        return getIncomingLink(new SwitchPort(dpid, number), type);
+    }
+
+
+    @Override
+    public Link getOutgoingLink(SwitchPort port, String type) {
+        final Collection<LinkEvent> links = internal.getLinkEventsFrom(port);
+        for (LinkEvent link : links) {
+            if (link.getType().equals(type)) {
+                return new LinkImpl(internal, link.getLinkTuple());
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Link getIncomingLink(SwitchPort port, String type) {
+        final Collection<LinkEvent> links = internal.getLinkEventsTo(port);
+        for (LinkEvent link : links) {
+            if (link.getType().equals(type)) {
+                return new LinkImpl(internal, link.getLinkTuple());
+            }
+        }
+        return null;
+    }
+
+
+    @Override
+    public Collection<Link> getOutgoingLinks(SwitchPort port) {
+        final Collection<LinkEvent> links = internal.getLinkEventsFrom(port);
+        return toLinkImpls(internal, links);
+    }
+
+    @Override
+    public Collection<Link> getIncomingLinks(SwitchPort port) {
+        final Collection<LinkEvent> links = internal.getLinkEventsTo(port);
+        return toLinkImpls(internal, links);
+    }
+
+
+    /**
+     * Converts collection of LinkEvent to collection of LinkImpls.
+     *
+     * @param internalTopology topology {@code links} resides
+     * @param links collection of LinkEvent
+     * @return collection of {@link LinkImpl}s
+     */
+    private static Collection<Link> toLinkImpls(
+                                final BaseInternalTopology internalTopology,
+                                final Collection<LinkEvent> links) {
+
+        if (links == null) {
+            return Collections.emptyList();
+        }
+        List<Link> list = new ArrayList<>(links.size());
+        for (LinkEvent elm : links) {
+            list.add(new LinkImpl(internalTopology, elm.getLinkTuple()));
+        }
+        return list;
+    }
+
+    @Override
+    public Link getLink(Dpid srcDpid, PortNumber srcNumber,
+                        Dpid dstDpid, PortNumber dstNumber) {
+
+        final SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstNumber);
+        Collection<Link> links = getOutgoingLinks(new SwitchPort(srcDpid, srcNumber));
+        for (Link link : links) {
+            if (link == null) {
+                continue;
+            }
+            if (link.getDstPort().getSwitchPort().equals(dstSwitchPort)) {
+                return link;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Link getLink(Dpid srcDpid, PortNumber srcNumber,
+                        Dpid dstDpid, PortNumber dstNumber,
+                        String type) {
+
+        Link link = getOutgoingLink(srcDpid, srcNumber, type);
+        if (link == null) {
+            return null;
+        }
+        if (!link.getDstSwitch().getDpid().equals(dstDpid)) {
+            return null;
+        }
+        if (!link.getDstPort().getNumber().equals(dstNumber)) {
+            return null;
+        }
+        return link;
+    }
+
+    @Override
+    public Iterable<Link> getLinks() {
+        final Collection<LinkEvent> links = internal.getAllLinkEvents();
+        return toLinkImpls(internal, links);
+    }
+
+    @Override
+    public Host getHostByMac(MACAddress address) {
+
+        HostEvent host = internal.getHostEvent(address);
+        if (host != null) {
+            return new HostImpl(internal, address);
+        }
+        return null;
+    }
+
+    @Override
+    public Iterable<Host> getHosts() {
+        return toHostImpls(internal, internal.getAllHostEvents());
+    }
+
+    /**
+     * Converts collection of HostEvent to collection of HostImpl.
+     *
+     * @param internalTopology topology {@code hosts} resides
+     * @param hosts collection of HostEvent
+     * @return collection of HostImpl
+     */
+    private static List<Host> toHostImpls(BaseInternalTopology internalTopology,
+                                          Collection<HostEvent> hosts) {
+        if (hosts == null) {
+            return Collections.emptyList();
+        }
+        List<Host> list = new ArrayList<>(hosts.size());
+        for (HostEvent elm : hosts) {
+            list.add(new HostImpl(internalTopology, elm.getMac()));
+        }
+        return list;
+    }
+
+    @Override
+    public Collection<Host> getHosts(SwitchPort port) {
+        return toHostImpls(internal, internal.getHostEvents(port));
+    }
+}
diff --git a/src/main/java/net/onrc/onos/core/topology/HostImpl.java b/src/main/java/net/onrc/onos/core/topology/HostImpl.java
index 7370be0..90af82b 100644
--- a/src/main/java/net/onrc/onos/core/topology/HostImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/HostImpl.java
@@ -4,13 +4,11 @@
 import java.util.List;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.core.util.SwitchPort;
 
 /**
  * Handler to Host object stored in In-memory Topology snapshot.
- * <p/>
  */
 public class HostImpl extends TopologyObject implements Host {
 
@@ -23,7 +21,7 @@
      * @param topology Topology instance this object belongs to
      * @param mac MAC address of the host
      */
-    HostImpl(TopologyInternal topology, MACAddress mac) {
+    HostImpl(BaseInternalTopology topology, MACAddress mac) {
         super(topology);
         this.id = checkNotNull(mac);
     }
@@ -36,16 +34,12 @@
     @Override
     public Iterable<Port> getAttachmentPoints() {
         List<Port> ports = new ArrayList<>();
-        topology.acquireReadLock();
-        try {
-            for (SwitchPort swp : getHostEvent().getAttachmentPoints()) {
-                Port p = this.topology.getPort(swp);
-                if (p != null) {
-                    ports.add(p);
-                }
+        final BaseTopologyAdaptor topo = new BaseTopologyAdaptor(topology);
+        for (SwitchPort swp : getHostEvent().getAttachmentPoints()) {
+            Port port = topo.getPort(swp);
+            if (port != null) {
+                ports.add(port);
             }
-        } finally {
-            topology.releaseReadLock();
         }
         return ports;
     }
diff --git a/src/main/java/net/onrc/onos/core/topology/ImmutableInternalTopology.java b/src/main/java/net/onrc/onos/core/topology/ImmutableInternalTopology.java
new file mode 100644
index 0000000..37ae54a
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/ImmutableInternalTopology.java
@@ -0,0 +1,9 @@
+package net.onrc.onos.core.topology;
+
+/**
+ * ImmutableInternalTopology, which could be accessed without locking, etc.
+ */
+public interface ImmutableInternalTopology extends BaseInternalTopology {
+
+    // no additional interface needed.
+}
diff --git a/src/main/java/net/onrc/onos/core/topology/LinkImpl.java b/src/main/java/net/onrc/onos/core/topology/LinkImpl.java
index ee60d2d..0fcb092 100644
--- a/src/main/java/net/onrc/onos/core/topology/LinkImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/LinkImpl.java
@@ -3,12 +3,10 @@
 import java.util.Map;
 
 import net.onrc.onos.core.util.LinkTuple;
-
 import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Handler to Link object stored in In-memory Topology snapshot.
- * <p/>
  */
 public class LinkImpl extends TopologyObject implements Link {
 
@@ -21,7 +19,7 @@
      * @param topology Topology instance this object belongs to
      * @param linkTuple Link identifier
      */
-    LinkImpl(TopologyInternal topology, LinkTuple linkTuple) {
+    LinkImpl(BaseInternalTopology topology, LinkTuple linkTuple) {
         super(topology);
         this.id = checkNotNull(linkTuple);
     }
@@ -33,47 +31,27 @@
 
     @Override
     public Switch getSrcSwitch() {
-        topology.acquireReadLock();
-        try {
-            return topology.getSwitch(id.getSrc().getDpid());
-        } finally {
-            topology.releaseReadLock();
-        }
+        // TODO Cache BaseTopologyAdaptor instance?
+        return new BaseTopologyAdaptor(topology).getSwitch(id.getSrc().getDpid());
     }
 
     @Override
     public Port getSrcPort() {
-        topology.acquireReadLock();
-        try {
-            return topology.getPort(id.getSrc());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getPort(id.getSrc());
     }
 
     @Override
     public Switch getDstSwitch() {
-        topology.acquireReadLock();
-        try {
-            return topology.getSwitch(id.getDst().getDpid());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getSwitch(id.getDst().getDpid());
     }
 
     @Override
     public Port getDstPort() {
-        topology.acquireReadLock();
-        try {
-            return topology.getPort(id.getDst());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getPort(id.getDst());
     }
 
     @Override
     public long getLastSeenTime() {
-        // TODO Auto-generated method stub
         throw new UnsupportedOperationException("Not implemented yet");
     }
 
diff --git a/src/main/java/net/onrc/onos/core/topology/MutableInternalTopology.java b/src/main/java/net/onrc/onos/core/topology/MutableInternalTopology.java
new file mode 100644
index 0000000..9c6693b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/MutableInternalTopology.java
@@ -0,0 +1,25 @@
+package net.onrc.onos.core.topology;
+
+// TODO Not sure if we need this at all
+/**
+ * MutableInternalTopology, which this instance can be updated to new view.
+ * <p>
+ * Requires read-lock to access any information on this topology view.
+ * <p>
+ * Note: This is still read-only view of the topology.
+ */
+public interface MutableInternalTopology extends BaseInternalTopology {
+
+    /**
+     * Acquire a read lock on the entire topology. The topology will not
+     * change while readers have the lock. Must be released using
+     * {@link #releaseReadLock()}. This method will block until a read lock is
+     * available.
+     */
+    public void acquireReadLock();
+
+    /**
+     * Release the read lock on the topology.
+     */
+    public void releaseReadLock();
+}
diff --git a/src/main/java/net/onrc/onos/core/topology/PortImpl.java b/src/main/java/net/onrc/onos/core/topology/PortImpl.java
index 5067049..d957809 100644
--- a/src/main/java/net/onrc/onos/core/topology/PortImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/PortImpl.java
@@ -4,14 +4,12 @@
 import java.util.Map;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-
 import net.onrc.onos.core.util.Dpid;
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
 
 /**
  * Handler to Port object stored in In-memory Topology snapshot.
- * <p/>
  */
 public class PortImpl extends TopologyObject implements Port {
 
@@ -24,7 +22,7 @@
      * @param topology Topology instance this object belongs to
      * @param switchPort SwitchPort
      */
-    PortImpl(TopologyInternal topology, SwitchPort switchPort) {
+    PortImpl(BaseInternalTopology topology, SwitchPort switchPort) {
         super(topology);
         this.id = checkNotNull(switchPort);
     }
@@ -36,7 +34,7 @@
      * @param dpid DPID
      * @param number PortNumber
      */
-    PortImpl(TopologyInternal topology, Dpid dpid, PortNumber number) {
+    PortImpl(BaseInternalTopology topology, Dpid dpid, PortNumber number) {
         this(topology, new SwitchPort(dpid, number));
     }
 
@@ -73,82 +71,43 @@
 
     @Override
     public Switch getSwitch() {
-        topology.acquireReadLock();
-        try {
-            return topology.getSwitch(getDpid());
-        } finally {
-            topology.releaseReadLock();
-        }
+        // TODO Cache BaseTopologyAdaptor instance?
+        return new BaseTopologyAdaptor(topology).getSwitch(getDpid());
     }
 
     @Override
     public Link getOutgoingLink() {
-        topology.acquireReadLock();
-        try {
-            return topology.getOutgoingLink(getSwitchPort());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getOutgoingLink(getSwitchPort());
     }
 
     @Override
     public Link getOutgoingLink(String type) {
-        topology.acquireReadLock();
-        try {
-            return topology.getOutgoingLink(getSwitchPort(), type);
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getOutgoingLink(getSwitchPort(), type);
     }
 
     @Override
     public Collection<Link> getOutgoingLinks() {
-        topology.acquireReadLock();
-        try {
-            return topology.getOutgoingLinks(getSwitchPort());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getOutgoingLinks(getSwitchPort());
     }
 
     @Override
     public Link getIncomingLink() {
-        topology.acquireReadLock();
-        try {
-            return topology.getIncomingLink(getSwitchPort());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getIncomingLink(getSwitchPort());
     }
 
     @Override
     public Link getIncomingLink(String type) {
-        topology.acquireReadLock();
-        try {
-            return topology.getIncomingLink(getSwitchPort(), type);
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getIncomingLink(getSwitchPort(), type);
     }
 
     @Override
     public Collection<Link> getIncomingLinks() {
-        topology.acquireReadLock();
-        try {
-            return topology.getIncomingLinks(getSwitchPort());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getIncomingLinks(getSwitchPort());
     }
 
     @Override
     public Collection<Host> getHosts() {
-        topology.acquireReadLock();
-        try {
-            return topology.getHosts(this.getSwitchPort());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getHosts(this.getSwitchPort());
     }
 
     /**
diff --git a/src/main/java/net/onrc/onos/core/topology/SwitchImpl.java b/src/main/java/net/onrc/onos/core/topology/SwitchImpl.java
index 29df7b8..6d4e27a 100644
--- a/src/main/java/net/onrc/onos/core/topology/SwitchImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/SwitchImpl.java
@@ -15,8 +15,6 @@
 
 /**
  * Handler to Switch object stored in In-memory Topology snapshot.
- * <p/>
- *
  */
 public class SwitchImpl extends TopologyObject implements Switch {
 
@@ -29,7 +27,7 @@
      * @param topology Topology instance this object belongs to
      * @param dpid DPID
      */
-    SwitchImpl(TopologyInternal topology, Dpid dpid) {
+    SwitchImpl(BaseInternalTopology topology, Dpid dpid) {
         super(topology);
         this.id = checkNotNull(dpid);
     }
@@ -41,22 +39,12 @@
 
     @Override
     public Collection<Port> getPorts() {
-        topology.acquireReadLock();
-        try {
-            return topology.getPorts(getDpid());
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getPorts(getDpid());
     }
 
     @Override
     public Port getPort(PortNumber number) {
-        topology.acquireReadLock();
-        try {
-            return topology.getPort(getDpid(), number);
-        } finally {
-            topology.releaseReadLock();
-        }
+        return new BaseTopologyAdaptor(topology).getPort(getDpid(), number);
     }
 
     @Override
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java b/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
index b50bf48..d407064 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
@@ -33,7 +33,7 @@
 /**
  * Class to represent an instance of Topology Snapshot.
  */
-public class TopologyImpl implements MutableTopology, TopologyInternal {
+public class TopologyImpl implements MutableTopology, MutableInternalTopology {
 
     private static final Logger log = LoggerFactory.getLogger(TopologyImpl.class);
 
@@ -51,10 +51,10 @@
     private final ConcurrentMap<SwitchPort, ConcurrentMap<String, LinkEvent>> outgoingLinks;
     private final ConcurrentMap<SwitchPort, ConcurrentMap<String, LinkEvent>> incomingLinks;
 
-    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
-    private Lock readLock = readWriteLock.readLock();
+    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
+    private final Lock readLock = readWriteLock.readLock();
     // TODO use the write lock after refactor
-    private Lock writeLock = readWriteLock.writeLock();
+    private final Lock writeLock = readWriteLock.writeLock();
 
     /**
      * Create an empty Topology.
@@ -429,6 +429,24 @@
     }
 
     @Override
+    public Collection<LinkEvent> getLinkEventsFrom(SwitchPort srcPort) {
+        ConcurrentMap<String, LinkEvent> links = this.outgoingLinks.get(srcPort);
+        if (links == null) {
+            return Collections.emptyList();
+        }
+        return Collections.unmodifiableCollection(links.values());
+    }
+
+    @Override
+    public Collection<LinkEvent> getLinkEventsTo(SwitchPort dstPort) {
+        ConcurrentMap<String, LinkEvent> links = this.incomingLinks.get(dstPort);
+        if (links == null) {
+            return Collections.emptyList();
+        }
+        return Collections.unmodifiableCollection(links.values());
+    }
+
+    @Override
     public Collection<LinkEvent> getLinkEvents(final LinkTuple linkId) {
         ConcurrentMap<String, LinkEvent> links = this.outgoingLinks.get(linkId.getSrc());
         if (links == null) {
@@ -454,6 +472,11 @@
     }
 
     @Override
+    public Collection<HostEvent> getHostEvents(SwitchPort port) {
+        return Collections.unmodifiableCollection(hosts.get(port));
+    }
+
+    @Override
     public Collection<HostEvent> getAllHostEvents() {
         return Collections.unmodifiableCollection(mac2Host.values());
     }
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyObject.java b/src/main/java/net/onrc/onos/core/topology/TopologyObject.java
index b83c99b..fe31283 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyObject.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyObject.java
@@ -11,7 +11,7 @@
     /**
      * Topology snapshot this object belongs to.
      */
-    protected volatile TopologyInternal topology;
+    protected volatile BaseInternalTopology topology;
 
     // XXX Updater to be used once we implement snapshot update.
     // Should it be static or not.
@@ -27,14 +27,13 @@
      *
      * @param topology Topology instance this object belongs to
      */
-    protected TopologyObject(TopologyInternal topology) {
+    protected TopologyObject(BaseInternalTopology topology) {
         this.topology = checkNotNull(topology);
     }
 
     // TODO Add method to replace topology snapshot
     //  - Request TopologyManager for latest TopologyImpl and swap?
     //  - Make caller specify TopologyImpl instance?
-    //  -
 
 
     /**
@@ -44,6 +43,4 @@
      */
     @Override
     public abstract String getType();
-
-
 }