Adding event sink & dispatcher abstractions.
Increased strength of the provider & service types.
diff --git a/net/api/src/main/java/org/onlab/onos/event/AbstractEventSinkBroker.java b/net/api/src/main/java/org/onlab/onos/event/AbstractEventSinkBroker.java
new file mode 100644
index 0000000..4ca3c3c
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/event/AbstractEventSinkBroker.java
@@ -0,0 +1,46 @@
+package org.onlab.onos.event;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Base implementation of event sink broker.
+ */
+public class AbstractEventSinkBroker implements EventSinkBroker {
+
+ private final Map<Class<? extends Event>, EventSink<? extends Event>> sinks =
+ new ConcurrentHashMap<>();
+
+ @Override
+ public <E extends Event> void addSink(Class<E> eventClass, EventSink<E> sink) {
+ checkNotNull(eventClass, "Event class cannot be null");
+ checkNotNull(sink, "Event sink cannot be null");
+ checkArgument(!sinks.containsKey(eventClass),
+ "Event sink already registered for %s", eventClass.getName());
+ sinks.put(eventClass, sink);
+ }
+
+ @Override
+ public <E extends Event> void removeSink(Class<E> eventClass) {
+ checkNotNull(eventClass, "Event class cannot be null");
+ checkArgument(sinks.remove(eventClass) != null,
+ "Event sink not registered for %s", eventClass.getName());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <E extends Event> EventSink<E> getSink(Class<E> eventClass) {
+ return (EventSink<E>) sinks.get(eventClass);
+ }
+
+ @Override
+ public Set<Class<? extends Event>> getSinks() {
+ return ImmutableSet.copyOf(sinks.keySet());
+ }
+}
diff --git a/net/api/src/main/java/org/onlab/onos/event/AbstractListenerManager.java b/net/api/src/main/java/org/onlab/onos/event/AbstractListenerManager.java
new file mode 100644
index 0000000..7d4836f
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/event/AbstractListenerManager.java
@@ -0,0 +1,59 @@
+package org.onlab.onos.event;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Base implementation of a manager capable of tracking listeners and
+ * dispatching events to them.
+ */
+public class AbstractListenerManager<E extends Event, L extends EventListener<E>>
+ implements EventSink<E> {
+
+ protected Logger log = LoggerFactory.getLogger(AbstractListenerManager.class);
+
+ private final Set<L> listeners = new CopyOnWriteArraySet<>();
+
+ /**
+ * Adds the specified listener.
+ *
+ * @param listener listener to be added
+ */
+ public void addListener(L listener) {
+ checkNotNull(listener, "Listener cannot be null");
+ listeners.add(listener);
+ }
+
+ /**
+ * Removes the specified listener.
+ *
+ * @param listener listener to be removed
+ */
+ public void removeListener(L listener) {
+ checkNotNull(listener, "Listener cannot be null");
+ checkArgument(listeners.remove(listener), "Listener not registered");
+ }
+
+ @Override
+ public void process(E event) {
+ for (L listener : listeners) {
+ try {
+ listener.event(event);
+ } catch (Throwable error) {
+ reportProblem(event, error);
+ }
+ }
+ }
+
+ @Override
+ public void reportProblem(E event, Throwable error) {
+ log.warn("Exception encountered while processing event " + event, error);
+ }
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/event/EventDispatcher.java b/net/api/src/main/java/org/onlab/onos/event/EventDispatcher.java
new file mode 100644
index 0000000..a9db575
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/event/EventDispatcher.java
@@ -0,0 +1,17 @@
+package org.onlab.onos.event;
+
+/**
+ * Abstraction of a mechanism capable of accepting and dispatching events.
+ * Whether the events are accepted and the dispatched synchronously or
+ * asynchronously is unspecified.
+ */
+public interface EventDispatcher<E extends Event> {
+
+ /**
+ * Posts the specified event for dispatching.
+ *
+ * @param event event to be posted
+ */
+ void post(E event);
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/event/EventSink.java b/net/api/src/main/java/org/onlab/onos/event/EventSink.java
new file mode 100644
index 0000000..f46458c
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/event/EventSink.java
@@ -0,0 +1,23 @@
+package org.onlab.onos.event;
+
+/**
+ * Abstraction of an event sink capable of processing the specified event types.
+ */
+public interface EventSink<E extends Event> {
+
+ /**
+ * Processes the specified event.
+ *
+ * @param event event to be processed
+ */
+ void process(E event);
+
+ /**
+ * Reports a problem encountered while processing an event.
+ *
+ * @param event event being processed
+ * @param error error encountered while processing
+ */
+ void reportProblem(E event, Throwable error);
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/event/EventSinkBroker.java b/net/api/src/main/java/org/onlab/onos/event/EventSinkBroker.java
new file mode 100644
index 0000000..7be9562
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/event/EventSinkBroker.java
@@ -0,0 +1,45 @@
+package org.onlab.onos.event;
+
+import java.util.Set;
+
+/**
+ * Abstraction of an event sink broker capable of tracking sinks based on
+ * their event class.
+ */
+public interface EventSinkBroker {
+
+ /**
+ * Adds the specified sink for the given event class.
+ *
+ * @param eventClass event class
+ * @param sink event sink
+ * @param <E> type of event
+ */
+ <E extends Event> void addSink(Class<E> eventClass, EventSink<E> sink);
+
+ /**
+ * Removes the sink associated with the given event class.
+ *
+ * @param eventClass event class
+ * @param <E> type of event
+ */
+ <E extends Event> void removeSink(Class<E> eventClass);
+
+ /**
+ * Returns the event sink associated with the specified event class.
+ *
+ * @param eventClass event class
+ * @param <E> type of event
+ * @return event sink or null if none found
+ */
+ <E extends Event> EventSink<E> getSink(Class<E> eventClass);
+
+ /**
+ * Returns the set of all event classes for which sinks are presently
+ * registered.
+ *
+ * @return set of event classes
+ */
+ Set<Class<? extends Event>> getSinks();
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java b/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java
index 930015f..f55675c 100644
--- a/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java
+++ b/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java
@@ -9,7 +9,7 @@
* Service through which device providers can inject device information into
* the core.
*/
-public interface DeviceProviderService extends ProviderService {
+public interface DeviceProviderService extends ProviderService<DeviceProvider> {
// TODO: define suspend and remove actions on the mezzanine administrative API
diff --git a/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java b/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java
index 4db01e6..a483d92 100644
--- a/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java
+++ b/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java
@@ -6,7 +6,7 @@
* Service through which flowrule providers can inject flowrule information into
* the core.
*/
-public interface FlowRuleProviderService extends ProviderService {
+public interface FlowRuleProviderService extends ProviderService<FlowRuleProvider> {
/**
* Signals that a flow that was previously installed has been removed.
diff --git a/net/api/src/main/java/org/onlab/onos/net/host/HostProviderService.java b/net/api/src/main/java/org/onlab/onos/net/host/HostProviderService.java
index f91acbc..4c4859f 100644
--- a/net/api/src/main/java/org/onlab/onos/net/host/HostProviderService.java
+++ b/net/api/src/main/java/org/onlab/onos/net/host/HostProviderService.java
@@ -5,7 +5,7 @@
/**
* Means of conveying host information to the core.
*/
-public interface HostProviderService extends ProviderService {
+public interface HostProviderService extends ProviderService<HostProvider> {
/**
* Notifies the core when a host has been detected on a network along with
diff --git a/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderService.java b/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderService.java
index 8e1f18f..190ee00 100644
--- a/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderService.java
+++ b/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderService.java
@@ -5,7 +5,7 @@
/**
* Means for injecting link information into the core.
*/
-public interface LinkProviderService extends ProviderService {
+public interface LinkProviderService extends ProviderService<LinkProvider> {
/**
* Signals that an infrastructure link has been connected.
diff --git a/net/api/src/main/java/org/onlab/onos/net/provider/AbstractProviderBroker.java b/net/api/src/main/java/org/onlab/onos/net/provider/AbstractProviderBroker.java
index 05545c2..a783fec 100644
--- a/net/api/src/main/java/org/onlab/onos/net/provider/AbstractProviderBroker.java
+++ b/net/api/src/main/java/org/onlab/onos/net/provider/AbstractProviderBroker.java
@@ -12,7 +12,7 @@
* @param <P> type of the information provider
* @param <S> type of the provider service
*/
-public abstract class AbstractProviderBroker<P extends Provider, S extends ProviderService>
+public abstract class AbstractProviderBroker<P extends Provider, S extends ProviderService<P>>
implements ProviderBroker<P, S> {
private final Map<ProviderId, S> services = new HashMap<>();
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java
index b28df4e..b3d85ad 100644
--- a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java
@@ -5,7 +5,7 @@
/**
* Means for injecting topology information into the core.
*/
-public interface TopologyProviderService extends ProviderService {
+public interface TopologyProviderService extends ProviderService<TopologyProvider> {
// What can be conveyed in a topology that isn't by individual
// providers?