1 package org.opendaylight.controller.sal.binding.impl;
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.HashSet;
11 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
12 import org.opendaylight.controller.sal.binding.api.BindingAwareService;
13 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
14 import org.opendaylight.controller.sal.binding.api.NotificationService;
15 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerSession;
16 import org.opendaylight.controller.sal.binding.spi.SALBindingModule;
17 import org.opendaylight.controller.sal.binding.spi.Mapper;
18 import org.opendaylight.controller.sal.binding.spi.MappingProvider;
19 import org.opendaylight.controller.sal.binding.spi.MappingProvider.MappingExtensionFactory;
20 import org.opendaylight.controller.sal.core.api.Provider;
21 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
22 import org.opendaylight.controller.yang.binding.DataObject;
23 import org.opendaylight.controller.yang.binding.Notification;
24 import org.opendaylight.controller.yang.binding.NotificationListener;
25 import org.opendaylight.controller.yang.common.QName;
26 import org.opendaylight.controller.yang.data.api.CompositeNode;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 public class NotificationModule implements SALBindingModule {
32 private ProviderSession biSession;
33 private org.opendaylight.controller.sal.core.api.notify.NotificationProviderService biNotifyService;
34 private BindingAwareBroker broker;
35 private MappingProvider mappingProvider;
37 private Map<Class<? extends Notification>, List<NotificationListener>> listeners = new HashMap<Class<? extends Notification>, List<NotificationListener>>();
38 private static Logger log = LoggerFactory.getLogger(NotificationModule.class);
41 public Set<Class<? extends BindingAwareService>> getProvidedServices() {
43 Set<Class<? extends BindingAwareService>> ret = new HashSet<Class<? extends BindingAwareService>>();
44 ret.add(NotificationService.class);
45 ret.add(NotificationProviderService.class);
50 public <T extends BindingAwareService> T getServiceForSession(
51 Class<T> service, ConsumerSession session) {
53 throw new IllegalArgumentException("Service should not be null");
55 throw new IllegalArgumentException("Session should not be null");
57 if (NotificationProviderSession.class.equals(service)) {
58 if (session instanceof org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderSession) {
59 @SuppressWarnings("unchecked")
60 T ret = (T) new NotificationProviderSession(session);
63 throw new IllegalArgumentException(
64 "NotificationProviderService is available only to ProviderSession");
68 if (NotificationService.class.equals(service)) {
69 @SuppressWarnings("unchecked")
70 T ret = (T) new NotificationSession(session);
77 public Set<Class<? extends org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality>> getSupportedProviderFunctionality() {
78 return Collections.emptySet();
82 public void setBroker(BindingAwareBroker broker) {
87 public void setMappingProvider(MappingProvider provider) {
88 this.mappingProvider = provider;
92 public void onBISessionAvailable(ProviderSession session) {
94 if (biSession != null) {
95 biNotifyService = session
96 .getService(org.opendaylight.controller.sal.core.api.notify.NotificationProviderService.class);
100 private void notify(Notification notification) {
101 notifyBindingIndependent(notification);
102 notifyBindingAware(notification);
105 private void notifyBindingAware(Notification notification) {
106 Class<? extends Notification> type = notification.getClass();
107 List<NotificationListener> toNotify = listeners.get(type);
109 // Invocation of notification on registered listeners
110 if (toNotify != null) {
112 // We get factory for Notification Invoker
113 MappingExtensionFactory<NotificationInvoker> invokerFactory = mappingProvider
114 .getExtensionFactory(NotificationInvoker.class);
116 // We get generated invoker for NoficiationListener interface
117 // associated to Notification Type
118 NotificationInvoker invoker = invokerFactory.forClass(type);
119 for (NotificationListener listener : toNotify) {
121 // Invoker invokes the right method on subtype of
122 // NotificationListener
123 // associated to the type of notification
124 invoker.notify(notification, listener);
125 } catch (Exception e) {
132 private void notifyBindingIndependent(Notification notification) {
133 Class<? extends Notification> type = notification.getClass();
135 if (biSession == null) {
138 if (biSession.isClosed()) {
141 if (biNotifyService == null) {
145 // FIXME: Somehow we need to resolve this for class hierarchy.
146 // probably use type.getInterfaces()
147 Mapper<? extends Notification> mapper = mappingProvider.getMapper(type);
148 CompositeNode domNotification = mapper.domFromObject(notification);
150 biNotifyService.sendNotification(domNotification);
153 private class NotificationSession implements NotificationService {
154 private final ConsumerSession session;
156 public NotificationSession(ConsumerSession session) {
157 this.session = session;
160 private Map<Class<? extends Notification>, List<NotificationListener>> sessionListeners = new HashMap<Class<? extends Notification>, List<NotificationListener>>();
163 public void addNotificationListener(
164 Class<? extends Notification> notificationType,
165 NotificationListener listener) {
166 // TODO Implement this method
167 throw new UnsupportedOperationException("Not implemented");
171 public void removeNotificationListener(
172 Class<? extends Notification> notificationType,
173 NotificationListener listener) {
174 // TODO Implement this method
175 throw new UnsupportedOperationException("Not implemented");
180 private class NotificationProviderSession extends NotificationSession
181 implements NotificationProviderService {
183 public NotificationProviderSession(ConsumerSession session) {
188 public void notify(Notification notification) {
189 NotificationModule.this.notify(notification);
194 private class BindingIndependentListener implements org.opendaylight.controller.sal.core.api.notify.NotificationListener {
197 public Set<QName> getSupportedNotifications() {
198 return Collections.emptySet();
202 public void onNotification(CompositeNode notification) {
203 NotificationModule.this.onBindingIndependentNotification(notification);
208 private void onBindingIndependentNotification(CompositeNode biNotification) {
209 QName biType = biNotification.getNodeType();
211 Mapper<DataObject> mapper = mappingProvider.getMapper(biType);
213 log.info("Received notification does not have a binding defined.");
216 Class<DataObject> type = mapper.getDataObjectClass();
218 // We check if the received QName / type is really Notification
219 if(Notification.class.isAssignableFrom(type)) {
220 Notification notification = (Notification) mapper.objectFromDom(biNotification);
221 notifyBindingAware(notification);
223 // The generated type for this QName does not inherits from notification
224 // something went wrong - generated APIs and/or provider sending notification
225 // which was incorectly described in the YANG schema.
226 log.error("Received notification "+ biType +" is not binded as notification");