From 3aeb76da594293aa97caa1d7a55f12770ef78033 Mon Sep 17 00:00:00 2001 From: Jan Hajnar Date: Thu, 7 May 2015 17:09:37 +0200 Subject: [PATCH 1/1] Bug 3224 - Parsing data with choice in case via augmentation results in incorrect parsing * added tests for multiple choices from augmentation parsing for json, xml and bindinging aware context * modified json parsing tests * fixed choice augmentation resolution in ChoiceNodeCodecContext and CompositeNodeDataWithSchema * moved findCorrespondingAugment to SchemaUtils since it is useful for multiple Classes * replaced getNodeIdentifierForAugmentation code in SchemaUtils with the one from CompositeNodeDataWithSchema. Change-Id: Ibf57a771b92de14ecb70dcbbe250d7c559066882 Signed-off-by: Jan Hajnar (cherry picked from commit a8f512b80e661dac1ff85db6c16c72bfbf7f5891) --- .../codec/impl/ChoiceNodeCodecContext.java | 9 ++ ...ormalizedNodeSerializeDeserializeTest.java | 99 ++++++++++++++++--- .../opendaylight-yangtools-augment-test.yang | 34 +++++++ .../gson/CompositeNodeDataWithSchema.java | 43 +------- .../gson/JsonStreamToNormalizedNodeTest.java | 56 ++++++++++- ...estingNormalizedNodeStructuresCreator.java | 10 +- ...iple-choice-augmentation-in-container.json | 7 ++ .../complexjson/yang/complexjson.yang | 34 +++++++ .../yang/data/impl/schema/SchemaUtils.java | 37 +++++-- .../NormalizedNodeXmlTranslationTest.java | 58 +++++++++-- .../data/impl/schema/augment_choice_hell.yang | 36 ++++++- .../impl/schema/augment_choice_hell_ok3.xml | 5 + 12 files changed, 343 insertions(+), 85 deletions(-) create mode 100644 yang/yang-data-codec-gson/src/test/resources/complexjson/multiple-choice-augmentation-in-container.json create mode 100644 yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok3.xml diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java index 5e015dbd9c..b9c44c8bbb 100644 --- a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java +++ b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java @@ -26,6 +26,8 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; +import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; @@ -61,6 +63,13 @@ final class ChoiceNodeCodecContext extends DataContainerCo } // Updates collection of YANG instance identifier to case for (final DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) { + if (cazeChild.isAugmenting()) { + final AugmentationSchema augment = SchemaUtils.findCorrespondingAugment(cazeDef.getSchema(), cazeChild); + if (augment != null) { + byYangCaseChildBuilder.put(SchemaUtils.getNodeIdentifierForAugmentation(augment), cazeDef); + continue; + } + } byYangCaseChildBuilder.put(new NodeIdentifier(cazeChild.getQName()), cazeDef); } } else { diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java index f223bfef28..e7af4ca9bc 100644 --- a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java +++ b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java @@ -7,12 +7,33 @@ */ package org.opendaylight.yangtools.binding.data.codec.test; +import static org.junit.Assert.assertEquals; +import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top; +import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList; +import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.*; +import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode; +import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry; +import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder; +import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder; +import com.google.common.collect.Sets; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import javassist.ClassPool; import org.junit.Before; import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TopChoiceAugment1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TopChoiceAugment1Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TopChoiceAugment2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TopChoiceAugment2Builder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.augment.choice1.Case1Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.augment.choice1.case1.augment.choice2.Case11Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.augment.choice1.case1.augment.choice2.case11.Case11ChoiceCaseContainerBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.ChoiceContainer; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.ChoiceContainerBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top; @@ -36,6 +57,9 @@ import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +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.SchemaUtils; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; @@ -44,20 +68,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLe import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top; -import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList; -import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode; -import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry; -import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder; -import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder; - public class NormalizedNodeSerializeDeserializeTest extends AbstractBindingRuntimeTest{ public static final String TOP_LEVEL_LIST_FOO_KEY_VALUE = "foo"; @@ -168,7 +178,7 @@ public class NormalizedNodeSerializeDeserializeTest extends AbstractBindingRunti .withChild(leafNode(SIMPLE_VALUE_QNAME, "simpleValue")) .build(); Map.Entry, DataObject> entry = registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH.node( - new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren)), augmentationNode); + new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren)), augmentationNode); assertEquals(new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build(), entry.getValue()); } @@ -274,4 +284,63 @@ public class NormalizedNodeSerializeDeserializeTest extends AbstractBindingRunti TopLevelList topLevelList = new TopLevelListBuilder().setKey(TOP_LEVEL_LIST_FOO_KEY).setNestedList(nestedLists).build(); assertEquals(topLevelList, entry.getValue()); } + + @Test + public void augmentMultipleChoices() { + QName augmentChoice1QName = QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:augment", + "2014-07-09", "augment-choice1"); + QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2"); + final QName containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container"); + final QName leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf"); + + final YangInstanceIdentifier.AugmentationIdentifier aug1Id = + new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice1QName)); + final YangInstanceIdentifier.AugmentationIdentifier aug2Id = + new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice2QName)); + final YangInstanceIdentifier.NodeIdentifier augmentChoice1Id = + new YangInstanceIdentifier.NodeIdentifier(augmentChoice1QName); + final YangInstanceIdentifier.NodeIdentifier augmentChoice2Id = + new YangInstanceIdentifier.NodeIdentifier(augmentChoice2QName); + final YangInstanceIdentifier.NodeIdentifier containerId = + new YangInstanceIdentifier.NodeIdentifier(containerQName); + + TopBuilder tBuilder = new TopBuilder(); + TopChoiceAugment1Builder tca1Builder = new TopChoiceAugment1Builder(); + Case1Builder c1Builder = new Case1Builder(); + TopChoiceAugment2Builder tca2Builder = new TopChoiceAugment2Builder(); + Case11Builder c11Builder = new Case11Builder(); + Case11ChoiceCaseContainerBuilder cccc1Builder = new Case11ChoiceCaseContainerBuilder(); + cccc1Builder.setCase11ChoiceCaseLeaf("leaf-value"); + c11Builder.setCase11ChoiceCaseContainer(cccc1Builder.build()); + tca2Builder.setAugmentChoice2(c11Builder.build()); + c1Builder.addAugmentation(TopChoiceAugment2.class, tca2Builder.build()); + tca1Builder.setAugmentChoice1(c1Builder.build()); + tBuilder.addAugmentation(TopChoiceAugment1.class, tca1Builder.build()); + final Top top = tBuilder.build(); + + final Map.Entry> biResult = + registry.toNormalizedNode(InstanceIdentifier.create(Top.class), top); + + final NormalizedNode topNormalized = + containerBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME)) + .withChild(augmentationBuilder().withNodeIdentifier(aug1Id) + .withChild(choiceBuilder().withNodeIdentifier(augmentChoice1Id) + .withChild(augmentationBuilder().withNodeIdentifier(aug2Id) + .withChild(choiceBuilder().withNodeIdentifier(augmentChoice2Id) + .withChild(containerBuilder().withNodeIdentifier(containerId) + .withChild(leafNode(leafQName, "leaf-value")) + .build()) + .build()) + .build()) + .build()) + .build()).build(); + + assertEquals(BI_TOP_PATH, biResult.getKey()); + assertEquals(topNormalized, biResult.getValue()); + + final Map.Entry, DataObject> baResult = registry.fromNormalizedNode(BI_TOP_PATH, topNormalized); + + assertEquals(InstanceIdentifier.create(Top.class), baResult.getKey()); + assertEquals(top, baResult.getValue()); + } } diff --git a/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang b/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang index c26559b071..04646fc838 100644 --- a/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang +++ b/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang @@ -146,4 +146,38 @@ module opendaylight-yangtools-augment-test { } } + augment "/test:top" { + ext:augment-identifier top-choice-augment1; + choice augment-choice1 { + case case1 { + container case1-container { + leaf case1-leaf { + type string; + } + } + } + + case case2 { + container case2-container { + leaf case2-leaf { + type string; + } + } + } + } + } + + augment "/test:top/augment-choice1/case1" { + ext:augment-identifier top-choice-augment2; + choice augment-choice2 { + case case11 { + container case11-choice-case-container { + leaf case11-choice-case-leaf { + type string; + } + } + } + } + } + } diff --git a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java index d34712e4f1..3d52fa1580 100644 --- a/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java +++ b/yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java @@ -7,11 +7,8 @@ */ package org.opendaylight.yangtools.yang.data.codec.gson; -import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Collections2; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import java.io.IOException; import java.util.ArrayList; @@ -19,13 +16,10 @@ import java.util.Collection; import java.util.Deque; import java.util.List; import java.util.Map.Entry; -import javax.annotation.Nonnull; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils; import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; -import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; @@ -38,12 +32,6 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; * A node which is composed of multiple simpler nodes. */ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { - private static final Function QNAME_FUNCTION = new Function() { - @Override - public QName apply(@Nonnull final DataSchemaNode input) { - return input.getQName(); - } - }; /** * nodes which were added to schema via augmentation and are present in data input @@ -82,7 +70,7 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { AugmentationSchema augSchema = null; if (choiceCandidate.isAugmenting()) { - augSchema = findCorrespondingAugment(getSchema(), choiceCandidate); + augSchema = SchemaUtils.findCorrespondingAugment(getSchema(), choiceCandidate); } // looking for existing choice @@ -115,7 +103,7 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { AugmentationSchema augSchema = null; if (schema.isAugmenting()) { - augSchema = findCorrespondingAugment(getSchema(), schema); + augSchema = SchemaUtils.findCorrespondingAugment(getSchema(), schema); } if (augSchema != null) { augmentationsToChild.put(augSchema, newChild); @@ -160,7 +148,7 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { } void addCompositeChild(final CompositeNodeDataWithSchema newChild) { - AugmentationSchema augSchema = findCorrespondingAugment(getSchema(), newChild.getSchema()); + AugmentationSchema augSchema = SchemaUtils.findCorrespondingAugment(getSchema(), newChild.getSchema()); if (augSchema != null) { augmentationsToChild.put(augSchema, newChild); } else { @@ -185,22 +173,6 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { return children.size(); } - /** - * Tries to find in {@code parent} which is dealed as augmentation target node with QName as {@code child}. If such - * node is found then it is returned, else null. - */ - AugmentationSchema findCorrespondingAugment(final DataSchemaNode parent, final DataSchemaNode child) { - if (parent instanceof AugmentationTarget && !((parent instanceof ChoiceCaseNode) || (parent instanceof ChoiceSchemaNode))) { - for (AugmentationSchema augmentation : ((AugmentationTarget) parent).getAvailableAugmentations()) { - DataSchemaNode childInAugmentation = augmentation.getDataChildByName(child.getQName()); - if (childInAugmentation != null) { - return augmentation; - } - } - } - return null; - } - @Override public void write(final NormalizedNodeStreamWriter writer) throws IOException { for (AbstractNodeDataWithSchema child : children) { @@ -209,7 +181,7 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { for (Entry> augmentationToChild : augmentationsToChild.asMap().entrySet()) { final Collection childsFromAgumentation = augmentationToChild.getValue(); if (!childsFromAgumentation.isEmpty()) { - writer.startAugmentationNode(toAugmentationIdentifier(augmentationToChild.getKey())); + writer.startAugmentationNode(SchemaUtils.getNodeIdentifierForAugmentation(augmentationToChild.getKey())); for (AbstractNodeDataWithSchema nodeDataWithSchema : childsFromAgumentation) { nodeDataWithSchema.write(writer); @@ -219,9 +191,4 @@ class CompositeNodeDataWithSchema extends AbstractNodeDataWithSchema { } } } - - private static AugmentationIdentifier toAugmentationIdentifier(final AugmentationSchema schema) { - final Collection qnames = Collections2.transform(schema.getChildNodes(), QNAME_FUNCTION); - return new AugmentationIdentifier(ImmutableSet.copyOf(qnames)); - } } diff --git a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java index 058c2747ad..4f59b16c03 100644 --- a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java +++ b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java @@ -13,7 +13,12 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadModules; import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadTextFile; +import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.augmentationBuilder; +import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.choiceBuilder; +import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.containerBuilder; +import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode; +import com.google.common.collect.Sets; import com.google.gson.stream.JsonReader; import java.io.IOException; import java.io.StringReader; @@ -169,7 +174,7 @@ public class JsonStreamToNormalizedNodeTest { try { //second parameter isn't necessary because error will be raised before it is used. verifyTransformationToNormalizedNode(inputJson, null); - fail("Expected exception not raised"); + fail("Expected exception not raised"); } catch (final IllegalStateException e) { final String errorMessage = e.getMessage(); assertTrue(errorMessage.contains("Choose suitable module name for element lf11-namesake:")); @@ -181,9 +186,9 @@ public class JsonStreamToNormalizedNodeTest { @Test public void emptyTypeTest() throws IOException, URISyntaxException { final String inputJson = loadTextFile("/complexjson/type-empty.json"); - final ContainerNode awaitedStructure = Builders.containerBuilder() + final ContainerNode awaitedStructure = containerBuilder() .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CONT_1)) - .addChild(ImmutableNodes.leafNode(EMPTY_LEAF, null)) + .addChild(leafNode(EMPTY_LEAF, null)) .build(); verifyTransformationToNormalizedNode(inputJson, awaitedStructure); @@ -233,6 +238,51 @@ public class JsonStreamToNormalizedNodeTest { assertNotNull(transformedInput); } + @Test + public void multipleChoiceAugmentation() throws IOException, URISyntaxException { + final String inputJson = loadTextFile("/complexjson/multiple-choice-augmentation-in-container.json"); + + final NormalizedNodeResult result = new NormalizedNodeResult(); + final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result); + final SchemaNode parentNode = schemaContext.getDataChildByName("cont1"); + + QName augmentChoice1QName = QName.create(parentNode.getQName(), "augment-choice1"); + QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2"); + final QName containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container"); + final QName leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf"); + + final YangInstanceIdentifier.AugmentationIdentifier aug1Id = + new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice1QName)); + final YangInstanceIdentifier.AugmentationIdentifier aug2Id = + new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice2QName)); + final YangInstanceIdentifier.NodeIdentifier augmentChoice1Id = + new YangInstanceIdentifier.NodeIdentifier(augmentChoice1QName); + final YangInstanceIdentifier.NodeIdentifier augmentChoice2Id = + new YangInstanceIdentifier.NodeIdentifier(augmentChoice2QName); + final YangInstanceIdentifier.NodeIdentifier containerId = + new YangInstanceIdentifier.NodeIdentifier(containerQName); + + final NormalizedNode cont1Normalized = + containerBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(parentNode.getQName())) + .withChild(augmentationBuilder().withNodeIdentifier(aug1Id) + .withChild(choiceBuilder().withNodeIdentifier(augmentChoice1Id) + .withChild(augmentationBuilder().withNodeIdentifier(aug2Id) + .withChild(choiceBuilder().withNodeIdentifier(augmentChoice2Id) + .withChild(containerBuilder().withNodeIdentifier(containerId) + .withChild(leafNode(leafQName, "leaf-value")) + .build()) + .build()) + .build()) + .build()) + .build()).build(); + + final JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext); + jsonParser.parse(new JsonReader(new StringReader(inputJson))); + final NormalizedNode transformedInput = result.getResult(); + assertNotNull(transformedInput); + assertEquals(cont1Normalized, transformedInput); + } + private void verifyTransformationToNormalizedNode(final String inputJson, final NormalizedNode awaitedStructure) { final NormalizedNodeResult result = new NormalizedNodeResult(); diff --git a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/TestingNormalizedNodeStructuresCreator.java b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/TestingNormalizedNodeStructuresCreator.java index 978b110051..79011b131c 100644 --- a/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/TestingNormalizedNodeStructuresCreator.java +++ b/yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/TestingNormalizedNodeStructuresCreator.java @@ -68,12 +68,6 @@ public class TestingNormalizedNodeStructuresCreator { DataContainerNodeBuilder choc12Builder = Builders.choiceBuilder() .withNodeIdentifier(new NodeIdentifier(QName.create("ns:complex:json", "2014-08-11", "choc12"))); -// DataContainerNodeBuilder choc12Augmentation = Builders -// .augmentationBuilder(); -// choc12Augmentation.withNodeIdentifier(new AugmentationIdentifier(Sets.newHashSet(QName.create( -// "ns:complex:json", "2014-08-11", "c12B")))); -// choc12Augmentation.withChild(lf17Node()); - choc12Builder.withChild(lf17Node()); return choc12Builder.build(); } @@ -280,11 +274,11 @@ public class TestingNormalizedNodeStructuresCreator { * @return */ public static NormalizedNode caseNodeAugmentationInChoiceInContainer() { - return cont1Node(choc11Node(lf13Node(), lf15_11Node(), lf15_12Node(), lf15_21Node())); + return cont1Node(choc11Node(augmentC11AWithLf15_11AndLf15_12Node(), lf13Node(), augmentC11AWithLf15_21Node())); } public static NormalizedNode caseNodeExternalAugmentationInChoiceInContainer() { - return cont1Node(choc11Node(lf13Node(), lf15_11Node(), lf15_12Node(), lf15_11NodeExternal(), lf15_12NodeExternal())); + return cont1Node(choc11Node(lf13Node(), augmentC11AWithLf15_11AndLf15_12Node(), externalAugmentC11AWithLf15_11AndLf15_12Node())); } public static NormalizedNode choiceNodeAugmentationInContainer() { diff --git a/yang/yang-data-codec-gson/src/test/resources/complexjson/multiple-choice-augmentation-in-container.json b/yang/yang-data-codec-gson/src/test/resources/complexjson/multiple-choice-augmentation-in-container.json new file mode 100644 index 0000000000..bd9a102c4a --- /dev/null +++ b/yang/yang-data-codec-gson/src/test/resources/complexjson/multiple-choice-augmentation-in-container.json @@ -0,0 +1,7 @@ +{ + "complexjson:cont1": { + "case11-choice-case-container" : { + "case11-choice-case-leaf" : "leaf-value" + } + } +} \ No newline at end of file diff --git a/yang/yang-data-codec-gson/src/test/resources/complexjson/yang/complexjson.yang b/yang/yang-data-codec-gson/src/test/resources/complexjson/yang/complexjson.yang index b48b952b9d..9d49d083fc 100644 --- a/yang/yang-data-codec-gson/src/test/resources/complexjson/yang/complexjson.yang +++ b/yang/yang-data-codec-gson/src/test/resources/complexjson/yang/complexjson.yang @@ -142,4 +142,38 @@ module complexjson { } } + augment "/cont1" { + /*ext:augment-identifier top-choice-augment1;*/ + choice augment-choice1 { + case case1 { + container case1-container { + leaf case1-leaf { + type string; + } + } + } + + case case2 { + container case2-container { + leaf case2-leaf { + type string; + } + } + } + } + } + + augment "/cont1/augment-choice1/case1" { + /*ext:augment-identifier top-choice-augment2;*/ + choice augment-choice2 { + case case11 { + container case11-choice-case-container { + leaf case11-choice-case-leaf { + type string; + } + } + } + } + } + } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/SchemaUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/SchemaUtils.java index 755a228c91..4896711e7d 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/SchemaUtils.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/SchemaUtils.java @@ -11,8 +11,10 @@ import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Map; @@ -32,6 +34,13 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; public final class SchemaUtils { + private static final Function QNAME_FUNCTION = new Function() { + @Override + public QName apply(@Nonnull final DataSchemaNode input) { + return input.getQName(); + } + }; + private SchemaUtils() { throw new UnsupportedOperationException(); } @@ -356,17 +365,25 @@ public final class SchemaUtils { return false; } - public static YangInstanceIdentifier.AugmentationIdentifier getNodeIdentifierForAugmentation(final AugmentationSchema schema) { - return new YangInstanceIdentifier.AugmentationIdentifier(getChildQNames(schema)); - } - - public static Set getChildQNames(final AugmentationSchema schema) { - Set qnames = Sets.newHashSet(); - - for (DataSchemaNode dataSchemaNode : schema.getChildNodes()) { - qnames.add(dataSchemaNode.getQName()); + /** + * Tries to find in {@code parent} which is dealed as augmentation target node with QName as {@code child}. If such + * node is found then it is returned, else null. + */ + public static AugmentationSchema findCorrespondingAugment(final DataSchemaNode parent, final DataSchemaNode child) { + if (parent instanceof AugmentationTarget && !(parent instanceof ChoiceSchemaNode)) { + for (AugmentationSchema augmentation : ((AugmentationTarget) parent).getAvailableAugmentations()) { + DataSchemaNode childInAugmentation = augmentation.getDataChildByName(child.getQName()); + if (childInAugmentation != null) { + return augmentation; + } + } } + return null; + } - return qnames; + public static YangInstanceIdentifier.AugmentationIdentifier getNodeIdentifierForAugmentation(final AugmentationSchema schema) { + final Collection qnames = Collections2.transform(schema.getChildNodes(), QNAME_FUNCTION); + return new YangInstanceIdentifier.AugmentationIdentifier(ImmutableSet.copyOf(qnames)); } + } diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java index 63962eb910..830e7a2ebd 100644 --- a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java +++ b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java @@ -7,6 +7,10 @@ */ package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer; +import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.augmentationBuilder; +import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.choiceBuilder; +import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.containerBuilder; +import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.Collections2; @@ -86,6 +90,7 @@ public class NormalizedNodeXmlTranslationTest { return Arrays.asList(new Object[][]{ {"augment_choice_hell.yang", "augment_choice_hell_ok.xml", augmentChoiceHell()}, {"augment_choice_hell.yang", "augment_choice_hell_ok2.xml", null}, + {"augment_choice_hell.yang", "augment_choice_hell_ok3.xml", augmentChoiceHell2()}, {"test.yang", "simple.xml", null}, {"test.yang", "simple2.xml", null}, // TODO check attributes @@ -103,8 +108,41 @@ public class NormalizedNodeXmlTranslationTest { } } + private static ContainerNode augmentChoiceHell2() { + final YangInstanceIdentifier.NodeIdentifier container = getNodeIdentifier("container"); + QName augmentChoice1QName = QName.create(container.getNodeType(), "augment-choice1"); + QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2"); + final QName containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container"); + final QName leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf"); + + final YangInstanceIdentifier.AugmentationIdentifier aug1Id = + new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice1QName)); + final YangInstanceIdentifier.AugmentationIdentifier aug2Id = + new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice2QName)); + final YangInstanceIdentifier.NodeIdentifier augmentChoice1Id = + new YangInstanceIdentifier.NodeIdentifier(augmentChoice1QName); + final YangInstanceIdentifier.NodeIdentifier augmentChoice2Id = + new YangInstanceIdentifier.NodeIdentifier(augmentChoice2QName); + final YangInstanceIdentifier.NodeIdentifier containerId = + new YangInstanceIdentifier.NodeIdentifier(containerQName); + + + return containerBuilder().withNodeIdentifier(container) + .withChild(augmentationBuilder().withNodeIdentifier(aug1Id) + .withChild(choiceBuilder().withNodeIdentifier(augmentChoice1Id) + .withChild(augmentationBuilder().withNodeIdentifier(aug2Id) + .withChild(choiceBuilder().withNodeIdentifier(augmentChoice2Id) + .withChild(containerBuilder().withNodeIdentifier(containerId) + .withChild(leafNode(leafQName, "leaf-value")) + .build()) + .build()) + .build()) + .build()) + .build()).build(); + } + private static ContainerNode withAttributes() { - final DataContainerNodeBuilder b = Builders.containerBuilder(); + final DataContainerNodeBuilder b = containerBuilder(); b.withNodeIdentifier(getNodeIdentifier("container")); final CollectionNodeBuilder listBuilder = Builders.mapBuilder().withNodeIdentifier( @@ -146,14 +184,14 @@ public class NormalizedNodeXmlTranslationTest { private static ContainerNode augmentChoiceHell() { - final DataContainerNodeBuilder b = Builders.containerBuilder(); + final DataContainerNodeBuilder b = containerBuilder(); b.withNodeIdentifier(getNodeIdentifier("container")); b.withChild( - Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch2")) + choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch2")) .withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c2Leaf")).withValue("2").build()) .withChild( - Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoice")) + choiceBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoice")) .withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoiceCase1Leaf2")).withValue("2").build()) .build() ) @@ -161,26 +199,26 @@ public class NormalizedNodeXmlTranslationTest { ); b.withChild( - Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch3")).withChild( + choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch3")).withChild( Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c3Leaf")).withValue("3").build()) .build()); b.withChild( - Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("augLeaf")).withChild( + augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("augLeaf")).withChild( Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("augLeaf")).withValue("augment").build()) .build()); b.withChild( - Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("ch")).withChild( - Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch")) + augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("ch")).withChild( + choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch")) .withChild( Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c1Leaf")).withValue("1").build()) .withChild( - Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("c1Leaf_AnotherAugment", "deepChoice")) + augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("c1Leaf_AnotherAugment", "deepChoice")) .withChild( Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c1Leaf_AnotherAugment")).withValue("1").build()) .withChild( - Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("deepChoice")) + choiceBuilder().withNodeIdentifier(getNodeIdentifier("deepChoice")) .withChild( Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("deepLeafc1")).withValue("1").build() ).build() diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang index c2a57f667c..5c3e49f797 100644 --- a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang +++ b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang @@ -105,5 +105,39 @@ module test { } } + augment "/container" { + /*ext:augment-identifier top-choice-augment1;*/ + choice augment-choice1 { + case case1 { + container case1-container { + leaf case1-leaf { + type string; + } + } + } + + case case2 { + container case2-container { + leaf case2-leaf { + type string; + } + } + } + } + } + + augment "/container/augment-choice1/case1" { + /*ext:augment-identifier top-choice-augment2;*/ + choice augment-choice2 { + case case11 { + container case11-choice-case-container { + leaf case11-choice-case-leaf { + type string; + } + } + } + } + } + -} \ No newline at end of file +} diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok3.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok3.xml new file mode 100644 index 0000000000..3a819246cb --- /dev/null +++ b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok3.xml @@ -0,0 +1,5 @@ + + + leaf-value + + \ No newline at end of file -- 2.36.6