Fix leaf list modification detection 35/3635/6
authorMaros Marsalek <mmarsale@cisco.com>
Mon, 21 Nov 2016 12:09:23 +0000 (13:09 +0100)
committerMarek Gradzki <mgradzki@cisco.com>
Thu, 24 Nov 2016 07:03:59 +0000 (07:03 +0000)
Change-Id: Ib7bcde546faf8e9bf73d16adaf87c2f8c43ec4aa
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
infra/data-impl/src/main/java/io/fd/honeycomb/data/impl/ModificationDiff.java
infra/data-impl/src/test/java/io/fd/honeycomb/data/impl/ModificationDiffTest.java
infra/data-impl/src/test/resources/test-diff.yang

index f999ba1..86666ba 100644 (file)
@@ -45,6 +45,7 @@ import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -151,7 +152,9 @@ final class ModificationDiff {
         // Check if there are any modified leaves and if so, consider current node as modified
         final Boolean directLeavesModified = emptyPresenceNode
                 || modification.streamChildren()
-                .filter(child -> child.is(LeafSchemaNode.class))
+                // Checking leaf or leaf-lists children for direct modification, which means that leafs of leaf lists
+                // trigger a modification on parent node
+                .filter(child -> child.is(LeafSchemaNode.class) || child.is(LeafListSchemaNode.class))
                 // For some reason, we get modifications on unmodified list keys
                 // and that messes up our modifications collection here, so we need to skip
                 .filter(Modification::isBeforeAndAfterDifferent)
@@ -387,6 +390,10 @@ final class ModificationDiff {
                 if (maybeChild.isPresent()) {
                     found = maybeChild.get();
                 }
+                // Special handling for leaf-list nodes. Basically the same as is for list mixin nodes
+            } else if (schema instanceof LeafListSchemaNode &&
+                    ((SchemaNode) schema).getQName().equals(identifier.getNodeType())) {
+                found = schema;
             }
 
             return checkNotNull(found, "Unable to find child node in: %s identifiable by: %s", schema, identifier);
index 29390e4..664b573 100644 (file)
@@ -28,6 +28,7 @@ import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -41,6 +42,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.TipProducingDataTree
 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
@@ -60,6 +62,10 @@ public class ModificationDiffTest {
     static final QName EMPTY_QNAME = QName.create(TOP_CONTAINER_QNAME, "empty");
     static final QName IN_EMPTY_QNAME = QName.create(TOP_CONTAINER_QNAME, "in-empty");
 
+    static final QName FOR_LEAF_LIST_QNAME = QName.create(TOP_CONTAINER_QNAME, "for-leaf-list");
+    static final QName NESTED_LEAF_LIST_QNAME = QName.create(TOP_CONTAINER_QNAME, "nested-leaf-list");
+
+
     static final QName WITH_CHOICE_CONTAINER_QNAME =
             QName.create("urn:opendaylight:params:xml:ns:yang:test:diff", "2015-01-05", "with-choice");
     static final QName CHOICE_QNAME = QName.create(WITH_CHOICE_CONTAINER_QNAME, "choice");
@@ -87,6 +93,24 @@ public class ModificationDiffTest {
         assertUpdate(modificationDiff.getUpdates().values().iterator().next(), TOP_CONTAINER_ID, null, topContainer);
     }
 
+    @Test
+    public void testLeafList() throws Exception {
+        final TipProducingDataTree dataTree = getDataTree();
+        final DataTreeModification dataTreeModification = getModification(dataTree);
+        final ContainerNode topContainer = getTopContainerWithLeafList("string1", "string2");
+        final YangInstanceIdentifier TOP_CONTAINER_ID = YangInstanceIdentifier.of(TOP_CONTAINER_QNAME);
+        dataTreeModification.write(TOP_CONTAINER_ID, topContainer);
+        final DataTreeCandidateTip prepare = prepareModification(dataTree, dataTreeModification);
+
+        final ModificationDiff modificationDiff = getModificationDiff(prepare);
+
+        assertThat(modificationDiff.getUpdates().size(), is(1));
+        assertThat(modificationDiff.getUpdates().values().size(), is(1));
+        assertUpdate(modificationDiff.getUpdates().values().iterator().next(),
+                TOP_CONTAINER_ID.node(FOR_LEAF_LIST_QNAME), null,
+                topContainer.getChild(new YangInstanceIdentifier.NodeIdentifier(FOR_LEAF_LIST_QNAME)).get());
+    }
+
     @Test
     public void testWritePresenceEmptyContainer() throws Exception {
         final TipProducingDataTree dataTree = getDataTree();
@@ -456,6 +480,26 @@ public class ModificationDiffTest {
                 .build();
     }
 
+    static ContainerNode getTopContainerWithLeafList(final String... stringValue) {
+        final ListNodeBuilder<String, LeafSetEntryNode<String>> leafSetBuilder = Builders.leafSetBuilder();
+        for (final String value : stringValue) {
+            leafSetBuilder.withChild(Builders.<String>leafSetEntryBuilder()
+                    .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue<>(NESTED_LEAF_LIST_QNAME, value))
+                    .withValue(value)
+                    .build());
+        }
+
+        return Builders.containerBuilder()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER_QNAME))
+                .withChild(Builders.containerBuilder()
+                        .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(FOR_LEAF_LIST_QNAME))
+                        .withChild(leafSetBuilder
+                                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LEAF_LIST_QNAME))
+                                .build())
+                        .build())
+                .build();
+    }
+
     static MapNode getNestedList(final String listItemName, final String text) {
         return Builders.mapBuilder()
                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME))
index 5770858..b7a0c7e 100644 (file)
@@ -22,6 +22,12 @@ module test-diff {
             }
         }
 
+        container for-leaf-list {
+            leaf-list nested-leaf-list {
+                type string;
+            }
+        }
+
         list nested-list {
             key "name";