2 * Copyright (c) 2015 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.mdsal.binding.api;
10 import org.eclipse.jdt.annotation.NonNull;
11 import org.opendaylight.yangtools.concepts.Registration;
12 import org.opendaylight.yangtools.yang.binding.DataObject;
15 * A {@link BindingService} which allows users to register for changes to a subtree.
17 public interface DataTreeChangeService extends BindingService {
19 * Registers a {@link DataTreeChangeListener} to receive notifications when data changes under a given path in the
20 * conceptual data tree.
23 * You are able to register for notifications for any node or subtree which can be represented using
24 * {@link DataTreeIdentifier}.
27 * You are able to register for data change notifications for a subtree or leaf even if it does not exist. You will
28 * receive notification once that node is created.
31 * If there is any pre-existing data in the data tree for the path for which you are registering, you will receive
32 * an initial data change event, which will contain all pre-existing data, marked as created.
35 * This method returns a {@link Registration} object. To "unregister" your listener for changes call the
36 * {@link Registration#close()} method on the returned object.
39 * You <b>MUST</b> explicitly unregister your listener when you no longer want to receive notifications. This is
40 * especially true in OSGi environments, where failure to do so during bundle shutdown can lead to stale listeners
41 * being still registered.
43 * @param treeId Data tree identifier of the subtree which should be watched for changes
44 * @param listener Listener instance which is being registered
45 * @return a Registration object, which may be used to unregister your listener using {@link Registration#close()}
46 * to stop delivery of change events.
48 <T extends DataObject> @NonNull Registration registerTreeChangeListener(
49 @NonNull DataTreeIdentifier<T> treeId, @NonNull DataTreeChangeListener<T> listener);
52 * Registers a {@link DataTreeChangeListener} to receive notifications when data changes under a given path in the
53 * conceptual data tree, with legacy semantics, where no events are delivered if this "cluster node" (further
54 * undefined) is a "leader" (also not explicitly undefined).
57 * The sole known implementation, the Akka-based datastore, defines the difference in terms of RAFT, suspending
58 * even delivery when the RAFT leader is not local. Even when there may be valid use cases for this, RAFT there
59 * is a storage backend whose lifecycle is disconnected from this object.
62 * Aside from the above difference, this method is equivalent to
63 * {@link #registerTreeChangeListener(DataTreeIdentifier, DataTreeChangeListener)}. If you are unable to migrate,
64 * please contact us on <a href="email:discuss@lists.opendaylight.org">the mailing list</a>
66 * @param treeId Data tree identifier of the subtree which should be watched for changes.
67 * @param listener Listener instance which is being registered
68 * @return A {@link Registration} object, which may be used to unregister your listener using
69 * {@link Registration#close()} to stop delivery of change events.
70 * @throws NullPointerException if any of the arguments is {@code null}
72 @Deprecated(since = "13.0.0", forRemoval = true)
73 <T extends DataObject> @NonNull Registration registerLegacyTreeChangeListener(@NonNull DataTreeIdentifier<T> treeId,
74 @NonNull DataTreeChangeListener<T> listener);
77 * Registers a {@link DataTreeChangeListener} to receive notifications when data changes under a given path in the
78 * conceptual data tree.
81 * You are able to register for notifications for any node or subtree which can be represented using
82 * {@link DataTreeIdentifier}.
85 * You are able to register for data change notifications for a subtree or leaf even if it does not exist. You will
86 * receive notification once that node is created.
89 * If there is any pre-existing data in the data tree for the path for which you are registering, you will receive
90 * an initial data change event, which will contain all pre-existing data, marked as created.
93 * This method returns a {@link Registration} object. To "unregister" your listener for changes call the
94 * {@link Registration#close()} method on the returned object.
97 * You <b>MUST</b> explicitly unregister your listener when you no longer want to receive notifications. This is
98 * especially true in OSGi environments, where failure to do so during bundle shutdown can lead to stale listeners
99 * being still registered.
101 * @param treeId Data tree identifier of the subtree which should be watched for changes
102 * @param listener Listener instance which is being registered
103 * @return a Registration object, which may be used to unregister your listener using {@link Registration#close()}
104 * to stop delivery of change events.
105 * @deprecated This interface relies on magic of {@link ClusteredDataTreeChangeListener}. See
106 * {@link #registerLegacyTreeChangeListener(DataTreeIdentifier, DataTreeChangeListener)} for migration
109 @Deprecated(since = "13.0.0", forRemoval = true)
110 default <T extends DataObject> @NonNull Registration registerDataTreeChangeListener(
111 final @NonNull DataTreeIdentifier<T> treeId, final @NonNull DataTreeChangeListener<T> listener) {
112 return listener instanceof ClusteredDataTreeChangeListener ? registerTreeChangeListener(treeId, listener)
113 : registerLegacyTreeChangeListener(treeId, listener);
117 * Registers a {@link ClusteredDataTreeChangeListener} to receive notifications when data changes under a given path
118 * in the conceptual data tree. This is a migration shorthand for
119 * {@code registerDataTreeListener(treeId, listener)}.
121 * @param treeId Data tree identifier of the subtree which should be watched for changes.
122 * @param listener Listener instance which is being registered
123 * @return A {@link Registration} object, which may be used to unregister your listener using
124 * {@link Registration#close()} to stop delivery of change events.
125 * @throws NullPointerException if any of the arguments is {@code null}
126 * @deprecated Use {@link #registerTreeChangeListener(DataTreeIdentifier, DataTreeChangeListener)} instead.
128 @Deprecated(since = "13.0.0", forRemoval = true)
129 default <T extends DataObject> @NonNull Registration registerDataTreeChangeListener(
130 final @NonNull DataTreeIdentifier<T> treeId, final @NonNull ClusteredDataTreeChangeListener<T> listener) {
131 return registerTreeChangeListener(treeId, listener);
135 * Registers a {@link DataTreeChangeListener} to receive notifications when data changes under a given path in the
136 * conceptual data tree.
139 * You are able to register for notifications for any node or subtree which can be represented using
140 * {@link DataTreeIdentifier}.
143 * This method returns a {@link Registration} object. To "unregister" your listener for changes call the
144 * {@link Registration#close()} method on the returned object.
147 * You <b>MUST</b> explicitly unregister your listener when you no longer want to receive notifications. This is
148 * especially true in OSGi environments, where failure to do so during bundle shutdown can lead to stale listeners
149 * being still registered.
151 * @implSpec This method provides {@link DataListenerAdapter} as listener during the registration of
152 * {@link DataTreeChangeListener}. This would allow users to know the last state of data instead of
153 * getting details about what changed in the entire tree.
155 * @param treeId Data tree identifier of the subtree which should be watched for changes.
156 * @param listener Listener instance which is being registered
157 * @return Listener registration object, which may be used to unregister your listener using
158 * {@link Registration#close()} to stop delivery of change events.
160 default <T extends DataObject> @NonNull Registration registerDataListener(
161 final @NonNull DataTreeIdentifier<T> treeId, final @NonNull DataListener<T> listener) {
162 return registerTreeChangeListener(checkNotWildcard(treeId), new DataListenerAdapter<>(listener));
166 * Registers a {@link DataTreeChangeListener} to receive notifications about the last data state when it changes
167 * under a given path in the conceptual data tree.
170 * You are able to register for notifications for any node or subtree which can be represented using
171 * {@link DataTreeIdentifier}.
174 * This method returns a {@link Registration} object. To "unregister" your listener for changes call the
175 * {@link Registration#close()} method on the returned object.
178 * You <b>MUST</b> explicitly unregister your listener when you no longer want to receive notifications. This is
179 * especially true in OSGi environments, where failure to do so during bundle shutdown can lead to stale listeners
180 * being still registered.
182 * @implSpec This method provides {@link DataChangeListenerAdapter} as listener during the registration of
183 * {@link DataTreeChangeListener}, which provides a comparison of before-value and after-value.
185 * @param treeId Data tree identifier of the subtree which should be watched for changes.
186 * @param listener Listener instance which is being registered
187 * @return Listener registration object, which may be used to unregister your listener using
188 * {@link Registration#close()} to stop delivery of change events.
190 default <T extends DataObject> @NonNull Registration registerDataChangeListener(
191 final @NonNull DataTreeIdentifier<T> treeId, final @NonNull DataChangeListener<T> listener) {
192 return registerTreeChangeListener(checkNotWildcard(treeId), new DataChangeListenerAdapter<>(listener));
195 private static <T extends DataObject> @NonNull DataTreeIdentifier<T> checkNotWildcard(
196 final DataTreeIdentifier<T> treeId) {
197 final var instanceIdentifier = treeId.path();
198 if (instanceIdentifier.isWildcarded()) {
199 throw new IllegalArgumentException("Cannot register listener for wildcard " + instanceIdentifier);