/* * 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.impl.BindingDOMNotificationPublishServiceAdapter; import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationServiceAdapter; import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec; 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.controller.sal.binding.api.NotificationListener; import org.opendaylight.yangtools.concepts.AbstractListenerRegistration; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.util.ListenerRegistry; import org.opendaylight.yangtools.yang.binding.Notification; import org.opendaylight.yangtools.yang.binding.util.BindingReflections; 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 DOMNotificationService domService; private final BindingToNormalizedNodeCodec codec; public HeliumNotificationProviderServiceWithInterestListeners( final BindingDOMNotificationPublishServiceAdapter publishService, final BindingDOMNotificationServiceAdapter listenService, final DOMNotificationSubscriptionListenerRegistry registry) { super(publishService, listenService); this.codec = publishService.getCodecRegistry(); this.domListener = registry.registerSubscriptionListener(new Listener()); this.domService = listenService.getDomService(); } @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); } } } } @Override public <T extends Notification> ListenerRegistration<NotificationListener<T>> registerNotificationListener( final Class<T> type, final NotificationListener<T> listener) { final FunctionalNotificationListenerAdapter<T> adapter = new FunctionalNotificationListenerAdapter<>(codec, type, listener); final SchemaPath domType = SchemaPath.create(true, BindingReflections.findQName(type)); final ListenerRegistration<?> domReg = domService.registerNotificationListener(adapter, domType); return new AbstractListenerRegistration<NotificationListener<T>>(listener) { @Override protected void removeRegistration() { domReg.close(); } }; } 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(); } }