Consider AugmentationNodes when direct descendant is not found 44/75944/1
authorMarek Gradzki <mgradzki@cisco.com>
Tue, 14 Aug 2018 08:05:37 +0000 (10:05 +0200)
committerRobert Varga <nite@hq.sk>
Mon, 10 Sep 2018 17:07:03 +0000 (17:07 +0000)
With previous refactors it is quite easy to arrive at a simple
solution to take augmentations into account. This also

This includes a unit test from upstream based on afi-safi-name
with bgp-openconfig-extensions.

JIRA: YANGTOOLS-892
Change-Id: I237ed2c6cbed458a2109a48b468a30650f103a48
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit e4777b6feff804cdcf633c28d4b654b0e885dbd1)

yang/yang-data-codec-xml/src/test/java/org/opendaylight/yangtools/yang/data/codec/xml/Yangtools892Test.java [new file with mode: 0644]
yang/yang-data-codec-xml/src/test/resources/yangtools892/bgp-test-extensions.yang [new file with mode: 0644]
yang/yang-data-codec-xml/src/test/resources/yangtools892/neighbour.xml [new file with mode: 0644]
yang/yang-data-codec-xml/src/test/resources/yangtools892/peer-groups.xml [new file with mode: 0644]
yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp-multiprotocol.yang [new file with mode: 0644]
yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp-types.yang [new file with mode: 0644]
yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp.yang [new file with mode: 0644]
yang/yang-data-codec-xml/src/test/resources/yangtools892/test-network-instance.yang [new file with mode: 0644]
yang/yang-data-codec-xml/src/test/resources/yangtools892/test-policy-types.yang [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/leafref/LeafRefValidation.java

diff --git a/yang/yang-data-codec-xml/src/test/java/org/opendaylight/yangtools/yang/data/codec/xml/Yangtools892Test.java b/yang/yang-data-codec-xml/src/test/java/org/opendaylight/yangtools/yang/data/codec/xml/Yangtools892Test.java
new file mode 100644 (file)
index 0000000..e564b41
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018 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.yangtools.yang.data.codec.xml;
+
+import java.io.InputStream;
+import javax.xml.stream.XMLStreamReader;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.util.xml.UntrustedXML;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.Revision;
+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.stream.NormalizedNodeStreamWriter;
+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.DataTreeConfiguration;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefContext;
+import org.opendaylight.yangtools.yang.data.impl.leafref.LeafRefValidation;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class Yangtools892Test {
+    private static final String TEST_BGP_NAME = "test-bgp";
+    private static final String TEST_BGP_NS = "urn:opendaylight:params:xml:ns:yang:test:bgp";
+    private static final String TEST_BGP_REV = "2018-08-14";
+    private static final QName BGP = QName.create(TEST_BGP_NS, TEST_BGP_REV, "bgp");
+    private static final YangInstanceIdentifier BGP_ID = YangInstanceIdentifier.of(BGP);
+
+    private static final String NETWORK_INSTANCE_NAME = "test-network-instance";
+    private static final String NETWORK_INSTANCE_NS = "urn:opendaylight:params:xml:ns:yang:test:network:instance";
+    private static final String NETWORK_INSTANCE_REV = "2018-08-14";
+    private static final QName NETWORK_INSTANCES =
+        QName.create(NETWORK_INSTANCE_NS, NETWORK_INSTANCE_REV, "network-instances");
+    private static final YangInstanceIdentifier NETWORK_INSTANCES_ID = YangInstanceIdentifier.of(NETWORK_INSTANCES);
+
+    private SchemaContext schemaContext;
+    private LeafRefContext leafRefContext;
+    private DataTree dataTree;
+    private ContainerSchemaNode bgpNode;
+    private ContainerSchemaNode networkInstancesNode;
+
+    @Before
+    public void setup() {
+        schemaContext = YangParserTestUtils.parseYangResourceDirectory("/yangtools892");
+        leafRefContext = LeafRefContext.create(schemaContext);
+        dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION, schemaContext);
+        final Module testBgpModule = schemaContext.findModule(TEST_BGP_NAME, Revision.of(TEST_BGP_REV)).get();
+        bgpNode = (ContainerSchemaNode) testBgpModule.findDataChildByName(BGP).get();
+        final Module networkInstanceModule =
+            schemaContext.findModule(NETWORK_INSTANCE_NAME, Revision.of(NETWORK_INSTANCE_REV)).get();
+        networkInstancesNode = (ContainerSchemaNode) networkInstanceModule.findDataChildByName(NETWORK_INSTANCES).get();
+    }
+
+    @Test
+    public void testWriteBgpNeighbour() throws Exception {
+        final DataTreeModification writeModification = dataTree.takeSnapshot().newModification();
+        final NormalizedNode<?, ?> bgp = readNode("/yangtools892/peer-groups.xml", bgpNode);
+        writeModification.write(BGP_ID, bgp);
+        final NormalizedNode<?, ?> networkInstances = readNode("/yangtools892/neighbour.xml", networkInstancesNode);
+        writeModification.write(NETWORK_INSTANCES_ID, networkInstances);
+
+        writeModification.ready();
+        final DataTreeCandidate writeContributorsCandidate = dataTree.prepare(writeModification);
+        LeafRefValidation.validate(writeContributorsCandidate, leafRefContext);
+        dataTree.commit(writeContributorsCandidate);
+    }
+
+    private NormalizedNode<?, ?> readNode(final String filename, final ContainerSchemaNode node) throws Exception {
+        final InputStream resourceAsStream = Yangtools891Test.class.getResourceAsStream(filename);
+        final XMLStreamReader reader = UntrustedXML.createXMLStreamReader(resourceAsStream);
+        final NormalizedNodeResult result = new NormalizedNodeResult();
+        final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+        final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, node);
+        xmlParser.parse(reader);
+        return result.getResult();
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-data-codec-xml/src/test/resources/yangtools892/bgp-test-extensions.yang b/yang/yang-data-codec-xml/src/test/resources/yangtools892/bgp-test-extensions.yang
new file mode 100644 (file)
index 0000000..42415d9
--- /dev/null
@@ -0,0 +1,27 @@
+module bgp-test-extensions {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:bgp:test:extensions";
+    prefix "odl-oc-ext";
+
+    import test-bgp-types { prefix bgp-types; }
+    import test-network-instance { prefix netinst; }
+    import test-bgp { prefix test-bgp; }
+
+    revision 2018-08-14;
+
+    augment /netinst:network-instances/netinst:network-instance/netinst:protocols/netinst:protocol {
+        uses test-bgp:bgp-top {
+            augment bgp/neighbors/neighbor/afi-safis/afi-safi {
+                uses test-bgp:bgp-neighbor-add-paths_config;
+            }
+
+            augment bgp/neighbors/neighbor/config {
+                description
+                    "Augmentation to allow association of a neighbor with a
+                     peer-group";
+                uses test-bgp:bgp-neighbor-peer-group_config;
+            }
+        }
+    }
+
+}
diff --git a/yang/yang-data-codec-xml/src/test/resources/yangtools892/neighbour.xml b/yang/yang-data-codec-xml/src/test/resources/yangtools892/neighbour.xml
new file mode 100644 (file)
index 0000000..690c41d
--- /dev/null
@@ -0,0 +1,38 @@
+<network-instances xmlns="urn:opendaylight:params:xml:ns:yang:test:network:instance">
+    <network-instance>
+        <name>global-bgp</name>
+        <config>
+            <name>global-bgp</name>
+        </config>
+        <protocols>
+            <protocol>
+                <identifier xmlns:x="urn:opendaylight:params:xml:ns:yang:test:policy:types">x:BGP</identifier>
+                <name>test-bgp-instance</name>
+                <config>
+                    <name>test-bgp-instance</name>
+                    <identifier xmlns:x="urn:opendaylight:params:xml:ns:yang:test:policy:types">x:BGP</identifier>
+                </config>
+                <bgp xmlns="urn:opendaylight:params:xml:ns:yang:bgp:test:extensions">
+                    <neighbors>
+                        <neighbor>
+                            <neighbor-address>10.25.1.9</neighbor-address>
+                            <config>
+                                <peer-group>application-peers</peer-group>
+                            </config>
+                            <afi-safis>
+                                <afi-safi>
+                                    <afi-safi-name xmlns:x="urn:opendaylight:params:xml:ns:yang:test:bgp:types">x:IPV4-UNICAST</afi-safi-name>
+                                    <config>
+                                        <afi-safi-name xmlns:x="urn:opendaylight:params:xml:ns:yang:test:bgp:types">x:IPV4-UNICAST</afi-safi-name>
+                                    </config>
+                                    <receive>true</receive>
+                                    <send-max>0</send-max>
+                                </afi-safi>
+                            </afi-safis>
+                        </neighbor>
+                    </neighbors>
+                </bgp>
+            </protocol>
+        </protocols>
+    </network-instance>
+</network-instances>
\ No newline at end of file
diff --git a/yang/yang-data-codec-xml/src/test/resources/yangtools892/peer-groups.xml b/yang/yang-data-codec-xml/src/test/resources/yangtools892/peer-groups.xml
new file mode 100644 (file)
index 0000000..07c4e55
--- /dev/null
@@ -0,0 +1,7 @@
+<bgp xmlns="urn:opendaylight:params:xml:ns:yang:test:bgp">
+    <peer-groups>
+        <peer-group>
+            <peer-group-name>application-peers</peer-group-name>
+        </peer-group>
+    </peer-groups>
+</bgp>
\ No newline at end of file
diff --git a/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp-multiprotocol.yang b/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp-multiprotocol.yang
new file mode 100644 (file)
index 0000000..41a2749
--- /dev/null
@@ -0,0 +1,33 @@
+module test-bgp-multiprotocol {
+    yang-version "1";
+    namespace "urn:opendaylight:params:xml:ns:yang:test:bgp:multiprotocol";
+    prefix "bgp-mp";
+
+    import test-bgp-types { prefix bgp-types; }
+
+    revision "2018-08-14";
+
+    grouping bgp-afi-safi_config {
+        leaf afi-safi-name {
+            type identityref {
+                base bgp-types:afi-safi-type;
+            }
+        }
+    }
+
+    grouping bgp-common-afi-safi-list {
+        list afi-safi {
+            key "afi-safi-name";
+
+            leaf afi-safi-name {
+                type leafref {
+                    path "../config/afi-safi-name";
+                }
+            }
+
+            container config {
+                uses bgp-afi-safi_config;
+            }
+        }
+    }
+}
diff --git a/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp-types.yang b/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp-types.yang
new file mode 100644 (file)
index 0000000..ae06008
--- /dev/null
@@ -0,0 +1,23 @@
+module test-bgp-types {
+    yang-version "1";
+    namespace "urn:opendaylight:params:xml:ns:yang:test:bgp:types";
+    prefix "bgp-types";
+
+    revision "2018-08-14";
+
+    typedef peer-type {
+        type enumeration {
+            enum INTERNAL {
+            }
+            enum EXTERNAL {
+            }
+        }
+    }
+
+    identity afi-safi-type {
+    }
+
+    identity IPV4-UNICAST {
+        base afi-safi-type;
+    }
+}
diff --git a/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp.yang b/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-bgp.yang
new file mode 100644 (file)
index 0000000..af9f5d1
--- /dev/null
@@ -0,0 +1,111 @@
+module test-bgp {
+    yang-version "1";
+    namespace "urn:opendaylight:params:xml:ns:yang:test:bgp";
+    prefix "bgp";
+
+    import test-bgp-multiprotocol { prefix bgp-mp; }
+    import test-bgp-types { prefix bgp-types; }
+
+    revision "2018-08-14";
+
+    grouping bgp-neighbor_config {
+        leaf peer-type {
+            type bgp-types:peer-type;
+        }
+    }
+
+    grouping bgp-neighbor-add-paths_config {
+        leaf receive {
+            type boolean;
+            default false;
+        }
+
+        leaf send-max {
+            type uint8;
+        }
+    }
+
+    grouping bgp-neighbor-peer-group_config {
+        leaf peer-group {
+            type leafref {
+                path "/bgp/peer-groups/peer-group/peer-group-name";
+            }
+        }
+    }
+
+    grouping bgp-neighbors {
+        list neighbor {
+            key "neighbor-address";
+
+            leaf neighbor-address {
+                type string;
+            }
+
+            uses bgp-neighbor-group;
+        }
+    }
+
+    grouping bgp-peer-group {
+        list peer-group {
+            key "peer-group-name";
+
+            leaf peer-group-name {
+                type string;
+            }
+
+            uses bgp-neighbor-group;
+
+        }
+    }
+
+    grouping bgp-neighbor-group {
+        container config {
+            uses bgp-neighbor_config;
+        }
+
+        container afi-safis {
+            uses bgp-mp:bgp-common-afi-safi-list;
+        }
+    }
+
+    grouping bgp-neighbor-neighbor-address_config {
+        leaf neighbor-address {
+            type string;
+        }
+    }
+
+    grouping bgp-peer-group-peer-group-name_config {
+        leaf peer-group-name {
+            type string;
+        }
+    }
+
+    augment /bgp/neighbors/neighbor/config {
+        uses bgp-neighbor-peer-group_config;
+    }
+
+    augment /bgp/neighbors/neighbor/config {
+        uses bgp-neighbor-neighbor-address_config;
+    }
+
+    augment /bgp/peer-groups/peer-group/config {
+        uses bgp-peer-group-peer-group-name_config;
+    }
+
+    grouping bgp-top {
+        container bgp {
+            presence "Container for BGP protocol hierarchy";
+
+            container neighbors {
+                uses bgp-neighbors;
+            }
+
+            container peer-groups {
+                uses bgp-peer-group;
+            }
+        }
+    }
+
+    uses bgp-top;
+}
+
diff --git a/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-network-instance.yang b/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-network-instance.yang
new file mode 100644 (file)
index 0000000..70947c4
--- /dev/null
@@ -0,0 +1,70 @@
+module test-network-instance {
+    yang-version "1";
+    namespace "urn:opendaylight:params:xml:ns:yang:test:network:instance";
+    prefix netinst;
+
+    import test-policy-types { prefix "pt"; }
+
+    revision 2018-08-14;
+
+    grouping network-instance-top {
+        container network-instances {
+            list network-instance {
+                key "name";
+
+                leaf name {
+                    type leafref {
+                        path "../config/name";
+                    }
+                }
+
+                container config {
+                    uses network-instance-config;
+                }
+
+                container protocols {
+                    list protocol {
+                        key "identifier name";
+
+                        leaf identifier {
+                            type leafref {
+                                path "../config/identifier";
+                            }
+                        }
+
+                        leaf name {
+                            type leafref {
+                                path "../config/name";
+                            }
+                        }
+
+                        container config {
+                            uses protocols-config;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    grouping network-instance-config {
+        leaf name {
+            type string;
+        }
+    }
+
+    grouping protocols-config {
+        leaf identifier {
+            type identityref {
+                base "pt:install-protocol-type";
+            }
+        }
+
+        leaf name {
+            type string;
+        }
+    }
+
+    uses network-instance-top;
+}
+
diff --git a/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-policy-types.yang b/yang/yang-data-codec-xml/src/test/resources/yangtools892/test-policy-types.yang
new file mode 100644 (file)
index 0000000..6aff5b2
--- /dev/null
@@ -0,0 +1,14 @@
+module test-policy-types {
+    yang-version "1";
+    namespace "urn:opendaylight:params:xml:ns:yang:test:policy:types";
+    prefix "ptypes";
+
+    revision "2018-08-14";
+
+    identity install-protocol-type {
+    }
+
+    identity BGP {
+        base install-protocol-type;
+    }
+}
index 5de4f032ba03ab0ea1c9439d51fe1d45232f2297..bf1433203f84f0e8eda2b92ae5778dc851d07bba 100644 (file)
@@ -390,9 +390,13 @@ public final class LeafRefValidation {
             final YangInstanceIdentifier current) {
         final Optional<DataContainerChild<?, ?>> child = parent.getChild(arg);
         if (!child.isPresent()) {
-            for (final DataContainerChild<?, ?> choice : parent.getValue()) {
-                if (choice instanceof ChoiceNode) {
-                    addValues(values, choice, nodePredicates, path, current);
+            // FIXME: YANGTOOLS-901. We have SchemaContext nearby, hence we should be able to cache how to get
+            //        to the leaf with with specified QName, without having to iterate through Choices/Augmentations.
+            //        That perhaps means we should not have QNameWithPredicates, but NodeIdentifierWithPredicates as
+            //        the path specification.
+            for (final DataContainerChild<?, ?> mixin : parent.getValue()) {
+                if (mixin instanceof AugmentationNode || mixin instanceof ChoiceNode) {
+                    addValues(values, mixin, nodePredicates, path, current);
                 }
             }
         } else {