Report non-present initial data in (DOM)DataTreeChangeListener
[mdsal.git] / dom / mdsal-dom-inmemory-datastore / src / main / java / org / opendaylight / mdsal / dom / store / inmemory / InMemoryDOMStoreTreeChangePublisher.java
index 81cc57d0cf0b32c94fd07e6124ca5f555375cf61..9b8e25cd30b48f27a413220a724b68d9ac37c058 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.mdsal.dom.store.inmemory;
 
+import static com.google.common.base.Preconditions.checkState;
+
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
 import java.util.Optional;
@@ -19,6 +21,7 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager;
 import org.opendaylight.yangtools.util.concurrent.QueuedNotificationManager.BatchedInvoker;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
@@ -71,23 +74,40 @@ final class InMemoryDOMStoreTreeChangePublisher extends AbstractDOMStoreTreeChan
     <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerTreeChangeListener(
             final YangInstanceIdentifier treeId, final L listener, final DataTreeSnapshot snapshot) {
         final AbstractDOMDataTreeChangeListenerRegistration<L> reg = registerTreeChangeListener(treeId, listener);
+        final Optional<NormalizedNode<?, ?>> preExistingData = snapshot.readNode(YangInstanceIdentifier.EMPTY);
+        if (!preExistingData.isPresent()) {
+            listener.onInitialData();
+            return reg;
+        }
 
-        final Optional<NormalizedNode<?, ?>> node = snapshot.readNode(YangInstanceIdentifier.EMPTY);
-        if (node.isPresent()) {
-            final DataTreeCandidate candidate = DataTreeCandidates.fromNormalizedNode(
-                    YangInstanceIdentifier.EMPTY, node.get());
+        final NormalizedNode<?, ?> data = preExistingData.get();
+        if (treeId.isEmpty()) {
+            checkState(data instanceof DataContainerNode, "Unexpected root node %s", data);
+            if (((DataContainerNode) data).getValue().isEmpty()) {
+                // If we are listening on root of data tree we still get empty normalized node, root is always present,
+                // we should filter this out separately and notify it by 'onInitialData()' once.
+                // Otherwise, it is just a valid data node with empty value which also should be notified by
+                // "onDataTreeChanged(Collection<DataTreeCandidate>)".
+                listener.onInitialData();
+                return reg;
+            }
+        }
 
-            InMemoryDOMStoreTreeChangePublisher publisher =
-                    new InMemoryDOMStoreTreeChangePublisher(notificationManager);
-            publisher.registerTreeChangeListener(treeId, listener);
-            publisher.publishChange(candidate);
+        final DataTreeCandidate candidate = DataTreeCandidates.fromNormalizedNode(YangInstanceIdentifier.EMPTY, data);
+        final InMemoryDOMStoreTreeChangePublisher publisher = new InMemoryDOMStoreTreeChangePublisher(
+            notificationManager);
+        publisher.registerTreeChangeListener(treeId, listener);
+        if (!publisher.publishChange(candidate)) {
+            // There is no data in the conceptual data tree then
+            // notify with 'onInitialData()'.
+            listener.onInitialData();
         }
 
         return reg;
     }
 
-    synchronized void publishChange(final @NonNull DataTreeCandidate candidate) {
+    synchronized boolean publishChange(final @NonNull DataTreeCandidate candidate) {
         // Runs synchronized with registrationRemoved()
-        processCandidateTree(candidate);
+        return processCandidateTree(candidate);
     }
 }