2 * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.md.sal.common.impl.util.compat;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
16 import com.google.common.collect.ImmutableList;
17 import com.google.common.collect.Lists;
18 import com.google.common.collect.Maps;
19 import com.google.common.collect.Sets;
21 import java.util.AbstractMap;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.Comparator;
26 import java.util.List;
28 import java.util.Map.Entry;
31 import org.junit.Test;
32 import org.opendaylight.yangtools.yang.common.QName;
33 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
34 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
38 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
39 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
40 import org.opendaylight.yangtools.yang.data.api.Node;
41 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
44 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
45 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
46 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
47 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
48 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
49 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
50 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
51 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
52 import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
53 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
54 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
56 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
57 import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
58 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
59 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
60 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
61 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
62 import org.opendaylight.yangtools.yang.model.api.Module;
63 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
64 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
66 public class DataNormalizerTest {
68 static class NormalizedNodeData {
71 Object nodeData; // List for a container, value Object for a leaf
73 NormalizedNodeData(final PathArgument nodeID, final Class<?> nodeClass, final Object nodeData) {
75 this.nodeClass = nodeClass;
76 this.nodeData = nodeData;
80 static class LegacyNodeData {
82 Object nodeData; // List for a CompositeNode, value Object for a
85 LegacyNodeData(final QName nodeKey, final Object nodeData) {
86 this.nodeKey = nodeKey;
87 this.nodeData = nodeData;
91 public String toString() {
92 return nodeKey.toString();
96 static final QName TEST_QNAME = QName.create(
97 "urn:opendaylight:params:xml:ns:yang:controller:md:sal:normalization:test", "2014-03-13", "test");
98 static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
99 static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
100 static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
101 static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
102 static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
103 static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
105 static final InstanceIdentifier TEST_PATH = InstanceIdentifier.of(TEST_QNAME);
106 static final InstanceIdentifier OUTER_LIST_PATH = InstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME)
108 static final QName ONE_QNAME = QName.create(TEST_QNAME, "one");
109 static final QName TWO_QNAME = QName.create(TEST_QNAME, "two");
110 static final QName THREE_QNAME = QName.create(TEST_QNAME, "three");
112 static final QName ANY_XML_DATA_QNAME = QName.create(TEST_QNAME, "any-xml-data");
113 static final QName OUTER_CONTAINER_QNAME = QName.create(TEST_QNAME, "outer-container");
114 static final QName AUGMENTED_LEAF_QNAME = QName.create(TEST_QNAME, "augmented-leaf");
115 static final QName UNKEYED_LIST_QNAME = QName.create(TEST_QNAME, "unkeyed-list");
116 static final QName UNORDERED_LEAF_LIST_QNAME = QName.create(TEST_QNAME, "unordered-leaf-list");
117 static final QName ORDERED_LEAF_LIST_QNAME = QName.create(TEST_QNAME, "ordered-leaf-list");
119 static final Short OUTER_LIST_ID = (short) 10;
121 static final InstanceIdentifier OUTER_LIST_PATH_LEGACY = InstanceIdentifier.builder(TEST_QNAME)
122 .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID).build();
124 static final InstanceIdentifier LEAF_TWO_PATH_LEGACY = InstanceIdentifier.builder(OUTER_LIST_PATH_LEGACY)
125 .node(TWO_QNAME).build();
127 static final QName ANY_XML_LEAF_QNAME = QName.create(TEST_QNAME, "leaf");;
128 static final QName ANY_XML_INNER_QNAME = QName.create(TEST_QNAME, "inner");
129 static final QName ANY_XML_INNER_LEAF_QNAME = QName.create(TEST_QNAME, "inner-leaf");
131 SchemaContext createTestContext() {
132 YangParserImpl parser = new YangParserImpl();
133 Set<Module> modules = parser.parseYangModelsFromStreams(Collections.singletonList(DataNormalizerTest.class
134 .getResourceAsStream("/normalization-test.yang")));
135 return parser.resolveSchemaContext(modules);
139 public void testToNormalizedInstanceIdentifier() {
140 SchemaContext testCtx = createTestContext();
141 DataNormalizer normalizer = new DataNormalizer(testCtx);
143 InstanceIdentifier normalizedPath = normalizer.toNormalized(LEAF_TWO_PATH_LEGACY);
145 verifyNormalizedInstanceIdentifier(normalizedPath, TEST_QNAME, OUTER_LIST_QNAME, new Object[] {
146 OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID }, OUTER_CHOICE_QNAME, TWO_QNAME);
149 private void verifyNormalizedInstanceIdentifier(final InstanceIdentifier actual, final Object... expPath) {
151 assertNotNull("Actual InstanceIdentifier is null", actual);
152 assertEquals("InstanceIdentifier path length", expPath.length, actual.getPath().size());
154 for (int i = 0; i < expPath.length; i++) {
155 PathArgument actualArg = actual.getPath().get(i);
156 if (expPath[i] instanceof Object[]) { // NodeIdentifierWithPredicates
157 Object[] exp = (Object[]) expPath[i];
158 assertEquals("Actual path arg " + (i + 1) + " class", NodeIdentifierWithPredicates.class,
159 actualArg.getClass());
160 NodeIdentifierWithPredicates actualNode = (NodeIdentifierWithPredicates) actualArg;
161 assertEquals("Actual path arg " + (i + 1) + " node type", exp[0], actualNode.getNodeType());
162 assertEquals("Actual path arg " + (i + 1) + " key values map size", 1, actualNode.getKeyValues().size());
163 Entry<QName, Object> keyValuesEntry = actualNode.getKeyValues().entrySet().iterator().next();
164 assertEquals("Actual path arg " + (i + 1) + " key values map key", exp[1], keyValuesEntry.getKey());
165 assertEquals("Actual path arg " + (i + 1) + " key values map value", exp[2], keyValuesEntry.getValue());
166 } else if (expPath[i] instanceof Set) { // AugmentationIdentifier
167 assertEquals("Actual path arg " + (i + 1) + " class", AugmentationIdentifier.class,
168 actualArg.getClass());
169 AugmentationIdentifier actualNode = (AugmentationIdentifier) actualArg;
170 assertEquals("Actual path arg " + (i + 1) + " PossibleChildNames", expPath[i],
171 actualNode.getPossibleChildNames());
173 assertEquals("Actual path arg " + (i + 1) + " node type", expPath[i], actualArg.getNodeType());
179 public void testToLegacyInstanceIdentifier() throws DataNormalizationException {
181 DataNormalizer normalizer = new DataNormalizer(createTestContext());
183 InstanceIdentifier normalized = InstanceIdentifier.builder().node(TEST_QNAME).node(OUTER_LIST_QNAME)
184 .nodeWithKey(OUTER_LIST_QNAME, ID_QNAME, OUTER_LIST_ID).node(OUTER_CHOICE_QNAME).node(TWO_QNAME)
187 InstanceIdentifier legacy = normalizer.toLegacy(normalized);
189 assertEquals("Legacy InstanceIdentifier", LEAF_TWO_PATH_LEGACY, legacy);
193 public void testToLegacyNormalizedNode() {
195 ChoiceNode choiceNode1 = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_CHOICE_QNAME))
196 .withChild(ImmutableNodes.leafNode(TWO_QNAME, "two"))
197 .withChild(ImmutableNodes.leafNode(THREE_QNAME, "three")).build();
199 MapEntryNode innerListEntryNode1 = Builders.mapEntryBuilder()
200 .withNodeIdentifier(new NodeIdentifierWithPredicates(INNER_LIST_QNAME, NAME_QNAME, "inner-name1"))
201 .withChild(ImmutableNodes.leafNode(NAME_QNAME, "inner-name1"))
202 .withChild(ImmutableNodes.leafNode(VALUE_QNAME, "inner-value1")).build();
204 MapEntryNode innerListEntryNode2 = Builders.mapEntryBuilder()
205 .withNodeIdentifier(new NodeIdentifierWithPredicates(INNER_LIST_QNAME, NAME_QNAME, "inner-name2"))
206 .withChild(ImmutableNodes.leafNode(NAME_QNAME, "inner-name2"))
207 .withChild(ImmutableNodes.leafNode(VALUE_QNAME, "inner-value2")).build();
209 OrderedMapNode innerListNode = Builders.orderedMapBuilder()
210 .withNodeIdentifier(new NodeIdentifier(INNER_LIST_QNAME)).withChild(innerListEntryNode1)
211 .withChild(innerListEntryNode2).build();
213 Short outerListID1 = Short.valueOf((short) 10);
214 MapEntryNode outerListEntryNode1 = Builders.mapEntryBuilder()
215 .withNodeIdentifier(new NodeIdentifierWithPredicates(OUTER_LIST_QNAME, ID_QNAME, outerListID1))
216 .withChild(ImmutableNodes.leafNode(ID_QNAME, outerListID1)).withChild(choiceNode1)
217 .withChild(innerListNode).build();
219 ChoiceNode choiceNode2 = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_CHOICE_QNAME))
220 .withChild(ImmutableNodes.leafNode(ONE_QNAME, "one")).build();
222 Short outerListID2 = Short.valueOf((short) 20);
223 MapEntryNode outerListEntryNode2 = Builders.mapEntryBuilder()
224 .withNodeIdentifier(new NodeIdentifierWithPredicates(OUTER_LIST_QNAME, ID_QNAME, outerListID2))
225 .withChild(ImmutableNodes.leafNode(ID_QNAME, outerListID2)).withChild(choiceNode2).build();
227 MapNode outerListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(OUTER_LIST_QNAME))
228 .withChild(outerListEntryNode1).withChild(outerListEntryNode2).build();
230 UnkeyedListEntryNode unkeyedListEntryNode1 = Builders.unkeyedListEntryBuilder()
231 .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME))
232 .withChild(ImmutableNodes.leafNode(NAME_QNAME, "unkeyed1")).build();
234 UnkeyedListEntryNode unkeyedListEntryNode2 = Builders.unkeyedListEntryBuilder()
235 .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME))
236 .withChild(ImmutableNodes.leafNode(NAME_QNAME, "unkeyed2")).build();
238 UnkeyedListNode unkeyedListNode = Builders.unkeyedListBuilder()
239 .withNodeIdentifier(new NodeIdentifier(UNKEYED_LIST_QNAME)).withChild(unkeyedListEntryNode1)
240 .withChild(unkeyedListEntryNode2).build();
242 ContainerNode testContainerNode = Builders.containerBuilder()
243 .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(outerListNode).withChild(unkeyedListNode)
246 Node<?> legacyNode = DataNormalizer.toLegacy(testContainerNode);
254 expectSimpleNode(ID_QNAME, outerListID1),
255 expectSimpleNode(TWO_QNAME, "two"),
256 expectSimpleNode(THREE_QNAME, "three"),
258 expectCompositeNode(INNER_LIST_QNAME, expectSimpleNode(NAME_QNAME, "inner-name1"),
259 expectSimpleNode(VALUE_QNAME, "inner-value1")),
261 expectCompositeNode(INNER_LIST_QNAME, expectSimpleNode(NAME_QNAME, "inner-name2"),
262 expectSimpleNode(VALUE_QNAME, "inner-value2"))),
263 expectCompositeNode(OUTER_LIST_QNAME, expectSimpleNode(ID_QNAME, outerListID2),
264 expectSimpleNode(ONE_QNAME, "one")),
265 expectCompositeNode(UNKEYED_LIST_QNAME, expectSimpleNode(NAME_QNAME, "unkeyed1")),
266 expectCompositeNode(UNKEYED_LIST_QNAME, expectSimpleNode(NAME_QNAME, "unkeyed2"))));
268 // Conversion of Mixin type nodes is not supported.
270 assertNull("Expected null returned for Mixin type node", DataNormalizer.toLegacy(outerListNode));
274 * Following data are constructed: <any-xml-data> <inner>
275 * <inner-leaf>inner-leaf-value</inner-leaf> </inner>
276 * <leaf>leaf-value</leaf> <any-xml-data>
279 public void testToLegacyNormalizedNodeWithAnyXml() {
281 Node<?> innerLeafChild = NodeFactory.createImmutableSimpleNode(ANY_XML_INNER_LEAF_QNAME, null,
283 CompositeNode innerContainer = NodeFactory.createImmutableCompositeNode(ANY_XML_INNER_QNAME, null,
284 Collections.<Node<?>> singletonList(innerLeafChild));
286 Node<?> leafChild = NodeFactory.createImmutableSimpleNode(ANY_XML_LEAF_QNAME, null, "leaf-value");
287 CompositeNode anyXmlNodeValue = NodeFactory.createImmutableCompositeNode(ANY_XML_DATA_QNAME, null,
288 Arrays.asList(leafChild, innerContainer));
290 AnyXmlNode testAnyXmlNode = Builders.anyXmlBuilder().withNodeIdentifier(new NodeIdentifier(TEST_QNAME))
291 .withValue(anyXmlNodeValue).build();
293 ContainerNode testContainerNode = Builders.containerBuilder()
294 .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(testAnyXmlNode).build();
296 DataNormalizer normalizer = new DataNormalizer(createTestContext());
297 Node<?> legacyNode = normalizer.toLegacy(InstanceIdentifier.builder(TEST_QNAME).build(), testContainerNode);
305 expectSimpleNode(ANY_XML_LEAF_QNAME, "leaf-value"),
306 expectCompositeNode(ANY_XML_INNER_QNAME,
307 expectSimpleNode(ANY_XML_INNER_LEAF_QNAME, "inner-leaf-value")))));
311 public void testToLegacyNormalizedNodeWithLeafLists() {
313 CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
314 testBuilder.setQName(TEST_QNAME);
316 ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafSetBuilder = Builders.leafSetBuilder()
317 .withNodeIdentifier(new NodeIdentifier(UNORDERED_LEAF_LIST_QNAME));
318 for (int i = 1; i <= 3; i++) {
319 leafSetBuilder.withChildValue("unordered-value" + i);
322 ListNodeBuilder<Object, LeafSetEntryNode<Object>> orderedLeafSetBuilder = Builders.orderedLeafSetBuilder()
323 .withNodeIdentifier(new NodeIdentifier(ORDERED_LEAF_LIST_QNAME));
324 for (int i = 3; i > 0; i--) {
325 orderedLeafSetBuilder.withChildValue("ordered-value" + i);
328 ContainerNode testContainerNode = Builders.containerBuilder()
329 .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(leafSetBuilder.build())
330 .withChild(orderedLeafSetBuilder.build()).build();
332 DataNormalizer normalizer = new DataNormalizer(createTestContext());
334 Node<?> legacyNode = normalizer.toLegacy(InstanceIdentifier.builder(TEST_QNAME).build(), testContainerNode);
338 expectCompositeNode(TEST_QNAME, expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value1"),
339 expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value2"),
340 expectSimpleNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value3"),
341 expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value3"),
342 expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value2"),
343 expectSimpleNode(ORDERED_LEAF_LIST_QNAME, "ordered-value1")));
347 public void testToLegacyNormalizedNodeWithAugmentation() {
349 AugmentationNode augmentationNode = Builders.augmentationBuilder()
350 .withNodeIdentifier(new AugmentationIdentifier(Sets.newHashSet(AUGMENTED_LEAF_QNAME)))
351 .withChild(ImmutableNodes.leafNode(AUGMENTED_LEAF_QNAME, "augmented-value")).build();
353 ContainerNode outerContainerNode = Builders.containerBuilder()
354 .withNodeIdentifier(new NodeIdentifier(OUTER_CONTAINER_QNAME)).withChild(augmentationNode).build();
356 ContainerNode testContainerNode = Builders.containerBuilder()
357 .withNodeIdentifier(new NodeIdentifier(TEST_QNAME)).withChild(outerContainerNode).build();
359 DataNormalizer normalizer = new DataNormalizer(createTestContext());
361 Node<?> legacyNode = normalizer.toLegacy(InstanceIdentifier.builder(TEST_QNAME).build(), testContainerNode);
367 expectCompositeNode(OUTER_CONTAINER_QNAME,
368 expectSimpleNode(AUGMENTED_LEAF_QNAME, "augmented-value"))));
371 private boolean isOrdered(final QName nodeName) {
372 return ORDERED_LEAF_LIST_QNAME.equals(nodeName) || INNER_LIST_QNAME.equals(nodeName);
375 @SuppressWarnings("unchecked")
376 private void verifyLegacyNode(final Node<?> actual, final LegacyNodeData expNodeData) {
378 assertNotNull("Actual Node is null", actual);
379 assertTrue("Expected CompositeNode instance", actual instanceof CompositeNode);
380 CompositeNode actualCN = (CompositeNode) actual;
381 assertEquals("Node key", expNodeData.nodeKey, actualCN.getKey());
383 List<LegacyNodeData> expChildData = Lists.newArrayList();
384 List<LegacyNodeData> unorderdChildData = Lists.newArrayList();
385 for (LegacyNodeData data : (List<LegacyNodeData>) expNodeData.nodeData) {
386 if (isOrdered(data.nodeKey)) {
387 expChildData.add(data);
389 unorderdChildData.add(data);
393 Collections.sort(unorderdChildData, new Comparator<LegacyNodeData>() {
395 public int compare(final LegacyNodeData arg1, final LegacyNodeData arg2) {
396 if (!(arg1.nodeData instanceof List) && !(arg2.nodeData instanceof List)) {
397 // if neither is a list, just compare them
398 String str1 = arg1.nodeKey.getLocalName() + arg1.nodeData;
399 String str2 = arg2.nodeKey.getLocalName() + arg2.nodeData;
400 return str1.compareTo(str2);
401 } else if (arg1.nodeData instanceof List && arg2.nodeData instanceof List) {
402 // if both are lists, first check their local name
403 String str1 = arg1.nodeKey.getLocalName();
404 String str2 = arg2.nodeKey.getLocalName();
405 if (!str1.equals(str2)) {
406 return str1.compareTo(str2);
408 // if local names are the same, then look at the list contents
409 List<LegacyNodeData> l1 = (List<LegacyNodeData>) arg1.nodeData;
410 List<LegacyNodeData> l2 = (List<LegacyNodeData>) arg2.nodeData;
412 if (l1.size() != l2.size()) {
413 // if the sizes are different, use that
414 return l2.size() - l1.size();
416 // lastly sort and recursively check the list contents
417 Collections.sort(l1, this);
418 Collections.sort(l2, this);
420 for (int i = 0 ; i < l1.size() ; i++) {
421 int diff = this.compare(l1.get(i), l2.get(i));
429 } else if( arg1.nodeData instanceof List ) {
437 expChildData.addAll(unorderdChildData);
439 List<Node<?>> actualChildNodes = Lists.newArrayList();
440 List<Node<?>> unorderedChildNodes = Lists.newArrayList();
441 for (Node<?> node : actualCN.getValue()) {
442 if (isOrdered(node.getKey())) {
443 actualChildNodes.add(node);
445 unorderedChildNodes.add(node);
449 Collections.sort(unorderedChildNodes, new Comparator<Node<?>>() {
451 public int compare(final Node<?> n1, final Node<?> n2) {
452 if (n1 instanceof SimpleNode && n2 instanceof SimpleNode) {
453 // if they're SimpleNodes just compare their strings
454 String str1 = n1.getKey().getLocalName() + ((SimpleNode<?>)n1).getValue();
455 String str2 = n2.getKey().getLocalName() + ((SimpleNode<?>)n2).getValue();
456 return str1.compareTo(str2);
457 } else if (n1 instanceof CompositeNode && n2 instanceof CompositeNode) {
458 // if they're CompositeNodes, things are more interesting
459 String str1 = n1.getKey().getLocalName();
460 String str2 = n2.getKey().getLocalName();
461 if (!str1.equals(str2)) {
462 // if their local names differ, return that difference
463 return str1.compareTo(str2);
465 // otherwise, we need to look at their contents
466 ArrayList<Node<?>> l1 = new ArrayList<Node<?>>( ((CompositeNode)n1).getValue() );
467 ArrayList<Node<?>> l2 = new ArrayList<Node<?>>( ((CompositeNode)n2).getValue() );
469 if (l1.size() != l2.size()) {
470 // if they have different numbers of things in them return that
471 return l2.size() - l1.size();
473 // otherwise, compare the individual elements, first sort them
474 Collections.sort(l1, this);
475 Collections.sort(l2, this);
477 // then compare them individually
478 for(int i = 0 ; i < l2.size() ; i++) {
479 int diff = this.compare(l1.get(i), l2.get(i));
487 } else if (n1 instanceof CompositeNode && n2 instanceof SimpleNode) {
489 } else if (n2 instanceof CompositeNode && n1 instanceof SimpleNode) {
492 assertTrue("Expected either SimpleNodes CompositeNodes", false);
498 actualChildNodes.addAll(unorderedChildNodes);
500 for (Node<?> actualChild : actualChildNodes) {
501 LegacyNodeData expData = expChildData.isEmpty() ? null : expChildData.remove(0);
502 assertNotNull("Unexpected child node with key " + actualChild.getKey(), expData);
503 assertEquals("Child node QName", expData.nodeKey, actualChild.getKey());
505 if (expData.nodeData instanceof List) { // List represents a
507 verifyLegacyNode(actualChild, expData);
508 } else { // else a simple node
509 assertTrue("Expected SimpleNode instance", actualChild instanceof SimpleNode);
510 assertEquals("Child node value with key " + actualChild.getKey(), expData.nodeData,
511 ((SimpleNode<?>) actualChild).getValue());
515 if (!expChildData.isEmpty()) {
516 fail("Missing child nodes: " + expChildData);
520 private LegacyNodeData expectCompositeNode(final QName key, final LegacyNodeData... childData) {
521 return new LegacyNodeData(key, Lists.newArrayList(childData));
524 private LegacyNodeData expectSimpleNode(final QName key, final Object value) {
525 return new LegacyNodeData(key, value);
529 public void testToNormalizedCompositeNode() {
530 SchemaContext testCtx = createTestContext();
531 DataNormalizer normalizer = new DataNormalizer(testCtx);
533 CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
534 testBuilder.setQName(TEST_QNAME);
536 CompositeNodeBuilder<ImmutableCompositeNode> outerListBuilder = ImmutableCompositeNode.builder();
537 outerListBuilder.setQName(OUTER_LIST_QNAME);
538 outerListBuilder.addLeaf(ID_QNAME, 10);
539 outerListBuilder.addLeaf(ONE_QNAME, "one");
541 for (int i = 3; i > 0; i--) {
542 CompositeNodeBuilder<ImmutableCompositeNode> innerListBuilder = ImmutableCompositeNode.builder();
543 innerListBuilder.setQName(INNER_LIST_QNAME);
544 innerListBuilder.addLeaf(NAME_QNAME, "inner-name" + i);
545 innerListBuilder.addLeaf(VALUE_QNAME, "inner-value" + i);
546 outerListBuilder.add(innerListBuilder.toInstance());
549 testBuilder.add(outerListBuilder.toInstance());
551 outerListBuilder = ImmutableCompositeNode.builder();
552 outerListBuilder.setQName(OUTER_LIST_QNAME);
553 outerListBuilder.addLeaf(ID_QNAME, 20);
554 outerListBuilder.addLeaf(TWO_QNAME, "two");
555 outerListBuilder.addLeaf(THREE_QNAME, "three");
556 testBuilder.add(outerListBuilder.toInstance());
558 for (int i = 1; i <= 2; i++) {
559 CompositeNodeBuilder<ImmutableCompositeNode> unkeyedListBuilder = ImmutableCompositeNode.builder();
560 unkeyedListBuilder.setQName(UNKEYED_LIST_QNAME);
561 unkeyedListBuilder.addLeaf(NAME_QNAME, "unkeyed-name" + i);
562 testBuilder.add(unkeyedListBuilder.toInstance());
565 Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
566 .toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(InstanceIdentifier.create(
567 ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
569 verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
571 verifyNormalizedNode(
572 normalizedNodeEntry.getValue(),
581 expectLeafNode(ID_QNAME, 10),
582 expectChoiceNode(OUTER_CHOICE_QNAME, expectLeafNode(ONE_QNAME, "one")),
583 expectOrderedMapNode(
585 expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name3",
586 expectLeafNode(NAME_QNAME, "inner-name3"),
587 expectLeafNode(VALUE_QNAME, "inner-value3")),
588 expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name2",
589 expectLeafNode(NAME_QNAME, "inner-name2"),
590 expectLeafNode(VALUE_QNAME, "inner-value2")),
591 expectMapEntryNode(INNER_LIST_QNAME, NAME_QNAME, "inner-name1",
592 expectLeafNode(NAME_QNAME, "inner-name1"),
593 expectLeafNode(VALUE_QNAME, "inner-value1")))),
598 expectLeafNode(ID_QNAME, 20),
599 expectChoiceNode(OUTER_CHOICE_QNAME, expectLeafNode(TWO_QNAME, "two"),
600 expectLeafNode(THREE_QNAME, "three")))),
601 expectUnkeyedListNode(
603 expectUnkeyedListEntryNode(UNKEYED_LIST_QNAME,
604 expectLeafNode(NAME_QNAME, "unkeyed-name1")),
605 expectUnkeyedListEntryNode(UNKEYED_LIST_QNAME,
606 expectLeafNode(NAME_QNAME, "unkeyed-name2")))));
610 public void testToNormalizedCompositeNodeWithAnyXml() {
611 SchemaContext testCtx = createTestContext();
612 DataNormalizer normalizer = new DataNormalizer(testCtx);
614 CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
615 testBuilder.setQName(TEST_QNAME);
617 CompositeNodeBuilder<ImmutableCompositeNode> anyXmlBuilder = ImmutableCompositeNode.builder();
618 anyXmlBuilder.setQName(ANY_XML_DATA_QNAME);
619 anyXmlBuilder.addLeaf(ANY_XML_LEAF_QNAME, "leaf-value");
621 CompositeNodeBuilder<ImmutableCompositeNode> innerBuilder = ImmutableCompositeNode.builder();
622 innerBuilder.setQName(ANY_XML_INNER_QNAME);
623 innerBuilder.addLeaf(ANY_XML_INNER_LEAF_QNAME, "inner-leaf-value");
625 anyXmlBuilder.add(innerBuilder.toInstance());
626 CompositeNode anyXmlLegacy = anyXmlBuilder.toInstance();
627 testBuilder.add(anyXmlLegacy);
629 Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
630 .toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(InstanceIdentifier.create(
631 ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
633 verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
635 verifyNormalizedNode(normalizedNodeEntry.getValue(),
636 expectContainerNode(TEST_QNAME, expectAnyXmlNode(ANY_XML_DATA_QNAME, anyXmlLegacy)));
640 public void testToNormalizedCompositeNodeWithAugmentation() {
641 SchemaContext testCtx = createTestContext();
642 DataNormalizer normalizer = new DataNormalizer(testCtx);
644 CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
645 testBuilder.setQName(TEST_QNAME);
647 CompositeNodeBuilder<ImmutableCompositeNode> outerContBuilder = ImmutableCompositeNode.builder();
648 outerContBuilder.setQName(OUTER_CONTAINER_QNAME);
649 outerContBuilder.addLeaf(AUGMENTED_LEAF_QNAME, "augmented-value");
651 testBuilder.add(outerContBuilder.toInstance());
653 Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
654 .toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(InstanceIdentifier.create(
655 ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
657 verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
659 NormalizedNodeData expAugmentation = expectAugmentation(AUGMENTED_LEAF_QNAME,
660 expectLeafNode(AUGMENTED_LEAF_QNAME, "augmented-value"));
662 verifyNormalizedNode(normalizedNodeEntry.getValue(),
663 expectContainerNode(TEST_QNAME, expectContainerNode(OUTER_CONTAINER_QNAME, expAugmentation)));
665 normalizedNodeEntry = normalizer.toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(
666 InstanceIdentifier.create(Lists.newArrayList(new NodeIdentifier(TEST_QNAME), new NodeIdentifier(
667 OUTER_CONTAINER_QNAME))), outerContBuilder.toInstance()));
669 verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME, OUTER_CONTAINER_QNAME,
670 Sets.newHashSet(AUGMENTED_LEAF_QNAME));
672 verifyNormalizedNode(normalizedNodeEntry.getValue(), expAugmentation);
676 public void testToNormalizedCompositeNodeWithLeafLists() {
677 SchemaContext testCtx = createTestContext();
678 DataNormalizer normalizer = new DataNormalizer(testCtx);
680 CompositeNodeBuilder<ImmutableCompositeNode> testBuilder = ImmutableCompositeNode.builder();
681 testBuilder.setQName(TEST_QNAME);
683 for (int i = 1; i <= 3; i++) {
684 testBuilder.addLeaf(UNORDERED_LEAF_LIST_QNAME, "unordered-value" + i);
687 for (int i = 3; i > 0; i--) {
688 testBuilder.addLeaf(ORDERED_LEAF_LIST_QNAME, "ordered-value" + i);
691 Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedNodeEntry = normalizer
692 .toNormalized(new AbstractMap.SimpleEntry<InstanceIdentifier, CompositeNode>(InstanceIdentifier.create(
693 ImmutableList.<PathArgument> of(new NodeIdentifier(TEST_QNAME))), testBuilder.toInstance()));
695 verifyNormalizedInstanceIdentifier(normalizedNodeEntry.getKey(), TEST_QNAME);
697 verifyNormalizedNode(
698 normalizedNodeEntry.getValue(),
701 expectLeafSetNode(UNORDERED_LEAF_LIST_QNAME,
702 expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value1"),
703 expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value2"),
704 expectLeafSetEntryNode(UNORDERED_LEAF_LIST_QNAME, "unordered-value3")),
705 expectOrderedLeafSetNode(ORDERED_LEAF_LIST_QNAME,
706 expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value3"),
707 expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value2"),
708 expectLeafSetEntryNode(ORDERED_LEAF_LIST_QNAME, "ordered-value1"))));
711 @SuppressWarnings("unchecked")
712 private void verifyNormalizedNode(final NormalizedNode<?, ?> actual, final NormalizedNodeData expNodeData) {
714 Class<?> expNodeClass = expNodeData.nodeClass;
715 PathArgument expNodeID = expNodeData.nodeID;
717 assertNotNull("Actual NormalizedNode is null", actual);
718 assertTrue("NormalizedNode instance " + actual.getClass() + " is not derived from " + expNodeClass,
719 expNodeClass.isAssignableFrom(actual.getClass()));
720 assertEquals("NormalizedNode identifier", expNodeID, actual.getIdentifier());
722 if (expNodeData.nodeData instanceof List) {
723 Map<PathArgument, Integer> orderingMap = null;
724 if (expNodeClass.equals(OrderedMapNode.class) || expNodeClass.equals(OrderedLeafSetNode.class)) {
725 orderingMap = Maps.newHashMap();
729 Map<PathArgument, NormalizedNodeData> expChildDataMap = Maps.newHashMap();
730 List<NormalizedNodeData> expChildDataList = (List<NormalizedNodeData>) expNodeData.nodeData;
731 for (NormalizedNodeData data : expChildDataList) {
732 expChildDataMap.put(data.nodeID, data);
734 if (orderingMap != null) {
735 orderingMap.put(data.nodeID, i++);
739 assertNotNull("Actual value is null for node " + actual.getIdentifier(), actual.getValue());
740 assertTrue("Expected value instance Iterable for node " + actual.getIdentifier(),
741 Iterable.class.isAssignableFrom(actual.getValue().getClass()));
744 for (NormalizedNode<?, ?> actualChild : (Iterable<NormalizedNode<?, ?>>) actual.getValue()) {
745 NormalizedNodeData expChildData = expNodeClass.equals(UnkeyedListNode.class) ? expChildDataList
746 .remove(0) : expChildDataMap.remove(actualChild.getIdentifier());
749 "Unexpected child node " + actualChild.getClass() + " with identifier "
750 + actualChild.getIdentifier() + " for parent node " + actual.getClass()
751 + " with identifier " + actual.getIdentifier(), expChildData);
753 if (orderingMap != null) {
754 assertEquals("Order index for child node " + actualChild.getIdentifier(),
755 orderingMap.get(actualChild.getIdentifier()), Integer.valueOf(i));
758 verifyNormalizedNode(actualChild, expChildData);
762 if (expNodeClass.equals(UnkeyedListNode.class)) {
763 if (expChildDataList.size() > 0) {
764 fail("Missing " + expChildDataList.size() + " child nodes for parent " + actual.getIdentifier());
767 if (!expChildDataMap.isEmpty()) {
768 fail("Missing child nodes for parent " + actual.getIdentifier() + ": " + expChildDataMap.keySet());
772 assertEquals("Leaf value for node " + actual.getIdentifier(), expNodeData.nodeData, actual.getValue());
776 private NormalizedNodeData expectOrderedLeafSetNode(final QName nodeName, final NormalizedNodeData... childData) {
777 return new NormalizedNodeData(new NodeIdentifier(nodeName), OrderedLeafSetNode.class,
778 Lists.newArrayList(childData));
781 private NormalizedNodeData expectLeafSetNode(final QName nodeName, final NormalizedNodeData... childData) {
782 return new NormalizedNodeData(new NodeIdentifier(nodeName), LeafSetNode.class, Lists.newArrayList(childData));
785 private NormalizedNodeData expectLeafSetEntryNode(final QName nodeName, final Object value) {
786 return new NormalizedNodeData(new NodeWithValue(nodeName, value), LeafSetEntryNode.class, value);
789 private NormalizedNodeData expectUnkeyedListNode(final QName nodeName, final NormalizedNodeData... childData) {
790 return new NormalizedNodeData(new NodeIdentifier(nodeName), UnkeyedListNode.class,
791 Lists.newArrayList(childData));
794 private NormalizedNodeData expectUnkeyedListEntryNode(final QName nodeName, final NormalizedNodeData... childData) {
795 return new NormalizedNodeData(new NodeIdentifier(nodeName), UnkeyedListEntryNode.class,
796 Lists.newArrayList(childData));
799 private NormalizedNodeData expectAugmentation(final QName augmentedNodeName, final NormalizedNodeData... childData) {
800 return new NormalizedNodeData(new AugmentationIdentifier(Sets.newHashSet(augmentedNodeName)),
801 AugmentationNode.class, Lists.newArrayList(childData));
804 private NormalizedNodeData expectAnyXmlNode(final QName nodeName, final Object value) {
805 return new NormalizedNodeData(new NodeIdentifier(nodeName), AnyXmlNode.class, value);
808 private NormalizedNodeData expectContainerNode(final QName nodeName, final NormalizedNodeData... childData) {
809 return new NormalizedNodeData(new NodeIdentifier(nodeName), ContainerNode.class, Lists.newArrayList(childData));
812 private NormalizedNodeData expectChoiceNode(final QName nodeName, final NormalizedNodeData... childData) {
813 return new NormalizedNodeData(new NodeIdentifier(nodeName), ChoiceNode.class, Lists.newArrayList(childData));
816 private NormalizedNodeData expectLeafNode(final QName nodeName, final Object value) {
817 return new NormalizedNodeData(new NodeIdentifier(nodeName), LeafNode.class, value);
821 private NormalizedNodeData expectMapEntryNode(final QName nodeName, final QName key, final Object value,
822 final NormalizedNodeData... childData) {
823 return new NormalizedNodeData(new NodeIdentifierWithPredicates(nodeName, key, value), MapEntryNode.class,
824 Lists.newArrayList(childData));
827 private NormalizedNodeData expectMapNode(final QName key, final NormalizedNodeData... childData) {
828 return new NormalizedNodeData(new NodeIdentifier(key), MapNode.class, Lists.newArrayList(childData));
831 private NormalizedNodeData expectOrderedMapNode(final QName key, final NormalizedNodeData... childData) {
832 return new NormalizedNodeData(new NodeIdentifier(key), OrderedMapNode.class, Lists.newArrayList(childData));