*/
package org.opendaylight.controller.sal.binding.impl;
-import java.util.Collections;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import org.eclipse.xtext.xbase.lib.Conversions;
-import org.eclipse.xtext.xbase.lib.Functions.Function1;
-import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.opendaylight.controller.sal.binding.api.NotificationListener;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker;
+import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
private final ListenerRegistry<NotificationInterestListener> interestListeners =
ListenerRegistry.create();
- private final Multimap<Class<? extends Notification>, NotificationListener<?>> listeners =
- Multimaps.synchronizedSetMultimap(HashMultimap.<Class<? extends Notification>, NotificationListener<?>>create());
+ private final Multimap<Class<? extends Notification>, NotificationListenerRegistration<?>> listeners =
+ Multimaps.synchronizedSetMultimap(HashMultimap.<Class<? extends Notification>, NotificationListenerRegistration<?>>create());
private ExecutorService executor;
@Deprecated
}
public Iterable<Class<?>> getNotificationTypes(final Notification notification) {
- Class<?>[] _interfaces = notification.getClass().getInterfaces();
- final Function1<Class<?>, Boolean> _function = new Function1<Class<?>, Boolean>() {
+ final Class<?>[] ifaces = notification.getClass().getInterfaces();
+ return Iterables.filter(Arrays.asList(ifaces), new Predicate<Class<?>>() {
@Override
- public Boolean apply(final Class<?> it) {
- if (Notification.class.equals(it)) {
+ public boolean apply(final Class<?> input) {
+ if (Notification.class.equals(input)) {
return false;
}
- return Notification.class.isAssignableFrom(it);
+ return Notification.class.isAssignableFrom(input);
}
- };
- return IterableExtensions.filter(((Iterable<Class<?>>)Conversions.doWrapArray(_interfaces)), _function);
+ });
}
@Override
@Override
public void publish(final Notification notification, final ExecutorService service) {
- Iterable<NotificationListener<?>> listenerToNotify = Collections.emptySet();
+ final Set<NotificationListenerRegistration<?>> toNotify = new HashSet<>();
+
for (final Class<?> type : getNotificationTypes(notification)) {
- listenerToNotify = Iterables.concat(listenerToNotify, listeners.get(((Class<? extends Notification>) type)));
- }
- final Function1<NotificationListener<?>,NotifyTask> _function = new Function1<NotificationListener<?>, NotifyTask>() {
- @Override
- public NotifyTask apply(final NotificationListener<?> it) {
- return new NotifyTask(it, notification);
+ final Collection<NotificationListenerRegistration<?>> l = listeners.get((Class<? extends Notification>) type);
+ if (l != null) {
+ toNotify.addAll(l);
}
- };
- final Set<NotifyTask> tasks = IterableExtensions.<NotifyTask>toSet(
- IterableExtensions.<NotificationListener<?>, NotifyTask>map(listenerToNotify, _function));
- this.submitAll(executor, tasks);
+ }
+
+ for (NotificationListenerRegistration<?> r : toNotify) {
+ service.submit(new NotifyTask(r, notification));
+ }
+ }
+
+ private void addRegistrations(final NotificationListenerRegistration<?>... registrations) {
+ for (NotificationListenerRegistration<?> reg : registrations) {
+ listeners.put(reg.getType(), reg);
+ this.announceNotificationSubscription(reg.getType());
+ }
}
- private ImmutableSet<Future<Object>> submitAll(final ExecutorService service, final Set<NotifyTask> tasks) {
- final Builder<Future<Object>> ret = ImmutableSet.<Future<Object>>builder();
- for (final NotifyTask task : tasks) {
- ret.add(service.submit(task));
+ void removeRegistrations(final NotificationListenerRegistration<?>... registrations) {
+ for (NotificationListenerRegistration<?> reg : registrations) {
+ listeners.remove(reg.getType(), reg);
}
- return ret.build();
}
@Override
- public <T extends Notification> Registration<NotificationListener<T>> registerNotificationListener(final Class<T> notificationType, final NotificationListener<T> listener) {
- final GenericNotificationRegistration<T> reg = new GenericNotificationRegistration<T>(notificationType, listener, this);
- this.listeners.put(notificationType, listener);
- this.announceNotificationSubscription(notificationType);
+ public <T extends Notification> NotificationListenerRegistration<T> registerNotificationListener(final Class<T> notificationType, final NotificationListener<T> listener) {
+ final NotificationListenerRegistration<T> reg = new AbstractNotificationListenerRegistration<T>(notificationType, listener) {
+ @Override
+ protected void removeRegistration() {
+ removeRegistrations(this);
+ }
+ };
+
+ addRegistrations(reg);
return reg;
}
}
@Override
- public Registration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(final org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
+ public ListenerRegistration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(final org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
final NotificationInvoker invoker = SingletonHolder.INVOKER_FACTORY.invokerFor(listener);
- for (final Class<? extends Notification> notifyType : invoker.getSupportedNotifications()) {
- listeners.put(notifyType, invoker.getInvocationProxy());
- announceNotificationSubscription(notifyType);
+ final Set<Class<? extends Notification>> types = invoker.getSupportedNotifications();
+ final NotificationListenerRegistration<?>[] regs = new NotificationListenerRegistration<?>[types.size()];
+
+ // Populate the registrations...
+ int i = 0;
+ for (Class<? extends Notification> type : types) {
+ regs[i] = new AggregatedNotificationListenerRegistration<Notification, Object>(type, invoker.getInvocationProxy(), regs) {
+ @Override
+ protected void removeRegistration() {
+ // Nothing to do, will be cleaned up by parent (below)
+ }
+ };
+ ++i;
}
- return new GeneratedListenerRegistration(listener, invoker, this);
- }
-
- protected boolean unregisterListener(final GenericNotificationRegistration<?> reg) {
- return listeners.remove(reg.getType(), reg.getInstance());
- }
+ // ... now put them to use ...
+ addRegistrations(regs);
- protected void unregisterListener(final GeneratedListenerRegistration reg) {
- final NotificationInvoker invoker = reg.getInvoker();
- for (final Class<? extends Notification> notifyType : invoker.getSupportedNotifications()) {
- this.listeners.remove(notifyType, invoker.getInvocationProxy());
- }
+ // ... finally return the parent registration
+ return new AbstractListenerRegistration<org.opendaylight.yangtools.yang.binding.NotificationListener>(listener) {
+ @Override
+ protected void removeRegistration() {
+ removeRegistrations(regs);
+ for (ListenerRegistration<?> reg : regs) {
+ reg.close();
+ }
+ }
+ };
}
@Override