ONOS-5682 Introduced VIRTUAL_DEVICE_* events.

Change-Id: I42354c2168775b59c6ca515ac114f0ca31e3bf98
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
index 9007c21..967504c 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
@@ -74,6 +74,7 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.BiFunction;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
@@ -109,7 +110,14 @@
     private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
 
     // Listener for virtual network events
-    private final MapEventListener<NetworkId, VirtualNetwork> virtualMapListener = new InternalMapListener();
+    private final MapEventListener<NetworkId, VirtualNetwork> virtualNetworkMapListener =
+            new InternalMapListener<>((mapEventType, virtualNetwork) -> {
+                VirtualNetworkEvent.Type eventType =
+                    mapEventType.equals(MapEvent.Type.INSERT) ? VirtualNetworkEvent.Type.NETWORK_ADDED :
+                    mapEventType.equals(MapEvent.Type.UPDATE) ? VirtualNetworkEvent.Type.NETWORK_UPDATED :
+                    mapEventType.equals(MapEvent.Type.REMOVE) ? VirtualNetworkEvent.Type.NETWORK_REMOVED : null;
+                return eventType == null ? null : new VirtualNetworkEvent(eventType, virtualNetwork.id());
+            });
 
     // Track virtual network IDs by tenant Id
     private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
@@ -119,6 +127,17 @@
     private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
     private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
 
+    // Listener for virtual device events
+    private final MapEventListener<DeviceId, VirtualDevice> virtualDeviceMapListener =
+            new InternalMapListener<>((mapEventType, virtualDevice) -> {
+                VirtualNetworkEvent.Type eventType =
+                    mapEventType.equals(MapEvent.Type.INSERT) ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_ADDED :
+                    mapEventType.equals(MapEvent.Type.UPDATE) ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_UPDATED :
+                    mapEventType.equals(MapEvent.Type.REMOVE) ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_REMOVED : null;
+                return eventType == null ? null :
+                        new VirtualNetworkEvent(eventType, virtualDevice.networkId(), virtualDevice);
+            });
+
     // Track device IDs by network Id
     private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
     private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
@@ -189,7 +208,7 @@
                 .withName("onos-networkId-virtualnetwork")
                 .withRelaxedReadConsistency()
                 .build();
-        networkIdVirtualNetworkConsistentMap.addListener(virtualMapListener);
+        networkIdVirtualNetworkConsistentMap.addListener(virtualNetworkMapListener);
         networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
 
         tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
@@ -204,6 +223,7 @@
                 .withName("onos-deviceId-virtualdevice")
                 .withRelaxedReadConsistency()
                 .build();
+        deviceIdVirtualDeviceConsistentMap.addListener(virtualDeviceMapListener);
         deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
 
         networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
@@ -264,7 +284,8 @@
     @Deactivate
     public void deactivate() {
         tenantIdSet.removeListener(setListener);
-        networkIdVirtualNetworkConsistentMap.removeListener(virtualMapListener);
+        networkIdVirtualNetworkConsistentMap.removeListener(virtualNetworkMapListener);
+        deviceIdVirtualDeviceConsistentMap.removeListener(virtualDeviceMapListener);
         log.info("Stopped");
     }
 
@@ -772,29 +793,40 @@
     /**
      * Listener class to map listener map events to the virtual network events.
      */
-    private class InternalMapListener implements MapEventListener<NetworkId, VirtualNetwork> {
+    private class InternalMapListener<K, V> implements MapEventListener<K, V> {
+
+        private final BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent;
+
+        InternalMapListener(BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent) {
+            this.createEvent = createEvent;
+        }
+
         @Override
-        public void event(MapEvent<NetworkId, VirtualNetwork> event) {
-            NetworkId networkId = checkNotNull(event.key());
-            VirtualNetworkEvent.Type type = null;
+        public void event(MapEvent<K, V> event) {
+            checkNotNull(event.key());
+            VirtualNetworkEvent vnetEvent = null;
             switch (event.type()) {
                 case INSERT:
-                    type = VirtualNetworkEvent.Type.NETWORK_ADDED;
+                    vnetEvent = createEvent.apply(event.type(), event.newValue().value());
                     break;
                 case UPDATE:
                     if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
-                        type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
+                        vnetEvent = createEvent.apply(MapEvent.Type.REMOVE, event.oldValue().value());
                     } else {
-                        type = VirtualNetworkEvent.Type.NETWORK_UPDATED;
+                        vnetEvent = createEvent.apply(event.type(), event.newValue().value());
                     }
                     break;
                 case REMOVE:
-                    type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
+                    if (event.oldValue() != null) {
+                        vnetEvent = createEvent.apply(event.type(), event.oldValue().value());
+                    }
                     break;
                 default:
                     log.error("Unsupported event type: " + event.type());
             }
-            notifyDelegate(new VirtualNetworkEvent(type, networkId));
+            if (vnetEvent != null) {
+                notifyDelegate(vnetEvent);
+            }
         }
     }
 }