Bug 3135 - Fixed support for InterestListener 02/19702/3
authorTony Tkacik <ttkacik@cisco.com>
Wed, 6 May 2015 10:42:28 +0000 (12:42 +0200)
committerTony Tkacik <ttkacik@cisco.com>
Wed, 6 May 2015 12:24:50 +0000 (14:24 +0200)
InterestListener was one of undocumented beta MD-SAL APIs
which was not intented for public support, but accidentally
was public since Hydrogen and as it turned out other Opendaylight
projects started to using it.

Added support to affected components in order to still support
this API even when using new Notification Broker.

Change-Id: I060474f68a6c37ed05b262a9b46923f668ca3c8b
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/BindingNotificationPublishAdapterModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/NotificationBrokerImplModule.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/compat/HeliumNotificationProviderServiceWithInterestListeners.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDOMNotificationPublishServiceAdapter.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMNotificationRouter.java
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DOMNotificationSubscriptionListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DOMNotificationSubscriptionListenerRegistry.java [new file with mode: 0644]

index de4a905931fe17478a53f2a287f086ab27b93066..ebfd5c2219ce17e140bdca12872a33c1f153c671 100644 (file)
@@ -9,17 +9,17 @@ package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
 import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationPublishServiceAdapter;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
 import org.opendaylight.controller.sal.core.api.Broker;
 
 public class BindingNotificationPublishAdapterModule extends AbstractBindingNotificationPublishAdapterModule {
-    public BindingNotificationPublishAdapterModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver) {
+    public BindingNotificationPublishAdapterModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
     }
 
-    public BindingNotificationPublishAdapterModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver, BindingNotificationPublishAdapterModule oldModule, java.lang.AutoCloseable oldInstance) {
+    public BindingNotificationPublishAdapterModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver, final BindingNotificationPublishAdapterModule oldModule, final java.lang.AutoCloseable oldInstance) {
         super(identifier, dependencyResolver, oldModule, oldInstance);
     }
 
@@ -33,7 +33,7 @@ public class BindingNotificationPublishAdapterModule extends AbstractBindingNoti
         final BindingToNormalizedNodeCodec codec = getBindingMappingServiceDependency();
         final Broker.ProviderSession session = getDomAsyncBrokerDependency().registerProvider(new DummyDOMProvider());
         final DOMNotificationPublishService publishService = session.getService(DOMNotificationPublishService.class);
-        return new BindingDOMNotificationPublishServiceAdapter(codec.getCodecRegistry(), publishService);
+        return new BindingDOMNotificationPublishServiceAdapter(codec, publishService);
     }
 
 }
index 58d5a855658879ad242a4dc24c3d465bd82eec52..cabdd15513e3dd89144029c3b515c2d1ed80dbce 100644 (file)
@@ -7,11 +7,14 @@
  */
 package org.opendaylight.controller.config.yang.md.sal.binding.impl;
 
-import org.opendaylight.controller.md.sal.binding.compat.HydrogenNotificationBrokerImpl;
-
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
 import org.opendaylight.controller.md.sal.binding.compat.HeliumNotificationProviderServiceAdapter;
+import org.opendaylight.controller.md.sal.binding.compat.HeliumNotificationProviderServiceWithInterestListeners;
+import org.opendaylight.controller.md.sal.binding.compat.HydrogenNotificationBrokerImpl;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationPublishServiceAdapter;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
+import org.opendaylight.controller.md.sal.dom.spi.DOMNotificationSubscriptionListenerRegistry;
 import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
 
 /**
@@ -44,7 +47,7 @@ public final class NotificationBrokerImplModule extends
         final NotificationService notificationService = getNotificationAdapterDependency();
 
         if(notificationPublishService != null & notificationService != null) {
-            return new HeliumNotificationProviderServiceAdapter(notificationPublishService, notificationService);
+            return createHeliumAdapter(notificationPublishService,notificationService);
         }
 
         /*
@@ -53,7 +56,19 @@ public final class NotificationBrokerImplModule extends
          *  we will have adapter implementation which will honor Helium
          *  threading model for notifications.
          */
-
         return new HydrogenNotificationBrokerImpl(SingletonHolder.getDefaultNotificationExecutor());
     }
+
+    private static AutoCloseable createHeliumAdapter(final NotificationPublishService publishService,
+            final NotificationService listenService) {
+        if(publishService instanceof BindingDOMNotificationPublishServiceAdapter) {
+            final BindingDOMNotificationPublishServiceAdapter casted = (BindingDOMNotificationPublishServiceAdapter) publishService;
+            final DOMNotificationPublishService domService = casted.getDomPublishService();
+            if(domService instanceof DOMNotificationSubscriptionListenerRegistry) {
+                final DOMNotificationSubscriptionListenerRegistry subsRegistry = (DOMNotificationSubscriptionListenerRegistry) domService;
+                return new HeliumNotificationProviderServiceWithInterestListeners(publishService, listenService, casted.getCodecRegistry(), subsRegistry);
+            }
+        }
+        return new HeliumNotificationProviderServiceAdapter(publishService, listenService);
+    }
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/compat/HeliumNotificationProviderServiceWithInterestListeners.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/compat/HeliumNotificationProviderServiceWithInterestListeners.java
new file mode 100644 (file)
index 0000000..2ccc4c1
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.compat;
+
+import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.dom.spi.DOMNotificationSubscriptionListener;
+import org.opendaylight.controller.md.sal.dom.spi.DOMNotificationSubscriptionListenerRegistry;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HeliumNotificationProviderServiceWithInterestListeners extends HeliumNotificationProviderServiceAdapter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HeliumNotificationProviderServiceWithInterestListeners.class);
+
+    private final ListenerRegistry<NotificationInterestListener> interestListeners = ListenerRegistry.create();
+    private final ListenerRegistration<Listener> domListener;
+    private final BindingToNormalizedNodeCodec codec;
+
+    public HeliumNotificationProviderServiceWithInterestListeners(
+            final NotificationPublishService publishService, final NotificationService listenService, final BindingToNormalizedNodeCodec codec, final DOMNotificationSubscriptionListenerRegistry registry) {
+        super(publishService, listenService);
+        this.codec = codec;
+        this.domListener = registry.registerSubscriptionListener(new Listener());
+    }
+
+    @Override
+    public ListenerRegistration<NotificationInterestListener> registerInterestListener(
+            final NotificationInterestListener listener) {
+        notifyListener(listener, translate(domListener.getInstance().getAllObserved()));
+        return interestListeners.register(listener);
+    }
+
+    private Set<Class<? extends Notification>> translate(final Set<SchemaPath> added) {
+        return codec.getNotificationClasses(added);
+    }
+
+    private void notifyAllListeners(final Set<SchemaPath> added) {
+        final Iterator<ListenerRegistration<NotificationInterestListener>> listeners = interestListeners.iterator();
+        if(listeners.hasNext()) {
+            final Set<Class<? extends Notification>> baEvent = translate(added);
+            while(listeners.hasNext()) {
+                final NotificationInterestListener listenerRef = listeners.next().getInstance();
+                try {
+                    notifyListener(listenerRef,baEvent);
+                } catch (final Exception e) {
+                    LOG.warn("Unhandled exception during invoking listener {}",e, listenerRef);
+                }
+            }
+        }
+    }
+
+    private void notifyListener(final NotificationInterestListener listener, final Set<Class<? extends Notification>> baEvent) {
+        for(final Class<? extends Notification> event: baEvent) {
+            listener.onNotificationSubscribtion(event);
+        }
+    }
+
+    private final class Listener implements DOMNotificationSubscriptionListener {
+
+        private volatile Set<SchemaPath> allObserved = Collections.emptySet();
+
+        @Override
+        public void onSubscriptionChanged(final Set<SchemaPath> currentTypes) {
+            final Set<SchemaPath> added = Sets.difference(currentTypes, allObserved).immutableCopy();
+            notifyAllListeners(added);
+            allObserved = Sets.union(allObserved, added).immutableCopy();
+        }
+
+        Set<SchemaPath> getAllObserved() {
+            return allObserved;
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        super.close();
+        domListener.close();
+    }
+}
index 6c54553e6ff13b28339f0ec58d2ceb1ea1d838a5..084f423807df24f004c3aa1a6dd6c3424905d1b7 100644 (file)
@@ -17,7 +17,6 @@ import org.opendaylight.controller.md.sal.binding.impl.BindingDOMAdapterBuilder.
 import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
 import org.opendaylight.controller.md.sal.dom.api.DOMService;
-import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
 import org.opendaylight.yangtools.yang.binding.Notification;
 
 public class BindingDOMNotificationPublishServiceAdapter implements NotificationPublishService, AutoCloseable {
@@ -31,14 +30,22 @@ public class BindingDOMNotificationPublishServiceAdapter implements Notification
 
     };
 
-    private final BindingNormalizedNodeSerializer codecRegistry;
+    private final BindingToNormalizedNodeCodec codecRegistry;
     private final DOMNotificationPublishService domPublishService;
 
-    public BindingDOMNotificationPublishServiceAdapter(final BindingNormalizedNodeSerializer codecRegistry, final DOMNotificationPublishService domPublishService) {
-        this.codecRegistry = codecRegistry;
+    public BindingDOMNotificationPublishServiceAdapter(final BindingToNormalizedNodeCodec codec, final DOMNotificationPublishService domPublishService) {
+        this.codecRegistry = codec;
         this.domPublishService = domPublishService;
     }
 
+    public BindingToNormalizedNodeCodec getCodecRegistry() {
+        return codecRegistry;
+    }
+
+    public DOMNotificationPublishService getDomPublishService() {
+        return domPublishService;
+    }
+
     @Override
     public void putNotification(final Notification notification) throws InterruptedException {
         domPublishService.putNotification(toDomNotification(notification));
@@ -76,9 +83,8 @@ public class BindingDOMNotificationPublishServiceAdapter implements Notification
         @Override
         protected NotificationPublishService createInstance(final BindingToNormalizedNodeCodec codec,
                 final ClassToInstanceMap<DOMService> delegates) {
-            final BindingNormalizedNodeSerializer codecReg = codec.getCodecRegistry();
             final DOMNotificationPublishService domPublish = delegates.getInstance(DOMNotificationPublishService.class);
-            return new BindingDOMNotificationPublishServiceAdapter(codecReg, domPublish);
+            return new BindingDOMNotificationPublishServiceAdapter(codec, domPublish);
         }
 
     }
index ec7df74e6098511885f595603c48afa6157adc3f..3795ad3bac8c4787bda7ff27cd22668b398eeb33 100644 (file)
@@ -16,9 +16,11 @@ import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableBiMap;
 import java.lang.reflect.Method;
 import java.util.AbstractMap.SimpleEntry;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
@@ -44,6 +46,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
@@ -304,4 +307,19 @@ public final class BindingToNormalizedNodeCodec implements BindingCodecTreeFacto
         return new SimpleEntry<InstanceIdentifier<?>, BindingCodecTreeNode<?>>(bindingPath, codecContext);
     }
 
+    public Set<Class<? extends Notification>> getNotificationClasses(final Set<SchemaPath> interested) {
+        final Set<Class<? extends Notification>> result = new HashSet<>();
+        final Set<NotificationDefinition> knownNotifications = runtimeContext.getSchemaContext().getNotifications();
+        for (final NotificationDefinition notification : knownNotifications) {
+            if (interested.contains(notification.getPath())) {
+                try {
+                    result.add((Class<? extends Notification>) runtimeContext.getClassForSchema(notification));
+                } catch (final IllegalStateException e) {
+                    // Ignore
+                }
+            }
+        }
+        return result;
+    }
+
 }
index 2647477c0f3e316f51983b0ad81ac9a5fb353310..ab6d1444aab1fc7c0dc7615fb38ab29383340c27 100644 (file)
@@ -80,7 +80,7 @@ public class DataBrokerTestCustomizer {
     }
 
     public NotificationPublishService createNotificationPublishService() {
-        return new BindingDOMNotificationPublishServiceAdapter(bindingToNormalized.getCodecRegistry(), domNotificationRouter);
+        return new BindingDOMNotificationPublishServiceAdapter(bindingToNormalized, domNotificationRouter);
     }
 
 
index e814dd254153d6ae8c32e38f7a6745a4e79d7e2e..d623c3ec969fed939fde3b683639837161a9e72b 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.md.sal.dom.broker.impl;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableMultimap.Builder;
 import com.google.common.collect.Multimap;
@@ -23,6 +24,8 @@ import com.lmax.disruptor.dsl.Disruptor;
 import com.lmax.disruptor.dsl.ProducerType;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
@@ -30,9 +33,14 @@ import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
+import org.opendaylight.controller.md.sal.dom.spi.DOMNotificationSubscriptionListener;
+import org.opendaylight.controller.md.sal.dom.spi.DOMNotificationSubscriptionListenerRegistry;
 import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.util.ListenerRegistry;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Joint implementation of {@link DOMNotificationPublishService} and {@link DOMNotificationService}. Provides
@@ -48,7 +56,10 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath;
  * are realized using the Disruptor's native operations. The bounded-blocking {@link #offerNotification(DOMNotification, long, TimeUnit)}
  * is realized by arming a background wakeup interrupt.
  */
-public final class DOMNotificationRouter implements AutoCloseable, DOMNotificationPublishService, DOMNotificationService {
+public final class DOMNotificationRouter implements AutoCloseable, DOMNotificationPublishService,
+        DOMNotificationService, DOMNotificationSubscriptionListenerRegistry {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DOMNotificationRouter.class);
     private static final ListenableFuture<Void> NO_LISTENERS = Futures.immediateFuture(null);
     private static final WaitStrategy DEFAULT_STRATEGY = PhasedBackoffWaitStrategy.withLock(1L, 30L, TimeUnit.MILLISECONDS);
     private static final EventHandler<DOMNotificationRouterEvent> DISPATCH_NOTIFICATIONS = new EventHandler<DOMNotificationRouterEvent>() {
@@ -68,6 +79,7 @@ public final class DOMNotificationRouter implements AutoCloseable, DOMNotificati
     private final Disruptor<DOMNotificationRouterEvent> disruptor;
     private final ExecutorService executor;
     private volatile Multimap<SchemaPath, ListenerRegistration<? extends DOMNotificationListener>> listeners = ImmutableMultimap.of();
+    private final ListenerRegistry<DOMNotificationSubscriptionListener> subscriptionListeners = ListenerRegistry.create();
 
     private DOMNotificationRouter(final ExecutorService executor, final Disruptor<DOMNotificationRouterEvent> disruptor) {
         this.executor = Preconditions.checkNotNull(executor);
@@ -94,12 +106,12 @@ public final class DOMNotificationRouter implements AutoCloseable, DOMNotificati
                 final ListenerRegistration<T> me = this;
 
                 synchronized (DOMNotificationRouter.this) {
-                    listeners = ImmutableMultimap.copyOf(Multimaps.filterValues(listeners, new Predicate<ListenerRegistration<? extends DOMNotificationListener>>() {
+                    replaceListeners(ImmutableMultimap.copyOf(Multimaps.filterValues(listeners, new Predicate<ListenerRegistration<? extends DOMNotificationListener>>() {
                         @Override
                         public boolean apply(final ListenerRegistration<? extends DOMNotificationListener> input) {
                             return input != me;
                         }
-                    }));
+                    })));
                 }
             }
         };
@@ -108,11 +120,11 @@ public final class DOMNotificationRouter implements AutoCloseable, DOMNotificati
             final Builder<SchemaPath, ListenerRegistration<? extends DOMNotificationListener>> b = ImmutableMultimap.builder();
             b.putAll(listeners);
 
-            for (SchemaPath t : types) {
+            for (final SchemaPath t : types) {
                 b.put(t, reg);
             }
 
-            listeners = b.build();
+            replaceListeners(b.build());
         }
 
         return reg;
@@ -123,6 +135,48 @@ public final class DOMNotificationRouter implements AutoCloseable, DOMNotificati
         return registerNotificationListener(listener, Arrays.asList(types));
     }
 
+    /**
+     * Swaps registered listeners and triggers notification update
+     *
+     * @param newListeners
+     */
+    private void replaceListeners(
+            final Multimap<SchemaPath, ListenerRegistration<? extends DOMNotificationListener>> newListeners) {
+        listeners = newListeners;
+        notifyListenerTypesChanged(newListeners.keySet());
+    }
+
+    private void notifyListenerTypesChanged(final Set<SchemaPath> typesAfter) {
+        final List<ListenerRegistration<DOMNotificationSubscriptionListener>> listenersAfter =ImmutableList.copyOf(subscriptionListeners.getListeners());
+        executor.submit(new Runnable() {
+
+            @Override
+            public void run() {
+                for (final ListenerRegistration<DOMNotificationSubscriptionListener> subListener : listenersAfter) {
+                    try {
+                        subListener.getInstance().onSubscriptionChanged(typesAfter);
+                    } catch (final Exception e) {
+                        LOG.warn("Uncaught exception during invoking listener {}", subListener.getInstance(), e);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public <L extends DOMNotificationSubscriptionListener> ListenerRegistration<L> registerSubscriptionListener(
+            final L listener) {
+        final Set<SchemaPath> initialTypes = listeners.keySet();
+        executor.submit(new Runnable() {
+
+            @Override
+            public void run() {
+                listener.onSubscriptionChanged(initialTypes);
+            }
+        });
+        return subscriptionListeners.registerWithType(listener);
+    }
+
     private ListenableFuture<Void> publish(final long seq, final DOMNotification notification, final Collection<ListenerRegistration<? extends DOMNotificationListener>> subscribers) {
         final DOMNotificationRouterEvent event = disruptor.get(seq);
         final ListenableFuture<Void> future = event.initialize(notification, subscribers);
@@ -145,7 +199,7 @@ public final class DOMNotificationRouter implements AutoCloseable, DOMNotificati
         final long seq;
         try {
              seq = disruptor.getRingBuffer().tryNext();
-        } catch (InsufficientCapacityException e) {
+        } catch (final InsufficientCapacityException e) {
             return DOMNotificationPublishService.REJECTED;
         }
 
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DOMNotificationSubscriptionListener.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DOMNotificationSubscriptionListener.java
new file mode 100644 (file)
index 0000000..85369da
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.spi;
+
+import com.google.common.annotations.Beta;
+import java.util.EventListener;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+/**
+ * Listener which is notified when subscriptions changes and
+ * provides set of notification types for which currently
+ * subscriptions are in place.
+ *
+ */
+@Beta
+public interface DOMNotificationSubscriptionListener extends EventListener {
+
+    /**
+     * Invoked when notification subscription changed
+     *
+     * @param currentTypes Set of notification types
+     * for which listeners are registered.
+     */
+    void onSubscriptionChanged(Set<SchemaPath> currentTypes);
+
+}
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DOMNotificationSubscriptionListenerRegistry.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DOMNotificationSubscriptionListenerRegistry.java
new file mode 100644 (file)
index 0000000..77e0d35
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.spi;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+/**
+ * Registry of {@link DOMNotificationSubscriptionListener}
+ * which listens for changes in notification types.
+ *
+ */
+@Beta
+public interface DOMNotificationSubscriptionListenerRegistry  {
+
+    <L extends DOMNotificationSubscriptionListener> ListenerRegistration<L> registerSubscriptionListener(L listener);
+
+}