+++ /dev/null
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.sal.binding.impl;\r
-\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.HashSet;\r
-import java.util.Set;\r
-\r
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;\r
-import org.opendaylight.controller.sal.binding.api.BindingAwareService;\r
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService;\r
-import org.opendaylight.controller.sal.binding.api.NotificationService;\r
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerSession;\r
-import org.opendaylight.controller.sal.binding.spi.SALBindingModule;\r
-import org.opendaylight.controller.sal.binding.spi.Mapper;\r
-import org.opendaylight.controller.sal.binding.spi.MappingProvider;\r
-import org.opendaylight.controller.sal.binding.spi.MappingProvider.MappingExtensionFactory;\r
-\r
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;\r
-import org.opendaylight.controller.yang.binding.DataObject;\r
-import org.opendaylight.controller.yang.binding.Notification;\r
-import org.opendaylight.controller.yang.binding.NotificationListener;\r
-import org.opendaylight.controller.yang.common.QName;\r
-import org.opendaylight.controller.yang.data.api.CompositeNode;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import com.google.common.collect.HashMultimap;\r
-import com.google.common.collect.Multimap;\r
-\r
-public class NotificationModule implements SALBindingModule {\r
-\r
- private ProviderSession biSession;\r
- private org.opendaylight.controller.sal.core.api.notify.NotificationProviderService biNotifyService;\r
- private MappingProvider mappingProvider;\r
-\r
- private Multimap<Class<? extends Notification>, NotificationListener> listeners = HashMultimap\r
- .create();\r
- private Set<QName> biNotifications = new HashSet<QName>();\r
- private static final Logger log = LoggerFactory\r
- .getLogger(NotificationModule.class);\r
- private final BindingIndependentListener biListener = new BindingIndependentListener();\r
- private BindingAwareBroker broker;\r
-\r
- @Override\r
- public Set<Class<? extends BindingAwareService>> getProvidedServices() {\r
-\r
- Set<Class<? extends BindingAwareService>> ret = new HashSet<Class<? extends BindingAwareService>>();\r
- ret.add(NotificationService.class);\r
- ret.add(NotificationProviderService.class);\r
- return ret;\r
- }\r
-\r
- @Override\r
- public <T extends BindingAwareService> T getServiceForSession(\r
- Class<T> service, ConsumerSession session) {\r
- if (service == null)\r
- throw new IllegalArgumentException("Service should not be null");\r
- if (session == null)\r
- throw new IllegalArgumentException("Session should not be null");\r
-\r
- if (NotificationProviderSession.class.equals(service)) {\r
- if (session instanceof org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderSession) {\r
- @SuppressWarnings("unchecked")\r
- T ret = (T) new NotificationProviderSession(session);\r
- return ret;\r
- } else {\r
- throw new IllegalArgumentException(\r
- "NotificationProviderService is available only to ProviderSession");\r
- }\r
- }\r
-\r
- if (NotificationService.class.equals(service)) {\r
- @SuppressWarnings("unchecked")\r
- T ret = (T) new NotificationSession(session);\r
- return ret;\r
- }\r
- return null;\r
- }\r
-\r
- @Override\r
- public Set<Class<? extends org.opendaylight.controller.sal.binding.api.BindingAwareProvider.ProviderFunctionality>> getSupportedProviderFunctionality() {\r
- return Collections.emptySet();\r
- }\r
-\r
- @Override\r
- public void setBroker(BindingAwareBroker broker) {\r
- this.broker = broker;\r
- }\r
-\r
- @Override\r
- public void setMappingProvider(MappingProvider provider) {\r
- this.mappingProvider = provider;\r
- }\r
-\r
- @Override\r
- public void onBISessionAvailable(ProviderSession session) {\r
- biSession = session;\r
- if (biSession != null) {\r
- biNotifyService = session\r
- .getService(org.opendaylight.controller.sal.core.api.notify.NotificationProviderService.class);\r
- }\r
- }\r
-\r
- private void notify(Notification notification) {\r
- notifyBindingIndependent(notification);\r
- notifyBindingAware(notification);\r
- }\r
-\r
- private void notifyBindingAware(Notification notification) {\r
- Class<? extends Notification> type = notification.getClass();\r
- Collection<NotificationListener> toNotify = listeners.get(type);\r
-\r
- // Invocation of notification on registered listeners\r
- if (toNotify != null) {\r
-\r
- // We get factory for Notification Invoker\r
- MappingExtensionFactory<NotificationInvoker> invokerFactory = mappingProvider\r
- .getExtensionFactory(NotificationInvoker.class);\r
-\r
- // We get generated invoker for NoficiationListener interface\r
- // associated to Notification Type\r
- NotificationInvoker invoker = invokerFactory.forClass(type);\r
- for (NotificationListener listener : toNotify) {\r
- try {\r
- // Invoker invokes the right method on subtype of\r
- // NotificationListener\r
- // associated to the type of notification\r
- invoker.notify(notification, listener);\r
- } catch (Exception e) {\r
-\r
- }\r
- }\r
- }\r
- }\r
-\r
- private void notifyBindingIndependent(Notification notification) {\r
- Class<? extends Notification> type = notification.getClass();\r
-\r
- if (biSession == null) {\r
- return;\r
- }\r
- if (biSession.isClosed()) {\r
- return;\r
- }\r
- if (biNotifyService == null) {\r
- return;\r
- }\r
-\r
- // FIXME: Somehow we need to resolve this for class hierarchy.\r
- // probably use type.getInterfaces()\r
- Mapper<? extends Notification> mapper = mappingProvider\r
- .mapperForClass(type);\r
- CompositeNode domNotification = mapper.domFromObject(notification);\r
-\r
- biNotifyService.sendNotification(domNotification);\r
- }\r
-\r
- private void addBAListener(Class<? extends Notification> notificationType,\r
- NotificationListener listener) {\r
-\r
- listeners.put(notificationType, listener);\r
- Mapper<? extends Notification> mapper = mappingProvider\r
- .mapperForClass(notificationType);\r
- QName biType = mapper.getQName();\r
- if (false == biNotifications.contains(biType)) {\r
- // The listener is not registered for binding independent\r
- // notification\r
- biNotifications.add(biType);\r
-\r
- if (biNotifyService != null) {\r
- biNotifyService.addNotificationListener(biType, biListener);\r
- }\r
- }\r
-\r
- }\r
-\r
- private void removeBAListener(\r
- Class<? extends Notification> notificationType,\r
- NotificationListener listener) {\r
- listeners.remove(notificationType, listener);\r
- }\r
-\r
- private class NotificationSession implements NotificationService {\r
- private final ConsumerSession session;\r
- private Multimap<Class<? extends Notification>, NotificationListener> sessionListeners = HashMultimap\r
- .create();\r
-\r
- public NotificationSession(ConsumerSession session) {\r
- this.session = session;\r
- }\r
-\r
- @Override\r
- public void addNotificationListener(\r
- Class<? extends Notification> notificationType,\r
- NotificationListener listener) {\r
-\r
- NotificationModule.this.addBAListener(notificationType, listener);\r
- sessionListeners.put(notificationType, listener);\r
-\r
- }\r
-\r
- @Override\r
- public void removeNotificationListener(\r
- Class<? extends Notification> notificationType,\r
- NotificationListener listener) {\r
- sessionListeners.remove(notificationType, listener);\r
- NotificationModule.this\r
- .removeBAListener(notificationType, listener);\r
- }\r
-\r
- }\r
-\r
- private class NotificationProviderSession extends NotificationSession\r
- implements NotificationProviderService {\r
-\r
- public NotificationProviderSession(ConsumerSession session) {\r
- super(session);\r
- }\r
-\r
- @Override\r
- public void notify(Notification notification) {\r
- NotificationModule.this.notify(notification);\r
- }\r
-\r
- }\r
-\r
- private class BindingIndependentListener\r
- implements\r
- org.opendaylight.controller.sal.core.api.notify.NotificationListener {\r
-\r
- @Override\r
- public Set<QName> getSupportedNotifications() {\r
- return biNotifications;\r
- }\r
-\r
- @Override\r
- public void onNotification(CompositeNode notification) {\r
- NotificationModule.this\r
- .onBindingIndependentNotification(notification);\r
- }\r
-\r
- }\r
-\r
- private void onBindingIndependentNotification(CompositeNode biNotification) {\r
- QName biType = biNotification.getNodeType();\r
-\r
- Mapper<DataObject> mapper = mappingProvider.mapperForQName(biType);\r
- if (mapper == null) {\r
- log.info("Received notification does not have a binding defined.");\r
- return;\r
- }\r
- Class<DataObject> type = mapper.getDataObjectClass();\r
-\r
- // We check if the received QName / type is really Notification\r
- if (Notification.class.isAssignableFrom(type)) {\r
- Notification notification = (Notification) mapper\r
- .objectFromDom(biNotification);\r
- notifyBindingAware(notification);\r
- } else {\r
- // The generated type for this QName does not inherits from\r
- // notification something went wrong - generated APIs and/or\r
- // provider sending notification\r
- // which was incorectly described in the YANG schema.\r
- log.error("Received notification " + biType\r
- + " is not binded as notification");\r
- }\r
-\r
- }\r
-}\r