2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.sal.streams.listeners;
10 import java.util.ArrayList;
11 import java.util.List;
14 import java.util.concurrent.ConcurrentHashMap;
15 import java.util.concurrent.locks.Lock;
16 import java.util.concurrent.locks.ReentrantLock;
17 import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
18 import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping.NotificationOutputType;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
20 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
21 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * {@link Notificator} is responsible to create, remove and find
27 * {@link ListenerAdapter} listener.
29 public final class Notificator {
31 private static Map<String, ListenerAdapter> dataChangeListener = new ConcurrentHashMap<>();
32 private static Map<String, List<NotificationListenerAdapter>> notificationListenersByStreamName =
33 new ConcurrentHashMap<>();
35 private static final Logger LOG = LoggerFactory.getLogger(Notificator.class);
36 private static final Lock LOCK = new ReentrantLock();
38 private Notificator() {
42 * Returns list of all stream names.
44 public static Set<String> getStreamNames() {
45 return dataChangeListener.keySet();
49 * Gets {@link ListenerAdapter} specified by stream name.
52 * The name of the stream.
53 * @return {@link ListenerAdapter} specified by stream name.
55 public static ListenerAdapter getListenerFor(final String streamName) {
56 return dataChangeListener.get(streamName);
60 * Checks if the listener specified by {@link YangInstanceIdentifier} path exist.
62 * @param streamName name of the stream
63 * @return True if the listener exist, false otherwise.
65 public static boolean existListenerFor(final String streamName) {
66 return dataChangeListener.containsKey(streamName);
70 * Creates new {@link ListenerAdapter} listener from
71 * {@link YangInstanceIdentifier} path and stream name.
74 * Path to data in data repository.
76 * The name of the stream.
78 * Spcific type of output for notifications - XML or JSON
79 * @return New {@link ListenerAdapter} listener from
80 * {@link YangInstanceIdentifier} path and stream name.
82 public static ListenerAdapter createListener(final YangInstanceIdentifier path, final String streamName,
83 final NotificationOutputType outputType, final ControllerContext controllerContext) {
84 final ListenerAdapter listener = new ListenerAdapter(path, streamName, outputType, controllerContext);
87 dataChangeListener.put(streamName, listener);
95 * Looks for listener determined by {@link YangInstanceIdentifier} path and removes it.
96 * Creates String representation of stream name from URI. Removes slash from URI in start and end position.
99 * URI for creation stream name.
100 * @return String representation of stream name.
102 public static String createStreamNameFromUri(final String uri) {
107 if (result.startsWith("/")) {
108 result = result.substring(1);
110 if (result.endsWith("/")) {
111 result = result.substring(0, result.length() - 1);
117 * Removes all listeners.
119 @SuppressWarnings("checkstyle:IllegalCatch")
120 public static void removeAllListeners() {
121 for (final ListenerAdapter listener : dataChangeListener.values()) {
124 } catch (final Exception e) {
125 LOG.error("Failed to close listener", e);
130 dataChangeListener = new ConcurrentHashMap<>();
137 * Delete {@link ListenerAdapter} listener specified in parameter.
144 @SuppressWarnings("checkstyle:IllegalCatch")
145 private static <T extends BaseListenerInterface> void deleteListener(final T listener) {
146 if (listener != null) {
149 } catch (final Exception e) {
150 LOG.error("Failed to close listener", e);
154 dataChangeListener.remove(listener.getStreamName());
162 * Check if the listener specified by qnames of request exist.
166 * @return True if the listener exist, false otherwise.
168 public static boolean existNotificationListenerFor(final String streamName) {
169 return notificationListenersByStreamName.containsKey(streamName);
173 * Prepare listener for notification ({@link NotificationDefinition}).
176 * paths of notifications
178 * name of stream (generated by paths)
180 * type of output for onNotification - XML or JSON
181 * @return List of {@link NotificationListenerAdapter} by paths
183 public static List<NotificationListenerAdapter> createNotificationListener(final List<Absolute> paths,
184 final String streamName, final String outputType, final ControllerContext controllerContext) {
185 final List<NotificationListenerAdapter> listListeners = new ArrayList<>();
186 for (final Absolute path : paths) {
187 final NotificationListenerAdapter listener =
188 new NotificationListenerAdapter(path, streamName, outputType, controllerContext);
189 listListeners.add(listener);
193 notificationListenersByStreamName.put(streamName, listListeners);
197 return listListeners;
200 public static <T extends BaseListenerInterface> void removeListenerIfNoSubscriberExists(final T listener) {
201 if (!listener.hasSubscribers()) {
202 if (listener instanceof NotificationListenerAdapter) {
203 deleteNotificationListener(listener);
205 deleteListener(listener);
210 @SuppressWarnings("checkstyle:IllegalCatch")
211 private static <T extends BaseListenerInterface> void deleteNotificationListener(final T listener) {
212 if (listener != null) {
215 } catch (final Exception e) {
216 LOG.error("Failed to close listener", e);
220 notificationListenersByStreamName.remove(listener.getStreamName());
227 public static List<NotificationListenerAdapter> getNotificationListenerFor(final String streamName) {
228 return notificationListenersByStreamName.get(streamName);