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