--- /dev/null
+/*
+ * 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
--- /dev/null
+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;
+ }
+ }
+ }
+
+}
--- /dev/null
+<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
--- /dev/null
+<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
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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;
+}
+
--- /dev/null
+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;
+}
+
--- /dev/null
+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;
+ }
+}
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 {