[ONOS-5821] (core) Develop Virtual Event Delivery Service

Chagnes
1. Virtual event is added
2. Virtual event listener manager is added
3. Virtual listener registry manager is added
4. test cases are added

Change-Id: I4157ab299c8316595eecafc8328e99433399a80c
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/AbstractVirtualListenerManager.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/AbstractVirtualListenerManager.java
new file mode 100644
index 0000000..fe6b2f9
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/AbstractVirtualListenerManager.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.incubator.net.virtual.event;
+
+import org.onosproject.event.Event;
+import org.onosproject.event.EventDeliveryService;
+import org.onosproject.event.EventListener;
+import org.onosproject.event.ListenerService;
+import org.onosproject.incubator.net.virtual.NetworkId;
+
+/**
+ * Basis for virtual event components which need to export listener mechanism.
+ */
+public abstract class AbstractVirtualListenerManager
+        <E extends Event, L extends EventListener<E>>
+    implements ListenerService<E, L> {
+
+    protected final NetworkId networkId;
+
+    protected EventDeliveryService eventDispatcher;
+
+    VirtualListenerRegistryManager listenerManager =
+            VirtualListenerRegistryManager.getInstance();
+
+    public AbstractVirtualListenerManager(NetworkId networkId) {
+        this.networkId = networkId;
+    }
+
+    @Override
+    public void addListener(L listener) {
+        listenerManager.getRegistry(networkId, getEventClass())
+                .addListener(listener);
+    }
+
+    @Override
+    public void removeListener(L listener) {
+        listenerManager.getRegistry(networkId, getEventClass())
+                .removeListener(listener);
+    }
+
+    /**
+     * Safely posts the specified event to the local event dispatcher.
+     * If there is no event dispatcher or if the event is null, this method
+     * is a noop.
+     *
+     * @param event event to be posted; may be null
+     */
+    protected void post(E event) {
+        if (event != null && eventDispatcher != null) {
+            VirtualEvent<E> vEvent =
+                    new VirtualEvent<E>(networkId, VirtualEvent.Type.POSTED, event);
+            eventDispatcher.post(vEvent);
+        }
+    }
+
+    /**
+     * Returns the class type of parameter type.
+     * More specifically, it returns the class type of event class.
+     *
+     * @return the class type of provider service of the service
+     */
+    private Class getEventClass() {
+        String className = this.getClass().getGenericSuperclass().toString();
+        String pramType = className.split("<")[1].split(",")[0];
+
+        try {
+            return Class.forName(pramType);
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualEvent.java
new file mode 100644
index 0000000..5ffdc37
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualEvent.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.net.virtual.event;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.event.Event;
+import org.onosproject.incubator.net.virtual.NetworkId;
+
+/**
+ * Base class for virtual network event that encapsulates a normal event.
+ */
+public class VirtualEvent<E extends Event>
+        extends AbstractEvent<VirtualEvent.Type, E> {
+
+    private NetworkId networkId;
+
+    /**
+     * Type of virtual network events.
+     */
+    public enum Type {
+        /**
+         * A new virtual event has been posted.
+         */
+        POSTED
+    }
+
+    protected VirtualEvent(NetworkId networkId, Type type, E subject) {
+        super(type, subject);
+        this.networkId = networkId;
+    }
+
+    protected VirtualEvent(NetworkId networkId, Type type, E subject, long time) {
+        super(type, subject, time);
+        this.networkId = networkId;
+    }
+
+    public NetworkId networkId() {
+        return networkId;
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualListenerRegistryManager.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualListenerRegistryManager.java
new file mode 100644
index 0000000..9d01a00
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/VirtualListenerRegistryManager.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.net.virtual.event;
+
+import com.google.common.collect.Maps;
+import org.onosproject.event.Event;
+import org.onosproject.event.EventSink;
+import org.onosproject.event.ListenerRegistry;
+import org.onosproject.incubator.net.virtual.NetworkId;
+
+import java.util.Map;
+
+/**
+ * Base implementation of an virtual event sink and a registry capable of tracking
+ * listeners and dispatching events to them as part of event sink processing.
+ */
+public final class VirtualListenerRegistryManager
+        implements EventSink<VirtualEvent> {
+
+    private Map<NetworkId, Map<Class<? extends Event>, ListenerRegistry>>
+            listenerMapByNetwork = Maps.newConcurrentMap();
+
+    ListenerRegistry lastStart;
+
+    // non-instantiable (except for our Singleton)
+    private VirtualListenerRegistryManager() {
+
+    }
+
+    public static VirtualListenerRegistryManager getInstance() {
+        return SingletonHelper.INSTANCE;
+    }
+
+    public ListenerRegistry getRegistry(NetworkId networkId,
+                                        Class<? extends Event> eventClass) {
+        Map<Class<? extends Event>, ListenerRegistry> listenerMapByEvent =
+                listenerMapByNetwork.get(networkId);
+
+        if (listenerMapByEvent == null) {
+            listenerMapByEvent = Maps.newConcurrentMap();
+            listenerMapByNetwork.putIfAbsent(networkId, listenerMapByEvent);
+        }
+
+        ListenerRegistry listenerRegistry = listenerMapByEvent.get(eventClass);
+
+        if (listenerRegistry == null) {
+            listenerRegistry = new ListenerRegistry();
+            listenerMapByEvent.putIfAbsent(eventClass, listenerRegistry);
+        }
+
+        return listenerRegistry;
+    }
+
+    @Override
+    public void process(VirtualEvent event) {
+        NetworkId networkId = event.networkId();
+        Event originalEvent = (Event) event.subject();
+
+        ListenerRegistry listenerRegistry =
+                listenerMapByNetwork.get(networkId).get(originalEvent.getClass());
+        listenerRegistry.process(originalEvent);
+        lastStart = listenerRegistry;
+    }
+
+    @Override
+    public void onProcessLimit() {
+        lastStart.onProcessLimit();
+    }
+
+    /**
+     * Prevents object instantiation from external.
+     */
+    private static final class SingletonHelper {
+        private static final String ILLEGAL_ACCESS_MSG =
+                "Should not instantiate this class.";
+        private static final VirtualListenerRegistryManager INSTANCE =
+                new VirtualListenerRegistryManager();
+
+        private SingletonHelper() {
+            throw new IllegalAccessError(ILLEGAL_ACCESS_MSG);
+        }
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/package-info.java
new file mode 100644
index 0000000..5032dc3
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/event/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Virtual network event delivery subsystem interfaces &amp; supporting abstractions.
+ */
+package org.onosproject.incubator.net.virtual.event;