import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private <L extends DOMDataTreeChangeListener> void initialDataChangeEvent(final YangInstanceIdentifier listenerPath, final L listener) {
// FIXME Add support for wildcard listeners
- final Optional<NormalizedNode<?, ?>> preExistingData = dataTree.takeSnapshot().readNode(listenerPath);
+ final Optional<NormalizedNode<?, ?>> preExistingData = dataTree.takeSnapshot()
+ .readNode(YangInstanceIdentifier.create(stripShardPath(listenerPath)));
final DataTreeCandidate initialCandidate;
+
if (preExistingData.isPresent()) {
- initialCandidate = DataTreeCandidates.fromNormalizedNode(listenerPath, preExistingData.get());
+ final NormalizedNode<?, ?> data = preExistingData.get();
+ Preconditions.checkState(data instanceof DataContainerNode,
+ "Expected DataContainer node, but was {}", data.getClass());
+ // if we are listening on root of some shard we still get
+ // empty normalized node, root is always present
+ if (((DataContainerNode) data).getValue().isEmpty()) {
+ initialCandidate = DataTreeCandidates.newDataTreeCandidate(listenerPath,
+ new EmptyDataTreeCandidateNode(data.getIdentifier()));
+ } else {
+ initialCandidate = DataTreeCandidates.fromNormalizedNode(listenerPath,
+ translateRootShardIdentifierToListenerPath(listenerPath, preExistingData.get()));
+ }
} else {
initialCandidate = DataTreeCandidates.newDataTreeCandidate(listenerPath,
new EmptyDataTreeCandidateNode(listenerPath.getLastPathArgument()));
listener.onDataTreeChanged(Collections.singleton(initialCandidate));
}
+ private NormalizedNode<?, ?> translateRootShardIdentifierToListenerPath(final YangInstanceIdentifier listenerPath,
+ final NormalizedNode<?, ?> node) {
+ if (listenerPath.isEmpty()) {
+ return node;
+ }
+
+ final NormalizedNodeBuilder nodeBuilder;
+ if (node instanceof ContainerNode) {
+ nodeBuilder = ImmutableContainerNodeBuilder.create().withValue(((ContainerNode) node).getValue());
+ } else if (node instanceof MapEntryNode) {
+ nodeBuilder = ImmutableMapEntryNodeBuilder.create().withValue(((MapEntryNode) node).getValue());
+ } else {
+ throw new IllegalArgumentException("Expected ContainerNode or MapEntryNode, but was " + node.getClass());
+ }
+ nodeBuilder.withNodeIdentifier(listenerPath.getLastPathArgument());
+ return nodeBuilder.build();
+ }
+
private <L extends DOMDataTreeChangeListener> AbstractDOMDataTreeChangeListenerRegistration<L> setupContextWithoutSubshards(final YangInstanceIdentifier listenerPath, final DOMDataTreeListenerWithSubshards listener) {
LOG.debug("Registering root listener at {}", listenerPath);
final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> node = findNodeFor(listenerPath.getPathArguments());
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
public class AbstractDOMShardTreeChangePublisherTest extends AbstractDOMShardTreeChangePublisher {
final DOMDataTreeChangeListener domDataTreeChangeListener = mock(DOMDataTreeChangeListener.class);
final ListenerRegistration listenerRegistration = mock(ListenerRegistration.class);
final DataTreeSnapshot initialSnapshot = mock(DataTreeSnapshot.class);
- final NormalizedNode<?, ?> initialData = mock(NormalizedNode.class);
+ final DataContainerNode initialData =
+ ImmutableContainerNodeBuilder.create()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create("test")))
+ .build();
doReturn(initialSnapshot).when(DATA_TREE).takeSnapshot();
doReturn(Optional.of(initialData)).when(initialSnapshot).readNode(any());
doNothing().when(domDataTreeChangeListener).onDataTreeChanged(any());
initialChange.forEach(dataTreeCandidate ->
assertEquals(dataTreeCandidate.getRootPath(), YANG_INSTANCE_IDENTIFIER));
initialChange.forEach(dataTreeCandidate ->
- assertSame(dataTreeCandidate.getRootNode().getDataAfter().get(), initialData));
+ assertEquals(dataTreeCandidate.getRootNode().getModificationType(), ModificationType.UNMODIFIED));
}
@Test(expected = UnsupportedOperationException.class)
*/
package org.opendaylight.mdsal.dom.spi.store;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener;
-
import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
* You are able to register for notifications for any node or subtree
* which can be represented using {@link YangInstanceIdentifier}.
* <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.
* <p>
* If there is any pre-existing data in data tree on path for which you are
* registering, you will receive initial data change event, which will
- * contain all pre-existing data, marked as created.
- *
+ * contain all pre-existing data, marked as created. If the data at the supplied
+ * path does not exist, you will also receive initial data change event, which will
+ * contain empty data tree modification, marked as unmodified.
* <p>
* This method returns a {@link ListenerRegistration} object. To
* "unregister" your listener for changes call the {@link ListenerRegistration#close()}
* 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
+ * @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.
+ * your listener using {@link ListenerRegistration#close()} to stop
+ * delivery of change events.
*/
- @Nonnull <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerTreeChangeListener(@Nonnull YangInstanceIdentifier treeId, @Nonnull L listener);
+ @Nonnull
+ <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerTreeChangeListener(@Nonnull YangInstanceIdentifier treeId, @Nonnull L listener);
}