Bug 3224 - Parsing data with choice in case via augmentation results in 75/21975/2
authorJan Hajnar <jhajnar@cisco.com>
Thu, 7 May 2015 15:09:37 +0000 (17:09 +0200)
committerTony Tkacik <ttkacik@cisco.com>
Mon, 8 Jun 2015 07:09:15 +0000 (07:09 +0000)
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 <jhajnar@cisco.com>
(cherry picked from commit a8f512b80e661dac1ff85db6c16c72bfbf7f5891)

12 files changed:
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java
code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang
yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/CompositeNodeDataWithSchema.java
yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/JsonStreamToNormalizedNodeTest.java
yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/TestingNormalizedNodeStructuresCreator.java
yang/yang-data-codec-gson/src/test/resources/complexjson/multiple-choice-augmentation-in-container.json [new file with mode: 0644]
yang/yang-data-codec-gson/src/test/resources/complexjson/yang/complexjson.yang
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/SchemaUtils.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok3.xml [new file with mode: 0644]

index 5e015dbd9c74c8554c8cfc27499a29c0460ed119..b9c44c8bbb491636ba4af3a83bf613b247f6dd54 100644 (file)
@@ -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<D extends DataObject> 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 {
index f223bfef285a843a9446c4aebffa34d7bc7d463f..e7af4ca9bc90df96bffe55586387b3dc78bef2d2 100644 (file)
@@ -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<InstanceIdentifier<?>, 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<YangInstanceIdentifier, NormalizedNode<?, ?>> 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<InstanceIdentifier<?>, DataObject> baResult = registry.fromNormalizedNode(BI_TOP_PATH, topNormalized);
+
+        assertEquals(InstanceIdentifier.create(Top.class), baResult.getKey());
+        assertEquals(top, baResult.getValue());
+    }
 }
index c26559b0714b081b92ea6828a19933c4d0e19d8e..04646fc83879c7ed25bc7259c51b58723c04fc45 100644 (file)
@@ -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;
+                    }
+                }
+            }
+        }
+    }
+
 }
index d34712e4f12909e8dbecdebd87cdc76989d9ac73..3d52fa1580cd639748b029e0faad755cd923f8e6 100644 (file)
@@ -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<DataSchemaNode, QName> QNAME_FUNCTION = new Function<DataSchemaNode, QName>() {
-        @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<AugmentationSchema, Collection<AbstractNodeDataWithSchema>> augmentationToChild : augmentationsToChild.asMap().entrySet()) {
             final Collection<AbstractNodeDataWithSchema> 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<QName> qnames = Collections2.transform(schema.getChildNodes(), QNAME_FUNCTION);
-        return new AugmentationIdentifier(ImmutableSet.copyOf(qnames));
-    }
 }
index 058c2747ad1aaadacd6af8f1baa3e62a946aafcf..4f59b16c03e0eb48cb65d249285fb0d7ff986614 100644 (file)
@@ -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();
index 978b11005156243bb118dcb5cf88761b9d6f5aa6..79011b131c8df379a413aa57aed066e27a967f51 100644 (file)
@@ -68,12 +68,6 @@ public class TestingNormalizedNodeStructuresCreator {
         DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> choc12Builder = Builders.choiceBuilder()
                 .withNodeIdentifier(new NodeIdentifier(QName.create("ns:complex:json", "2014-08-11", "choc12")));
 
-//        DataContainerNodeBuilder<AugmentationIdentifier, AugmentationNode> 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 (file)
index 0000000..bd9a102
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "complexjson:cont1": {
+    "case11-choice-case-container" : {
+      "case11-choice-case-leaf" : "leaf-value"
+    }
+  }
+}
\ No newline at end of file
index b48b952b9de0593a84b70d8dbf3f9aa51f8336df..9d49d083fcea54f15a23e480109835eb72a3279e 100644 (file)
@@ -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;
+                    }
+                }
+            }
+        }
+    }
+
 }
index 755a228c91ff11fcf0ca4bb6264eb26406c28a5a..4896711e7d51805bdf583e174c9e5d4f1c107651 100644 (file)
@@ -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<DataSchemaNode, QName> QNAME_FUNCTION = new Function<DataSchemaNode, QName>() {
+        @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<QName> getChildQNames(final AugmentationSchema schema) {
-        Set<QName> 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<QName> qnames = Collections2.transform(schema.getChildNodes(), QNAME_FUNCTION);
+        return new YangInstanceIdentifier.AugmentationIdentifier(ImmutableSet.copyOf(qnames));
     }
+
 }
index 63962eb91096120c9d083b0ea165937d15202406..830e7a2ebd14cd1450c18bbdf615a9581b7f8bbc 100644 (file)
@@ -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<YangInstanceIdentifier.NodeIdentifier, ContainerNode> b = Builders.containerBuilder();
+        final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> b = containerBuilder();
         b.withNodeIdentifier(getNodeIdentifier("container"));
 
         final CollectionNodeBuilder<MapEntryNode, MapNode> listBuilder = Builders.mapBuilder().withNodeIdentifier(
@@ -146,14 +184,14 @@ public class NormalizedNodeXmlTranslationTest {
 
     private static ContainerNode augmentChoiceHell() {
 
-        final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> b = Builders.containerBuilder();
+        final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> 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()
index c2a57f667c657c1b5979ba0ae1fd08b70c2ff880..5c3e49f797ca6cf4d09d6c121032ab7a413a6a54 100644 (file)
@@ -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 (file)
index 0000000..3a81924
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <case11-choice-case-container>
+        <case11-choice-case-leaf>leaf-value</case11-choice-case-leaf>
+    </case11-choice-case-container>
+</container>
\ No newline at end of file