Bug 1418 - onDataChange notification is not returning any data to 87/9687/4
authorJan Hajnar <jhajnar@cisco.com>
Tue, 5 Aug 2014 10:25:44 +0000 (12:25 +0200)
committerJan Hajnar <jhajnar@cisco.com>
Wed, 6 Aug 2014 06:22:37 +0000 (06:22 +0000)
the getCreatedData and getModifiedData function calls. Data change
notification does not seem to work.

* Changed normalized to binding data change event translation call to
include event listener path. This path is then used to decode leaf or
mixin only augmentation because it can't be injected through children.
* Added verification tests.

Change-Id: Ia9d936f17b30b94fe4878e343cff7babb8d29d0f
Signed-off-by: Jan Hajnar <jhajnar@cisco.com>
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedDataBroker.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java

index 2d81b6022d35af1c70fba4adb269ffc2d8c93dce..e632e6336aaf959808a28f9ecc209432c504b4eb 100644 (file)
@@ -97,6 +97,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
     }
 
     protected Map<InstanceIdentifier<?>, DataObject> toBinding(
+            InstanceIdentifier<?> path,
             final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
         Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
 
@@ -107,6 +108,11 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
                 if (potential.isPresent()) {
                     Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
                     newMap.put(binding.getKey(), binding.getValue());
+                } else if (entry.getKey().getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+                    DataObject bindingDataObject = getCodec().toBinding(path, entry.getValue());
+                    if (bindingDataObject != null) {
+                        newMap.put(path, bindingDataObject);
+                    }
                 }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", entry, e);
@@ -148,7 +154,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         }
     }
 
-    protected Set<InstanceIdentifier<?>> toBinding(
+    protected Set<InstanceIdentifier<?>> toBinding(InstanceIdentifier<?> path,
             final Set<YangInstanceIdentifier> normalized) {
         Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
         for (YangInstanceIdentifier normalizedPath : normalized) {
@@ -157,6 +163,8 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
                 if (potential.isPresent()) {
                     InstanceIdentifier<? extends DataObject> binding = potential.get();
                     hashSet.add(binding);
+                } else if (normalizedPath.getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+                    hashSet.add(path);
                 }
             } catch (DeserializationException e) {
                 LOG.warn("Failed to transform {}, omitting it", normalizedPath, e);
@@ -219,7 +227,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
             if (createdCache == null) {
-                createdCache = Collections.unmodifiableMap(toBinding(domEvent.getCreatedData()));
+                createdCache = Collections.unmodifiableMap(toBinding(path, domEvent.getCreatedData()));
             }
             return createdCache;
         }
@@ -227,7 +235,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
             if (updatedCache == null) {
-                updatedCache = Collections.unmodifiableMap(toBinding(domEvent.getUpdatedData()));
+                updatedCache = Collections.unmodifiableMap(toBinding(path, domEvent.getUpdatedData()));
             }
             return updatedCache;
 
@@ -236,7 +244,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Set<InstanceIdentifier<?>> getRemovedPaths() {
             if (removedCache == null) {
-                removedCache = Collections.unmodifiableSet(toBinding(domEvent.getRemovedPaths()));
+                removedCache = Collections.unmodifiableSet(toBinding(path, domEvent.getRemovedPaths()));
             }
             return removedCache;
         }
@@ -244,7 +252,7 @@ public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBr
         @Override
         public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
             if (originalCache == null) {
-                originalCache = Collections.unmodifiableMap(toBinding(domEvent.getOriginalData()));
+                originalCache = Collections.unmodifiableMap(toBinding(path, domEvent.getOriginalData()));
             }
             return originalCache;
 
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java
new file mode 100644 (file)
index 0000000..6b5c825
--- /dev/null
@@ -0,0 +1,135 @@
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.leafOnlyUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
+
+public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
+    private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
+    private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
+    private static final InstanceIdentifier<TreeLeafOnlyUsesAugment> SIMPLE_AUGMENT =
+            TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeLeafOnlyUsesAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> COMPLEX_AUGMENT =
+            TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeComplexUsesAugment.class);
+    private static final ListViaUsesKey LIST_VIA_USES_KEY =
+            new ListViaUsesKey("list key");
+    private static final ListViaUsesKey LIST_VIA_USES_KEY_MOD =
+            new ListViaUsesKey("list key modified");
+
+    @Test
+    public void leafOnlyAugmentationCreatedTest() {
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getCreatedData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getUpdatedData());
+        assertEmpty(event.getOriginalData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void leafOnlyAugmentationUpdatedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf changed"));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getUpdatedData(), SIMPLE_AUGMENT);
+        assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getCreatedData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void leafOnlyAugmentationDeletedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.delete(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT);
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getRemovedPaths(), SIMPLE_AUGMENT);
+        assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+        assertEmpty(event.getCreatedData());
+        assertEmpty(event.getUpdatedData());
+    }
+
+    @Test
+    public void complexAugmentationCreatedTest() {
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT);
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+        assertEmpty(event.getUpdatedData());
+        assertEmpty(event.getOriginalData());
+        assertEmpty(event.getRemovedPaths());
+    }
+
+    @Test
+    public void complexAugmentationUpdatedTest() {
+        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+        assertCommit(writeTx.submit());
+        TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+                AsyncDataBroker.DataChangeScope.SUBTREE);
+        writeTx = getDataBroker().newWriteOnlyTransaction();
+        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY_MOD));
+        assertCommit(writeTx.submit());
+        assertTrue(listener.hasEvent());
+        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        assertContains(event.getUpdatedData(), COMPLEX_AUGMENT);
+        assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY_MOD));
+        assertContains(event.getRemovedPaths(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+        assertContains(event.getOriginalData(), COMPLEX_AUGMENT);
+        assertContains(event.getOriginalData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+    }
+}
index a0c23aecb4627c4aec4ab1a828d6d97fe695fc60..af7a32924b783ebfafa1f43a2726b9a635387270 100644 (file)
@@ -7,10 +7,11 @@
  */
 package org.opendaylight.controller.md.sal.test.model.util;
 
-import java.util.Arrays;
-
+import com.google.common.collect.ImmutableList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugmentBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
@@ -25,7 +26,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
 
 public class ListsBindingUtils {
 
@@ -79,4 +80,9 @@ public class ListsBindingUtils {
         return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build();
     }
 
+    public static TreeLeafOnlyUsesAugment leafOnlyUsesAugment(String leafFromGroupingValue) {
+
+        return new TreeLeafOnlyUsesAugmentBuilder().setLeafFromGrouping(leafFromGroupingValue).build();
+    }
+
 }