X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fsal%2Fyang-prototype%2Fsal%2Fsal-binding-broker-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fbinding%2Fimpl%2FNotificationModule.java;fp=opendaylight%2Fsal%2Fyang-prototype%2Fsal%2Fsal-binding-broker-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fbinding%2Fimpl%2FNotificationModule.java;h=189c58555fbb562337335bac30a77c469b0b2461;hb=ca85a6f3a39b406ab122fe985ee010a41489f658;hp=0000000000000000000000000000000000000000;hpb=ed39d9e127dcea25cdd05e4f228a6d7b8b08fad5;p=controller.git diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationModule.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationModule.java new file mode 100644 index 0000000000..189c58555f --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationModule.java @@ -0,0 +1,230 @@ +package org.opendaylight.controller.sal.binding.impl; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareService; +import org.opendaylight.controller.sal.binding.api.NotificationProviderService; +import org.opendaylight.controller.sal.binding.api.NotificationService; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerSession; +import org.opendaylight.controller.sal.binding.spi.SALBindingModule; +import org.opendaylight.controller.sal.binding.spi.Mapper; +import org.opendaylight.controller.sal.binding.spi.MappingProvider; +import org.opendaylight.controller.sal.binding.spi.MappingProvider.MappingExtensionFactory; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.yang.binding.DataObject; +import org.opendaylight.controller.yang.binding.Notification; +import org.opendaylight.controller.yang.binding.NotificationListener; +import org.opendaylight.controller.yang.common.QName; +import org.opendaylight.controller.yang.data.api.CompositeNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NotificationModule implements SALBindingModule { + + private ProviderSession biSession; + private org.opendaylight.controller.sal.core.api.notify.NotificationProviderService biNotifyService; + private BindingAwareBroker broker; + private MappingProvider mappingProvider; + + private Map, List> listeners = new HashMap, List>(); + private static Logger log = LoggerFactory.getLogger(NotificationModule.class); + + @Override + public Set> getProvidedServices() { + + Set> ret = new HashSet>(); + ret.add(NotificationService.class); + ret.add(NotificationProviderService.class); + return ret; + } + + @Override + public T getServiceForSession( + Class service, ConsumerSession session) { + if (service == null) + throw new IllegalArgumentException("Service should not be null"); + if (session == null) + throw new IllegalArgumentException("Session should not be null"); + + if (NotificationProviderSession.class.equals(service)) { + if (session instanceof org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderSession) { + @SuppressWarnings("unchecked") + T ret = (T) new NotificationProviderSession(session); + return ret; + } else { + throw new IllegalArgumentException( + "NotificationProviderService is available only to ProviderSession"); + } + } + + if (NotificationService.class.equals(service)) { + @SuppressWarnings("unchecked") + T ret = (T) new NotificationSession(session); + return ret; + } + return null; + } + + @Override + public Set> getSupportedProviderFunctionality() { + return Collections.emptySet(); + } + + @Override + public void setBroker(BindingAwareBroker broker) { + this.broker = broker; + } + + @Override + public void setMappingProvider(MappingProvider provider) { + this.mappingProvider = provider; + } + + @Override + public void onBISessionAvailable(ProviderSession session) { + biSession = session; + if (biSession != null) { + biNotifyService = session + .getService(org.opendaylight.controller.sal.core.api.notify.NotificationProviderService.class); + } + } + + private void notify(Notification notification) { + notifyBindingIndependent(notification); + notifyBindingAware(notification); + } + + private void notifyBindingAware(Notification notification) { + Class type = notification.getClass(); + List toNotify = listeners.get(type); + + // Invocation of notification on registered listeners + if (toNotify != null) { + + // We get factory for Notification Invoker + MappingExtensionFactory invokerFactory = mappingProvider + .getExtensionFactory(NotificationInvoker.class); + + // We get generated invoker for NoficiationListener interface + // associated to Notification Type + NotificationInvoker invoker = invokerFactory.forClass(type); + for (NotificationListener listener : toNotify) { + try { + // Invoker invokes the right method on subtype of + // NotificationListener + // associated to the type of notification + invoker.notify(notification, listener); + } catch (Exception e) { + + } + } + } + } + + private void notifyBindingIndependent(Notification notification) { + Class type = notification.getClass(); + + if (biSession == null) { + return; + } + if (biSession.isClosed()) { + return; + } + if (biNotifyService == null) { + return; + } + + // FIXME: Somehow we need to resolve this for class hierarchy. + // probably use type.getInterfaces() + Mapper mapper = mappingProvider.getMapper(type); + CompositeNode domNotification = mapper.domFromObject(notification); + + biNotifyService.sendNotification(domNotification); + } + + private class NotificationSession implements NotificationService { + private final ConsumerSession session; + + public NotificationSession(ConsumerSession session) { + this.session = session; + } + + private Map, List> sessionListeners = new HashMap, List>(); + + @Override + public void addNotificationListener( + Class notificationType, + NotificationListener listener) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public void removeNotificationListener( + Class notificationType, + NotificationListener listener) { + // TODO Implement this method + throw new UnsupportedOperationException("Not implemented"); + } + + } + + private class NotificationProviderSession extends NotificationSession + implements NotificationProviderService { + + public NotificationProviderSession(ConsumerSession session) { + super(session); + } + + @Override + public void notify(Notification notification) { + NotificationModule.this.notify(notification); + } + + } + + private class BindingIndependentListener implements org.opendaylight.controller.sal.core.api.notify.NotificationListener { + + @Override + public Set getSupportedNotifications() { + return Collections.emptySet(); + } + + @Override + public void onNotification(CompositeNode notification) { + NotificationModule.this.onBindingIndependentNotification(notification); + } + + } + + private void onBindingIndependentNotification(CompositeNode biNotification) { + QName biType = biNotification.getNodeType(); + + Mapper mapper = mappingProvider.getMapper(biType); + if(mapper == null) { + log.info("Received notification does not have a binding defined."); + return; + } + Class type = mapper.getDataObjectClass(); + + // We check if the received QName / type is really Notification + if(Notification.class.isAssignableFrom(type)) { + Notification notification = (Notification) mapper.objectFromDom(biNotification); + notifyBindingAware(notification); + } else { + // The generated type for this QName does not inherits from notification + // something went wrong - generated APIs and/or provider sending notification + // which was incorectly described in the YANG schema. + log.error("Received notification "+ biType +" is not binded as notification"); + } + + } +}