Clean up (DOM)DataTreeIdentifier methods
[mdsal.git] / binding / mdsal-binding-api / src / main / java / org / opendaylight / mdsal / binding / api / NotificationService.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.api;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.annotations.Beta;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import java.util.Set;
16 import java.util.concurrent.Executor;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.yangtools.concepts.Registration;
19 import org.opendaylight.yangtools.yang.binding.DataObject;
20 import org.opendaylight.yangtools.yang.binding.Notification;
21
22 /**
23  * Notification broker which allows clients to subscribe for and publish YANG 1.0 notifications, which is to say
24  * {@code notification} statements occurring directly within a {@code module} or a {@code submodule} statement.
25  */
26 public interface NotificationService extends BindingService {
27     /**
28      * Registers a {@link Listener} to receive callbacks for {@link Notification}s of a particular type.
29      *
30      * @param <N> Notification type
31      * @param type Notification type class
32      * @param listener The listener implementation that will receive notifications
33      * @param executor Executor to use for invoking the listener's methods
34      * @return a {@link Registration} instance that should be used to unregister the listener by invoking the
35      *        {@link Registration#close()} method when no longer needed
36      */
37     <N extends Notification<N> & DataObject> @NonNull Registration registerListener(Class<N> type, Listener<N> listener,
38         Executor executor);
39
40     /**
41      * Registers a {@link Listener} to receive callbacks for {@link Notification}s of a particular type.
42      *
43      * @implSpec
44      *     This method is equivalent to {@code registerListener(type, listener, MoreExecutors.directExecutor())}, i.e.
45      *     the listener will be invoked on some implementation-specific thread.
46      *
47      * @param <N> Notification type
48      * @param type Notification type class
49      * @param listener The listener implementation that will receive notifications
50      * @return a {@link Registration} instance that should be used to unregister the listener by invoking the
51      *        {@link Registration#close()} method when no longer needed
52      */
53     default <N extends Notification<N> & DataObject> @NonNull Registration registerListener(final Class<N> type,
54             final Listener<N> listener) {
55         return registerListener(type, listener, MoreExecutors.directExecutor());
56     }
57
58     /**
59      * Registers a {@link Listener} to receive callbacks for {@link Notification}s of a particular type.
60      *
61      * @param listener Composite listener containing listener implementations that will receive notifications
62      * @param executor Executor to use for invoking the listener's methods
63      * @return a {@link Registration} instance that should be used to unregister the listener by invoking the
64      *        {@link Registration#close()} method when no longer needed
65      */
66     @Beta
67     @NonNull Registration registerCompositeListener(CompositeListener listener, Executor executor);
68
69     /**
70      * Registers a {@link Listener} to receive callbacks for {@link Notification}s of a particular type.
71      *
72      * @implSpec
73      *     This method is equivalent to {@code registerCompositeListener(listener, MoreExecutors.directExecutor())},
74      *     i.e. listeners will be invoked on some implementation-specific thread.
75      *
76      * @param listener Composite listener containing listener implementations that will receive notifications
77      * @return a {@link Registration} instance that should be used to unregister the listener by invoking the
78      *        {@link Registration#close()} method when no longer needed
79      */
80     @Beta
81     default @NonNull Registration registerCompositeListener(final CompositeListener listener) {
82         return registerCompositeListener(listener, MoreExecutors.directExecutor());
83     }
84
85     /**
86      * Interface for listeners on global (YANG 1.0) notifications. Such notifications are identified by their generated
87      * interface which extends {@link Notification}. Each listener instance can listen to only a single notification
88      * type.
89      *
90      * @param <N> Notification type
91      */
92     @FunctionalInterface
93     interface Listener<N extends Notification<N> & DataObject> {
94         /**
95          * Process a global notification.
96          *
97          * @param notification Notification body
98          */
99         void onNotification(@NonNull N notification);
100     }
101
102     /**
103      * A composite listener. This class allows registering multiple {@link Listener}s in a single operation. Constituent
104      * listeners are available through {@link #constituents()}.
105      */
106     @Beta
107     record CompositeListener(@NonNull Set<CompositeListener.Component<?>> constituents) {
108         @Beta
109         public record Component<T extends Notification<T> & DataObject>(@NonNull Class<T> type, Listener<T> listener) {
110             public Component {
111                 requireNonNull(type);
112                 requireNonNull(listener);
113                 checkArgument(DataObject.class.isAssignableFrom(type), "%s is not a DataObject", type);
114                 checkArgument(Notification.class.isAssignableFrom(type), "%s is not a Notification", type);
115             }
116         }
117
118         public CompositeListener {
119             requireNonNull(constituents);
120             checkArgument(!constituents.isEmpty(), "Composite listener requires at least one constituent listener");
121         }
122     }
123 }