Migrate users of Builders/ImmutableNodes
[mdsal.git] / binding / mdsal-binding-dom-codec / src / test / java / org / opendaylight / mdsal / binding / dom / codec / impl / NormalizedNodeSerializeDeserializeTest.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.dom.codec.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertThrows;
14 import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.top;
15 import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList;
16
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Map.Entry;
20 import java.util.Set;
21 import org.junit.Test;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TopChoiceAugment1Builder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TopChoiceAugment2Builder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeLeafOnlyAugmentBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.top.choice.augment1.AugmentChoice1;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.top.choice.augment1.augment.choice1.Case1Builder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.top.choice.augment2.augment.choice2.Case11Builder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.top.choice.augment2.augment.choice2.case11.Case11ChoiceCaseContainerBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.ChoiceContainer;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.ChoiceContainerBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top1;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top1Builder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top2;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top2Builder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.TopBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.choice.identifier.ExtendedBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.choice.identifier.extended.ExtendedIdBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.top.level.list.NestedListBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.top.level.list.NestedListKey;
45 import org.opendaylight.yang.gen.v1.urn.test.foo4798.rev160101.Root;
46 import org.opendaylight.yangtools.yang.binding.Augmentation;
47 import org.opendaylight.yangtools.yang.binding.DataObject;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.opendaylight.yangtools.yang.common.QName;
50 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
51 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
52 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
53 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
54 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
55 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
56
57 public class NormalizedNodeSerializeDeserializeTest extends AbstractBindingCodecTest {
58     public static final String TOP_LEVEL_LIST_FOO_KEY_VALUE = "foo";
59     public static final TopLevelListKey TOP_LEVEL_LIST_FOO_KEY = new TopLevelListKey(TOP_LEVEL_LIST_FOO_KEY_VALUE);
60
61     public static final QName TOP_QNAME = Top.QNAME;
62     public static final QName TOP_LEVEL_LIST_QNAME = QName.create(TOP_QNAME, "top-level-list");
63     public static final QName TOP_LEVEL_LIST_KEY_QNAME = QName.create(TOP_QNAME, "name");
64     public static final QName TOP_LEVEL_LEAF_LIST_QNAME = QName.create(TOP_QNAME, "top-level-leaf-list");
65     public static final QName TOP_LEVEL_ORDERED_LEAF_LIST_QNAME = QName.create(TOP_QNAME,
66         "top-level-ordered-leaf-list");
67     public static final QName NESTED_LIST_QNAME = QName.create(TOP_QNAME, "nested-list");
68     public static final QName NESTED_LIST_KEY_QNAME = QName.create(TOP_QNAME, "name");
69     public static final QName CHOICE_CONTAINER_QNAME = ChoiceContainer.QNAME;
70     public static final QName CHOICE_IDENTIFIER_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "identifier");
71     public static final QName CHOICE_IDENTIFIER_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "id");
72     public static final QName EXTENDED_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "extended-id");
73     private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
74
75     private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
76             .builder(Top.class).child(TopLevelList.class, TOP_LEVEL_LIST_FOO_KEY).build();
77
78     public static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.of(TOP_QNAME);
79     public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_PATH = BI_TOP_PATH.node(TOP_LEVEL_LIST_QNAME);
80     public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_FOO_PATH = BI_TOP_LEVEL_LIST_PATH
81             .node(NodeIdentifierWithPredicates.of(TOP_LEVEL_LIST_QNAME,
82                 TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE));
83     public static final YangInstanceIdentifier BI_CHOICE_CONTAINER_PATH = YangInstanceIdentifier.of(
84         CHOICE_CONTAINER_QNAME);
85
86     @Test
87     public void containerToNormalized() {
88         final var entry = codecContext.toNormalizedDataObject(InstanceIdentifier.create(Top.class), top());
89         assertEquals(getEmptyTop(), entry.node());
90     }
91
92     @Test
93     public void containerFromNormalized() {
94         final var entry = codecContext.fromNormalizedNode(BI_TOP_PATH, getEmptyTop());
95         assertEquals(top(), entry.getValue());
96     }
97
98     private static ContainerNode getEmptyTop() {
99         return ImmutableNodes.newContainerBuilder().withNodeIdentifier(new NodeIdentifier(TOP_QNAME)).build();
100     }
101
102     private static final QName AGUMENT_STRING_Q = QName.create(TOP_QNAME, "augmented-string");
103     private static final String AUGMENT_STRING_VALUE = "testingEquals";
104     private static final QName AUGMENT_INT_Q = QName.create(TOP_QNAME, "augmented-int");
105     private static final int AUGMENT_INT_VALUE = 44;
106
107     @Test
108     public void equalsWithAugment() {
109         final ContainerNode topNormalizedWithAugments =
110             getNormalizedTopWithChildren(ImmutableNodes.leafNode(AGUMENT_STRING_Q, AUGMENT_STRING_VALUE));
111         final ContainerNode topNormalized = getEmptyTop();
112
113         final var entry = codecContext.fromNormalizedNode(BI_TOP_PATH, topNormalized);
114         final var entryWithAugments = codecContext.fromNormalizedNode(BI_TOP_PATH, topNormalizedWithAugments);
115
116         // Equals on other with no augmentation should be false
117         assertNotEquals(top(), entryWithAugments.getValue());
118         // Equals on other(reversed) with no augmentation should be false
119         assertNotEquals(entryWithAugments.getValue(), top());
120         // Equals on other(lazy) with no augmentation should be false
121         assertNotEquals(entry.getValue(), entryWithAugments.getValue());
122         // Equals on other(lazy, reversed) with no augmentation should be false
123         assertNotEquals(entryWithAugments.getValue(), entry.getValue());
124
125         final Top topWithAugments = topWithAugments(
126             Map.of(Top1.class, new Top1Builder().setAugmentedString(AUGMENT_STRING_VALUE).build()));
127         // Equals other with same augment should be true
128         assertEquals(topWithAugments, entryWithAugments.getValue());
129         // Equals other with same augment should be true
130         assertEquals(entryWithAugments.getValue(), topWithAugments);
131         // Equals on self should be true
132         assertEquals(entryWithAugments.getValue(), entryWithAugments.getValue());
133
134         final Top topWithAugmentsDiffValue = topWithAugments(
135             Map.of(Top1.class, new Top1Builder().setAugmentedString("differentValue").build()));
136         assertNotEquals(topWithAugmentsDiffValue, entryWithAugments.getValue());
137         assertNotEquals(entryWithAugments.getValue(), topWithAugmentsDiffValue);
138     }
139
140     @Test
141     public void equalsWithMultipleAugments() {
142         final ContainerNode topNormalizedWithAugments = getNormalizedTopWithChildren(
143             ImmutableNodes.leafNode(AGUMENT_STRING_Q, AUGMENT_STRING_VALUE),
144             ImmutableNodes.leafNode(AUGMENT_INT_Q, AUGMENT_INT_VALUE));
145         final var entryWithAugments = codecContext.fromNormalizedNode(BI_TOP_PATH, topNormalizedWithAugments);
146         Top topWithAugments = topWithAugments(Map.of(
147             Top1.class, new Top1Builder().setAugmentedString(AUGMENT_STRING_VALUE).build(),
148             Top2.class, new Top2Builder().setAugmentedInt(AUGMENT_INT_VALUE).build()));
149
150         assertEquals(topWithAugments, entryWithAugments.getValue());
151         assertEquals(entryWithAugments.getValue(), topWithAugments);
152
153         topWithAugments = topWithAugments(Map.of(
154             Top1.class, new Top1Builder().setAugmentedString(AUGMENT_STRING_VALUE).build(),
155             Top2.class, new Top2Builder().setAugmentedInt(999).build()));
156
157         assertNotEquals(topWithAugments, entryWithAugments.getValue());
158         assertNotEquals(entryWithAugments.getValue(), topWithAugments);
159     }
160
161     private static ContainerNode getNormalizedTopWithChildren(final DataContainerChild... children) {
162         final var builder = ImmutableNodes.newContainerBuilder().withNodeIdentifier(new NodeIdentifier(TOP_QNAME));
163         for (var child : children) {
164             builder.withChild(child);
165         }
166         return builder
167             .withChild(ImmutableNodes.newSystemMapBuilder()
168                 .withNodeIdentifier(new NodeIdentifier(TOP_LEVEL_LIST_QNAME))
169                 .build())
170             .build();
171     }
172
173     private static Top topWithAugments(
174             final Map<Class<? extends Augmentation<Top>>, ? extends Augmentation<Top>> augments) {
175         final TopBuilder topBuilder = new TopBuilder();
176         for (Augmentation<Top> augment : augments.values()) {
177             topBuilder.addAugmentation(augment);
178         }
179         return topBuilder.build();
180     }
181
182     @Test
183     public void listWithKeysToNormalized() {
184         final var entry = codecContext.toNormalizedDataObject(BA_TOP_LEVEL_LIST, topLevelList(TOP_LEVEL_LIST_FOO_KEY));
185         assertEquals(ImmutableNodes.newMapEntryBuilder()
186             .withNodeIdentifier(NodeIdentifierWithPredicates.of(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME,
187                 TOP_LEVEL_LIST_FOO_KEY_VALUE))
188             .withChild(ImmutableNodes.leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
189             .build(),
190             entry.node());
191     }
192
193     @Test
194     public void listWithKeysFromNormalized() {
195         final var entry = codecContext.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH,
196             ImmutableNodes.newMapEntryBuilder()
197                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME,
198                     TOP_LEVEL_LIST_FOO_KEY_VALUE))
199                 .withChild(ImmutableNodes.leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
200                 .build());
201         assertEquals(topLevelList(TOP_LEVEL_LIST_FOO_KEY), entry.getValue());
202     }
203
204     @Test
205     public void leafOnlyAugmentationToNormalized() {
206         final var entry = codecContext.toNormalizedDataObject(BA_TOP_LEVEL_LIST,
207             topLevelList(TOP_LEVEL_LIST_FOO_KEY,
208                 new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build()));
209         assertEquals(ImmutableNodes.newMapEntryBuilder()
210             .withNodeIdentifier(NodeIdentifierWithPredicates.of(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME,
211                 TOP_LEVEL_LIST_FOO_KEY_VALUE))
212             .withChild(ImmutableNodes.leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
213             .withChild(ImmutableNodes.leafNode(SIMPLE_VALUE_QNAME, "simpleValue")) // augmentation child
214             .build(),
215             entry.node());
216     }
217
218     @Test
219     public void leafOnlyAugmentationFromNormalized() {
220         final var entry = codecContext.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH,
221             ImmutableNodes.newMapEntryBuilder()
222                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME,
223                     TOP_LEVEL_LIST_FOO_KEY_VALUE))
224                 .withChild(ImmutableNodes.leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
225                 .withChild(ImmutableNodes.leafNode(SIMPLE_VALUE_QNAME, "simpleValue")) // augmentation child
226                 .build());
227         assertEquals(
228             topLevelList(TOP_LEVEL_LIST_FOO_KEY,
229                 new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build()),
230             entry.getValue());
231     }
232
233     @Test
234     public void orderedleafListToNormalized() {
235         final var entry = codecContext.toNormalizedDataObject(InstanceIdentifier.create(Top.class),
236             new TopBuilder().setTopLevelOrderedLeafList(List.of("foo")).build());
237         assertEquals(ImmutableNodes.newContainerBuilder()
238             .withNodeIdentifier(new NodeIdentifier(TOP_QNAME))
239             .withChild(ImmutableNodes.newUserLeafSetBuilder()
240                 .withNodeIdentifier(new NodeIdentifier(TOP_LEVEL_ORDERED_LEAF_LIST_QNAME))
241                 .withChild(ImmutableNodes.leafSetEntry(TOP_LEVEL_ORDERED_LEAF_LIST_QNAME, "foo"))
242                 .build())
243             .build(),
244             entry.node());
245     }
246
247     @Test
248     public void leafListToNormalized() {
249         final var entry = codecContext.toNormalizedDataObject(
250             InstanceIdentifier.create(Top.class), new TopBuilder().setTopLevelLeafList(Set.of("foo")).build());
251         assertEquals(ImmutableNodes.newContainerBuilder()
252             .withNodeIdentifier(new NodeIdentifier(TOP_QNAME))
253             .withChild(ImmutableNodes.newSystemLeafSetBuilder()
254                 .withNodeIdentifier(new NodeIdentifier(TOP_LEVEL_LEAF_LIST_QNAME))
255                 .withChild(ImmutableNodes.leafSetEntry(TOP_LEVEL_LEAF_LIST_QNAME, "foo"))
256                 .build())
257             .build(),
258             entry.node());
259     }
260
261     @Test
262     public void leafListFromNormalized() {
263         final var entry = codecContext.fromNormalizedNode(BI_TOP_PATH, ImmutableNodes.newContainerBuilder()
264             .withNodeIdentifier(new NodeIdentifier(TOP_QNAME))
265             .withChild(ImmutableNodes.newSystemLeafSetBuilder()
266                 .withNodeIdentifier(new NodeIdentifier(TOP_LEVEL_LEAF_LIST_QNAME))
267                 .withChild(ImmutableNodes.leafSetEntry(TOP_LEVEL_LEAF_LIST_QNAME, "foo"))
268                 .build())
269             .build());
270         assertEquals(new TopBuilder().setTopLevelLeafList(Set.of("foo")).build(), entry.getValue());
271     }
272
273     @Test
274     public void orderedLeafListFromNormalized() {
275         final var entry = codecContext.fromNormalizedNode(BI_TOP_PATH, ImmutableNodes.newContainerBuilder()
276             .withNodeIdentifier(new NodeIdentifier(TOP_QNAME))
277             .withChild(ImmutableNodes.newUserLeafSetBuilder()
278                 .withNodeIdentifier(new NodeIdentifier(TOP_LEVEL_ORDERED_LEAF_LIST_QNAME))
279                 .withChild(ImmutableNodes.leafSetEntry(TOP_LEVEL_ORDERED_LEAF_LIST_QNAME, "foo"))
280                 .build())
281             .build());
282         assertEquals(new TopBuilder().setTopLevelOrderedLeafList(List.of("foo")).build(), entry.getValue());
283     }
284
285     @Test
286     public void choiceToNormalized() {
287         final var entry = codecContext.toNormalizedDataObject(InstanceIdentifier.create(ChoiceContainer.class),
288             new ChoiceContainerBuilder()
289                 .setIdentifier(new ExtendedBuilder()
290                     .setExtendedId(new ExtendedIdBuilder().setId("identifier_value").build())
291                     .build())
292                 .build());
293         assertEquals(ImmutableNodes.newContainerBuilder()
294             .withNodeIdentifier(new NodeIdentifier(CHOICE_CONTAINER_QNAME))
295             .withChild(ImmutableNodes.newChoiceBuilder()
296                 .withNodeIdentifier(new NodeIdentifier(CHOICE_IDENTIFIER_QNAME))
297                 .withChild(ImmutableNodes.newContainerBuilder()
298                     .withNodeIdentifier(new NodeIdentifier(EXTENDED_ID_QNAME))
299                     .withChild(ImmutableNodes.leafNode(CHOICE_IDENTIFIER_ID_QNAME, "identifier_value"))
300                     .build())
301                 .build())
302             .build(),
303             entry.node());
304     }
305
306     @Test
307     public void test4798() {
308         final QName containerIdentifierQname4798 = Root.QNAME;
309         final QName choiceIdentifierQname4798 = QName.create(containerIdentifierQname4798, "bug4798-choice");
310         final QName nestedListQname4798 = QName.create(containerIdentifierQname4798, "list-in-case");
311         final QName nestedListKeyQname4798 = QName.create(containerIdentifierQname4798, "test-leaf");
312         final QName nestedContainerValidQname = QName.create(containerIdentifierQname4798, "case-b-container");
313         final QName nestedContainerOuterQname = QName.create(containerIdentifierQname4798, "outer-container");
314         final QName nestedContainerLeafOuterQname = QName.create(containerIdentifierQname4798,
315                 "leaf-in-outer-container");
316
317         final YangInstanceIdentifier yangInstanceIdentifierOuter = YangInstanceIdentifier.of(
318             containerIdentifierQname4798);
319         final ContainerNode containerNodeOuter = ImmutableNodes.newContainerBuilder()
320             .withNodeIdentifier(new NodeIdentifier(containerIdentifierQname4798))
321             .withChild(ImmutableNodes.newContainerBuilder()
322                 .withNodeIdentifier(new NodeIdentifier(nestedContainerOuterQname))
323                 .withChild(ImmutableNodes.leafNode(nestedContainerLeafOuterQname, "bar"))
324                 .build())
325             .build();
326         final Entry<InstanceIdentifier<?>, DataObject> entryContainer = codecContext.fromNormalizedNode(
327             yangInstanceIdentifierOuter, containerNodeOuter);
328         assertNotNull(entryContainer.getValue());
329         assertNotNull(entryContainer.getKey());
330
331         final NodeIdentifierWithPredicates nodeIdentifierWithPredicates4798 =
332                 NodeIdentifierWithPredicates.of(nestedListQname4798, nestedListKeyQname4798, "foo");
333         final YangInstanceIdentifier yangInstanceIdentifier4798 = YangInstanceIdentifier.of(
334             containerIdentifierQname4798)
335                 .node(choiceIdentifierQname4798)
336                 .node(nestedListQname4798)
337                 .node(nodeIdentifierWithPredicates4798);
338
339         final YangInstanceIdentifier yangInstanceIdentifierValid = YangInstanceIdentifier.of(
340             containerIdentifierQname4798)
341                 .node(choiceIdentifierQname4798)
342                 .node(nestedContainerValidQname)
343                 .node(nestedListQname4798)
344                 .node(nodeIdentifierWithPredicates4798);
345         final ContainerNode containerNodeValid = ImmutableNodes.newContainerBuilder()
346             .withNodeIdentifier(new NodeIdentifier(containerIdentifierQname4798))
347             .withChild(ImmutableNodes.newChoiceBuilder()
348                 .withNodeIdentifier(new NodeIdentifier(choiceIdentifierQname4798))
349                 .withChild(ImmutableNodes.newContainerBuilder()
350                     .withNodeIdentifier(new NodeIdentifier(nestedContainerValidQname))
351                     .withChild(ImmutableNodes.newSystemMapBuilder()
352                         .withNodeIdentifier(new NodeIdentifier(nestedListQname4798))
353                         .withChild(ImmutableNodes.newMapEntryBuilder()
354                             .withNodeIdentifier(
355                                 NodeIdentifierWithPredicates.of(nestedListQname4798, nestedListKeyQname4798, "foo"))
356                             .withChild(ImmutableNodes.leafNode(nestedListKeyQname4798, "foo"))
357                             .build())
358                         .withChild(ImmutableNodes.newMapEntryBuilder()
359                             .withNodeIdentifier(
360                                 NodeIdentifierWithPredicates.of(nestedListQname4798, nestedListKeyQname4798, "bar"))
361                             .withChild(ImmutableNodes.leafNode(nestedListKeyQname4798, "bar"))
362                             .build())
363                         .build())
364                     .build())
365                 .build())
366             .build();
367
368         var msg = assertThrows(IllegalArgumentException.class,
369             () -> codecContext.fromNormalizedNode(yangInstanceIdentifierValid, containerNodeValid))
370             .getMessage();
371         assertEquals("Expecting either a MapEntryNode or an UnkeyedListEntryNode, not ContainerNode", msg);
372
373         final ContainerNode containerNode4798 = ImmutableNodes.newContainerBuilder()
374             .withNodeIdentifier(new NodeIdentifier(containerIdentifierQname4798))
375             .withChild(ImmutableNodes.newChoiceBuilder()
376                 .withNodeIdentifier(new NodeIdentifier(choiceIdentifierQname4798))
377                 .withChild(ImmutableNodes.newSystemMapBuilder()
378                     .withNodeIdentifier(new NodeIdentifier(nestedListQname4798))
379                     .withChild(ImmutableNodes.newMapEntryBuilder()
380                         .withNodeIdentifier(
381                             NodeIdentifierWithPredicates.of(nestedListQname4798, nestedListKeyQname4798, "foo"))
382                         .withChild(ImmutableNodes.leafNode(nestedListKeyQname4798, "foo"))
383                         .build())
384                     .withChild(ImmutableNodes.newMapEntryBuilder()
385                         .withNodeIdentifier(
386                             NodeIdentifierWithPredicates.of(nestedListQname4798, nestedListKeyQname4798, "bar"))
387                         .withChild(ImmutableNodes.leafNode(nestedListKeyQname4798, "bar"))
388                         .build())
389                     .build())
390                 .build())
391             .build();
392
393         msg = assertThrows(IllegalArgumentException.class,
394             () -> codecContext.fromNormalizedNode(yangInstanceIdentifier4798, containerNode4798))
395             .getMessage();
396         assertEquals("Expecting either a MapEntryNode or an UnkeyedListEntryNode, not ContainerNode", msg);
397     }
398
399     @Test
400     public void choiceFromNormalized() {
401         final ContainerNode choiceContainerBI = ImmutableNodes.newContainerBuilder()
402             .withNodeIdentifier(new NodeIdentifier(CHOICE_CONTAINER_QNAME))
403             .withChild(ImmutableNodes.newChoiceBuilder()
404                 .withNodeIdentifier(new NodeIdentifier(CHOICE_IDENTIFIER_QNAME))
405                 .withChild(ImmutableNodes.newContainerBuilder()
406                     .withNodeIdentifier(new NodeIdentifier(EXTENDED_ID_QNAME))
407                     .withChild(ImmutableNodes.leafNode(CHOICE_IDENTIFIER_ID_QNAME, "identifier_value"))
408                     .build())
409                 .build())
410             .build();
411         final Entry<InstanceIdentifier<?>, DataObject> entry = codecContext.fromNormalizedNode(BI_CHOICE_CONTAINER_PATH,
412             choiceContainerBI);
413         final ChoiceContainer choiceContainerBA = new ChoiceContainerBuilder().setIdentifier(new ExtendedBuilder()
414             .setExtendedId(new ExtendedIdBuilder().setId("identifier_value").build()).build()).build();
415         assertEquals(choiceContainerBA, entry.getValue());
416     }
417
418     @Test
419     public void orderedLisToNormalized() {
420         final var entry = codecContext.toNormalizedDataObject(BA_TOP_LEVEL_LIST, new TopLevelListBuilder()
421             .withKey(TOP_LEVEL_LIST_FOO_KEY)
422             .setNestedList(List.of(
423                 new NestedListBuilder().withKey(new NestedListKey("foo")).build(),
424                 new NestedListBuilder().withKey(new NestedListKey("bar")).build()))
425             .build());
426         assertEquals(ImmutableNodes.newMapEntryBuilder()
427             .withNodeIdentifier(NodeIdentifierWithPredicates.of(TOP_LEVEL_LIST_QNAME,
428                 TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
429             .withChild(ImmutableNodes.leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
430             .withChild(ImmutableNodes.newUserMapBuilder()
431                 .withNodeIdentifier(new NodeIdentifier(NESTED_LIST_QNAME))
432                 .withChild(ImmutableNodes.newMapEntryBuilder()
433                     .withNodeIdentifier(
434                         NodeIdentifierWithPredicates.of(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "foo"))
435                     .withChild(ImmutableNodes.leafNode(NESTED_LIST_KEY_QNAME, "foo"))
436                     .build())
437                 .withChild(ImmutableNodes.newMapEntryBuilder()
438                     .withNodeIdentifier(
439                         NodeIdentifierWithPredicates.of(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "bar"))
440                     .withChild(ImmutableNodes.leafNode(NESTED_LIST_KEY_QNAME, "bar"))
441                     .build())
442                 .build())
443             .build(),
444             entry.node());
445     }
446
447     @Test
448     public void orderedLisFromNormalized() {
449         final var entry = codecContext.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH,
450             ImmutableNodes.newMapEntryBuilder()
451                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(
452                     TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
453                 .withChild(ImmutableNodes.leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
454                 .withChild(ImmutableNodes.newUserMapBuilder()
455                     .withNodeIdentifier(new NodeIdentifier(NESTED_LIST_QNAME))
456                     .withChild(ImmutableNodes.newMapEntryBuilder()
457                         .withNodeIdentifier(
458                             NodeIdentifierWithPredicates.of(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "foo"))
459                         .withChild(ImmutableNodes.leafNode(NESTED_LIST_KEY_QNAME, "foo"))
460                         .build())
461                     .withChild(ImmutableNodes.newMapEntryBuilder()
462                         .withNodeIdentifier(
463                             NodeIdentifierWithPredicates.of(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "bar"))
464                         .withChild(ImmutableNodes.leafNode(NESTED_LIST_KEY_QNAME, "bar"))
465                         .build())
466                     .build())
467                 .build());
468         assertEquals(new TopLevelListBuilder()
469             .withKey(TOP_LEVEL_LIST_FOO_KEY)
470             .setNestedList(List.of(
471                 new NestedListBuilder().withKey(new NestedListKey("foo")).build(),
472                 new NestedListBuilder().withKey(new NestedListKey("bar")).build()))
473             .build(),
474             entry.getValue());
475     }
476
477     @Test
478     public void augmentMultipleChoices() {
479         final QName augmentChoice1QName = AugmentChoice1.QNAME;
480         final QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2");
481         final QName containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container");
482         final QName leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf");
483
484         final NodeIdentifier augmentChoice1Id = new NodeIdentifier(augmentChoice1QName);
485         final NodeIdentifier augmentChoice2Id = new NodeIdentifier(augmentChoice2QName);
486         final NodeIdentifier containerId = new NodeIdentifier(containerQName);
487
488         final Top top = new TopBuilder().addAugmentation(
489             // top is augmented with choice1 having case1
490             new TopChoiceAugment1Builder().setAugmentChoice1(
491                 new Case1Builder().addAugmentation(
492                     // case1 is augmented with choice2 having case11 (with container having leaf)
493                     new TopChoiceAugment2Builder().setAugmentChoice2(
494                         new Case11Builder().setCase11ChoiceCaseContainer(
495                                 new Case11ChoiceCaseContainerBuilder()
496                                         .setCase11ChoiceCaseLeaf("leaf-value").build()
497                         ).build()
498                     ).build()
499                 ).build()
500             ).build()
501         ).build();
502
503         final var biResult = codecContext.toNormalizedDataObject(InstanceIdentifier.create(Top.class), top);
504
505         final var topNormalized = ImmutableNodes.newContainerBuilder()
506             .withNodeIdentifier(new NodeIdentifier(TOP_QNAME))
507             .withChild(ImmutableNodes.newChoiceBuilder()
508                 .withNodeIdentifier(augmentChoice1Id)
509                 .withChild(ImmutableNodes.newChoiceBuilder()
510                     .withNodeIdentifier(augmentChoice2Id)
511                     .withChild(ImmutableNodes.newContainerBuilder()
512                         .withNodeIdentifier(containerId)
513                         .withChild(ImmutableNodes.leafNode(leafQName, "leaf-value"))
514                         .build())
515                     .build())
516                 .build())
517             .build();
518
519         assertEquals(BI_TOP_PATH, biResult.path());
520         assertEquals(topNormalized, biResult.node());
521
522         final var baResult = codecContext.fromNormalizedNode(BI_TOP_PATH, topNormalized);
523
524         assertEquals(InstanceIdentifier.create(Top.class), baResult.getKey());
525         assertEquals(top, baResult.getValue());
526     }
527 }