package org.opendaylight.mdsal.binding.api;
import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
/**
* A {@link BindingService} which allows users to register for changes to a subtree.
*/
public interface DataTreeChangeService extends BindingService {
/**
- * Registers a {@link DataTreeChangeListener} to receive
- * notifications when data changes under a given path in the conceptual data
- * tree.
+ * Registers a {@link DataTreeChangeListener} to receive notifications when data changes under a given path in the
+ * conceptual data tree.
*
* <p>
- * You are able to register for notifications for any node or subtree
- * which can be represented using {@link DataTreeIdentifier}.
+ * You are able to register for notifications for any node or subtree which can be represented using
+ * {@link DataTreeIdentifier}.
*
* <p>
- * You are able to register for data change notifications for a subtree or leaf
- * even if it does not exist. You will receive notification once that node is
- * created.
+ * You are able to register for data change notifications for a subtree or leaf even if it does not exist. You will
+ * receive notification once that node is created.
*
* <p>
- * If there is any pre-existing data in the data tree for the path for which you are
- * registering, you will receive an initial data change event, which will
- * contain all pre-existing data, marked as created.
+ * If there is any pre-existing data in the data tree for the path for which you are registering, you will receive
+ * an initial data change event, which will contain all pre-existing data, marked as created.
*
* <p>
- * This method returns a {@link ListenerRegistration} object. To
- * "unregister" your listener for changes call the {@link ListenerRegistration#close()}
- * method on the returned object.
+ * This method returns a {@link Registration} object. To "unregister" your listener for changes call the
+ * {@link Registration#close()} method on the returned object.
*
* <p>
* You MUST explicitly unregister your listener when you no longer want to receive
* notifications. This is especially true in OSGi environments, where failure to
* do so during bundle shutdown can lead to stale listeners being still registered.
*
- * @param treeId
- * Data tree identifier of the subtree which should be watched for
- * changes.
- * @param listener
- * Listener instance which is being registered
- * @return Listener registration object, which may be used to unregister
- * your listener using {@link ListenerRegistration#close()} to stop
- * delivery of change events.
+ * @param treeId Data tree identifier of the subtree which should be watched for changes
+ * @param listener Listener instance which is being registered
+ * @return a Registration object, which may be used to unregister your listener using {@link Registration#close()}
+ * to stop delivery of change events.
*/
- <T extends DataObject, L extends DataTreeChangeListener<T>> @NonNull ListenerRegistration<L>
- registerDataTreeChangeListener(@NonNull DataTreeIdentifier<T> treeId, @NonNull L listener);
+ <T extends DataObject> @NonNull Registration registerDataTreeChangeListener(@NonNull DataTreeIdentifier<T> treeId,
+ @NonNull DataTreeChangeListener<T> listener);
/**
* Registers a {@link DataTreeChangeListener} to receive
private static <T extends DataObject> @NonNull DataTreeIdentifier<T> checkNotWildcard(
final DataTreeIdentifier<T> treeId) {
- final @NonNull InstanceIdentifier<T> instanceIdentifier = treeId.getRootIdentifier();
+ final var instanceIdentifier = treeId.getRootIdentifier();
if (instanceIdentifier.isWildcarded()) {
throw new IllegalArgumentException("Cannot register listener for wildcard " + instanceIdentifier);
}
*/
package org.opendaylight.mdsal.binding.api;
-import java.util.EventListener;
import java.util.Optional;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public interface MountPointService extends BindingService {
Optional<MountPoint> getMountPoint(InstanceIdentifier<?> mountPoint);
- <T extends MountPointListener> ListenerRegistration<T> registerListener(InstanceIdentifier<?> path, T listener);
+ @NonNull Registration registerListener(InstanceIdentifier<?> path, MountPointListener listener);
- interface MountPointListener extends EventListener {
+ interface MountPointListener {
- void onMountPointCreated(InstanceIdentifier<?> path);
+ void onMountPointCreated(@NonNull InstanceIdentifier<?> path);
- void onMountPointRemoved(InstanceIdentifier<?> path);
+ void onMountPointRemoved(@NonNull InstanceIdentifier<?> path);
}
}
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
import org.opendaylight.mdsal.dom.api.DOMService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
/**
listener);
}
+ @Override
+ public <T extends DataObject> Registration registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId,
+ final DataTreeChangeListener<T> listener) {
+ if (treeChangeService == null) {
+ throw new UnsupportedOperationException("Underlying data broker does not expose DOMDataTreeChangeService.");
+ }
+ return treeChangeService.registerDataTreeChangeListener(treeId, listener);
+ }
+
private static class Builder extends BindingDOMAdapterBuilder<DataBroker> {
Builder(final AdapterContext adapterContext) {
super(adapterContext);
}
}
- @Override
- public <T extends DataObject, L extends DataTreeChangeListener<T>>
- ListenerRegistration<L> registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId,
- final L listener) {
- if (treeChangeService == null) {
- throw new UnsupportedOperationException("Underlying data broker does not expose DOMDataTreeChangeService.");
- }
- return treeChangeService.registerDataTreeChangeListener(treeId, listener);
- }
}
import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.DataObject;
}
@Override
- public <T extends DataObject, L extends DataTreeChangeListener<T>> ListenerRegistration<L>
- registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId, final L listener) {
+ public <T extends DataObject> Registration registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId,
+ final DataTreeChangeListener<T> listener) {
final var domIdentifier = toDomTreeIdentifier(treeId);
final var storeType = treeId.getDatastoreType();
final var target = treeId.getRootIdentifier().getTargetType();
(ClusteredDataTreeChangeListener<T>) listener, storeType, augment)
: new BindingDOMDataTreeChangeListenerAdapter<>(adapterContext(), listener, storeType, augment);
- final var domReg = getDelegate().registerDataTreeChangeListener(domIdentifier, domListener);
- return new BindingDataTreeChangeListenerRegistration<>(listener, domReg);
+ return getDelegate().registerDataTreeChangeListener(domIdentifier, domListener);
}
@Override
import static java.util.Objects.requireNonNull;
+import com.google.common.annotations.VisibleForTesting;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.api.MountPointService.MountPointListener;
import org.opendaylight.mdsal.dom.api.DOMMountPointListener;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class BindingDOMMountPointListenerAdapter<T extends MountPointListener> implements
- ListenerRegistration<T>, DOMMountPointListener {
+final class BindingDOMMountPointListenerAdapter implements Registration, DOMMountPointListener {
private static final Logger LOG = LoggerFactory.getLogger(BindingDOMMountPointListenerAdapter.class);
- private final @NonNull T listener;
+ @VisibleForTesting
+ final @NonNull MountPointListener listener;
private final AdapterContext adapterContext;
private final Registration registration;
- BindingDOMMountPointListenerAdapter(final T listener, final AdapterContext adapterContext,
+ BindingDOMMountPointListenerAdapter(final MountPointListener listener, final AdapterContext adapterContext,
final DOMMountPointService mountService) {
this.listener = requireNonNull(listener);
this.adapterContext = requireNonNull(adapterContext);
registration = mountService.registerProvisionListener(this);
}
- @Override
- public T getInstance() {
- return listener;
- }
-
@Override
public void close() {
registration.close();
}
return binding;
}
-
-
}
\ No newline at end of file
import org.opendaylight.mdsal.binding.api.MountPointService;
import org.opendaylight.mdsal.dom.api.DOMMountPoint;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
public class BindingDOMMountPointServiceAdapter
extends AbstractBindingLoadingAdapter<DOMMountPointService, DOMMountPoint, BindingMountPointAdapter>
@Override
public Optional<MountPoint> getMountPoint(final InstanceIdentifier<?> mountPoint) {
- YangInstanceIdentifier domPath = currentSerializer().toCachedYangInstanceIdentifier(mountPoint);
- Optional<DOMMountPoint> domMount = getDelegate().getMountPoint(domPath);
- return domMount.map(this::getAdapter);
+ final var domPath = currentSerializer().toCachedYangInstanceIdentifier(mountPoint);
+ return getDelegate().getMountPoint(domPath).map(this::getAdapter);
}
@Override
- public <T extends MountPointListener> ListenerRegistration<T> registerListener(final InstanceIdentifier<?> path,
- final T listener) {
- return new BindingDOMMountPointListenerAdapter<>(listener, adapterContext(), getDelegate());
+ public Registration registerListener(final InstanceIdentifier<?> path, final MountPointListener listener) {
+ return new BindingDOMMountPointListenerAdapter(listener, adapterContext(), getDelegate());
}
@Override
+++ /dev/null
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.dom.adapter;
-
-import static java.util.Objects.requireNonNull;
-
-import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
-import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
-
-class BindingDataTreeChangeListenerRegistration<L extends DataTreeChangeListener<?>>
- extends AbstractListenerRegistration<L> {
- private final Registration domReg;
-
- BindingDataTreeChangeListenerRegistration(final L listener, final Registration domReg) {
- super(listener);
- this.domReg = requireNonNull(domReg);
- }
-
- @Override
- protected void removeRegistration() {
- domReg.close();
- }
-}
import org.opendaylight.mdsal.binding.api.TransactionChain;
import org.opendaylight.mdsal.binding.api.TransactionChainListener;
import org.opendaylight.mdsal.binding.api.WriteTransaction;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
}
@Override
- public <T extends DataObject, L extends DataTreeChangeListener<T>>
- ListenerRegistration<L> registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId,
- final L listener) {
+ public <T extends DataObject> Registration registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId,
+ final DataTreeChangeListener<T> listener) {
return delegate().registerDataTreeChangeListener(treeId, listener);
}
import java.util.Optional;
import org.opendaylight.mdsal.binding.api.MountPoint;
import org.opendaylight.mdsal.binding.api.MountPointService;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
}
@Override
- public <T extends MountPointService.MountPointListener> ListenerRegistration<T> registerListener(
- final InstanceIdentifier<?> path, final T listener) {
+ public Registration registerListener(final InstanceIdentifier<?> path, final MountPointListener listener) {
return delegate().registerListener(path, listener);
}
*/
package org.opendaylight.mdsal.binding.dom.adapter;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.reset;
import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.mdsal.binding.api.MountPointService.MountPointListener;
import org.opendaylight.mdsal.binding.dom.adapter.test.util.BindingBrokerTestFactory;
-import org.opendaylight.mdsal.binding.dom.adapter.test.util.BindingTestContext;
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class BindingDOMMountPointListenerAdapterTest {
-
- private BindingDOMMountPointListenerAdapter<?> bindingDOMMountPointListenerAdapter;
+ private BindingDOMMountPointListenerAdapter adapter;
private AdapterContext codec;
@Mock private MountPointListener listener;
@Before
public void setUp() throws Exception {
- final BindingBrokerTestFactory testFactory = new BindingBrokerTestFactory();
+ final var testFactory = new BindingBrokerTestFactory();
testFactory.setExecutor(MoreExecutors.newDirectExecutorService());
- final BindingTestContext testContext = testFactory.getTestContext();
+ final var testContext = testFactory.getTestContext();
testContext.start();
codec = testContext.getCodec();
doReturn(listenerRegistration).when(mountPointService).registerProvisionListener(any());
- bindingDOMMountPointListenerAdapter =
- new BindingDOMMountPointListenerAdapter<>(listener, codec, mountPointService);
+ adapter = new BindingDOMMountPointListenerAdapter(listener, codec, mountPointService);
}
@Test
public void basicTest() throws Exception {
- assertEquals(listener, bindingDOMMountPointListenerAdapter.getInstance());
- bindingDOMMountPointListenerAdapter.close();
+ assertSame(listener, adapter.listener);
+ adapter.close();
verify(listenerRegistration).close();
}
@Test
public void onMountPointCreatedWithExceptionTest() throws Exception {
reset(listener);
- bindingDOMMountPointListenerAdapter.onMountPointCreated(YangInstanceIdentifier.of());
+ adapter.onMountPointCreated(YangInstanceIdentifier.of());
verifyNoInteractions(listener);
}
@Test
public void onMountPointRemovedWithExceptionTest() throws Exception {
reset(listener);
- bindingDOMMountPointListenerAdapter.onMountPointRemoved(YangInstanceIdentifier.of());
+ adapter.onMountPointRemoved(YangInstanceIdentifier.of());
verifyNoInteractions(listener);
}
}
\ No newline at end of file
*/
package org.opendaylight.mdsal.binding.dom.adapter;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import java.util.Collection;
-import java.util.Map;
import org.junit.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
-import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
import org.opendaylight.mdsal.binding.api.DataTreeModification;
-import org.opendaylight.mdsal.binding.api.WriteTransaction;
import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataBrokerTest;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.listener.rev150825.ListenerTest;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.listener.rev150825.ListenerTestBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.listener.rev150825.listener.test.ListItem;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.listener.rev150825.listener.test.ListItemBuilder;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingMap;
import org.opendaylight.yangtools.yang.common.Uint32;
/**
* Regression test suite for https://bugs.opendaylight.org/show_bug.cgi?id=4513 - Change event is empty when
* Homogeneous composite key is used homogeneous composite key is used.
*/
-public class Bug4513Test extends AbstractDataBrokerTest {
- @SuppressWarnings({ "rawtypes", "unchecked" })
+@ExtendWith(MockitoExtension.class)
+class Bug4513Test extends AbstractDataBrokerTest {
+ @Mock
+ private DataTreeChangeListener<ListItem> listener;
+ @Captor
+ private ArgumentCaptor<Collection<DataTreeModification<ListItem>>> captor;
+
@Test
- public void testDataTreeChangeListener() {
- DataBroker dataBroker = getDataBroker();
+ void testDataTreeChangeListener() {
+ final var dataBroker = getDataBroker();
- DataTreeChangeListener<ListItem> listener = mock(DataTreeChangeListener.class);
- InstanceIdentifier<ListItem> wildCard = InstanceIdentifier.builder(ListenerTest.class)
- .child(ListItem.class).build();
- ListenerRegistration<DataTreeChangeListener<ListItem>> reg = dataBroker.registerDataTreeChangeListener(
+ final var wildCard = InstanceIdentifier.builder(ListenerTest.class).child(ListItem.class).build();
+ final var reg = dataBroker.registerDataTreeChangeListener(
DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, wildCard), listener);
- final ListItem item = writeListItem();
-
- ArgumentCaptor<Collection> captor = ArgumentCaptor.forClass(Collection.class);
+ final var item = writeListItem();
verify(listener, timeout(100)).onDataTreeChanged(captor.capture());
- Collection<DataTreeModification<ListItem>> mods = captor.getValue();
- assertEquals("ListItem", item, mods.iterator().next().getRootNode().getDataAfter());
+ final var mods = captor.getValue();
+ assertEquals(1, mods.size());
+ assertEquals(item, mods.iterator().next().getRootNode().getDataAfter());
}
private ListItem writeListItem() {
- WriteTransaction writeTransaction = getDataBroker().newWriteOnlyTransaction();
- final ListItem item = new ListItemBuilder().setSip("name").setOp(Uint32.valueOf(43)).build();
- ListenerTestBuilder builder = new ListenerTestBuilder().setListItem(Map.of(item.key(), item));
- writeTransaction.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
- ListenerTest.class).build(), builder.build());
+ final var writeTransaction = getDataBroker().newWriteOnlyTransaction();
+ final var item = new ListItemBuilder().setSip("name").setOp(Uint32.valueOf(43)).build();
+ writeTransaction.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(ListenerTest.class),
+ new ListenerTestBuilder().setListItem(BindingMap.of(item)).build());
assertCommit(writeTransaction.commit());
return item;
}
import org.opendaylight.mdsal.binding.api.TransactionChain;
import org.opendaylight.mdsal.binding.api.TransactionChainListener;
import org.opendaylight.mdsal.binding.api.WriteTransaction;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
/**
}
@Override
- public <T extends DataObject, L extends DataTreeChangeListener<T>> ListenerRegistration<L>
- registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId, final L listener) {
+ public <T extends DataObject> Registration registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId,
+ final DataTreeChangeListener<T> listener) {
return delegate().registerDataTreeChangeListener(treeId, listener);
}