2 * Copyright (c) 2016 Cisco 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.yangtools.yang.stmt;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotEquals;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertNull;
15 import static org.junit.Assert.assertTrue;
17 import com.google.common.collect.Iterables;
18 import java.util.Collection;
20 import java.util.Optional;
21 import org.junit.Test;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.common.QNameModule;
24 import org.opendaylight.yangtools.yang.common.Revision;
25 import org.opendaylight.yangtools.yang.common.XMLNamespace;
26 import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
32 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
34 import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
35 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
36 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.Module;
39 import org.opendaylight.yangtools.yang.model.api.MustDefinition;
40 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
42 import org.opendaylight.yangtools.yang.model.api.UsesNode;
43 import org.opendaylight.yangtools.yang.model.api.stmt.RefineEffectiveStatement;
44 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Descendant;
45 import org.opendaylight.yangtools.yang.model.api.stmt.UnrecognizedStatement;
47 public class GroupingTest extends AbstractModelTest {
49 public void testRefine() {
50 final ContainerSchemaNode peer = (ContainerSchemaNode) FOO.getDataChildByName(fooQName("peer"));
51 final ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName(fooQName("destination"));
53 final Collection<? extends UsesNode> usesNodes = destination.getUses();
54 assertEquals(1, usesNodes.size());
55 final UsesNode usesNode = usesNodes.iterator().next();
56 final Map<Descendant, SchemaNode> refines = usesNode.getRefines();
57 assertEquals(4, refines.size());
59 LeafSchemaNode refineLeaf = null;
60 ContainerSchemaNode refineContainer = null;
61 ListSchemaNode refineList = null;
62 LeafSchemaNode refineInnerLeaf = null;
63 for (final Map.Entry<Descendant, SchemaNode> entry : refines.entrySet()) {
64 final SchemaNode value = entry.getValue();
65 if ("address".equals(value.getQName().getLocalName())) {
66 refineLeaf = (LeafSchemaNode) destination.getDataChildByName(value.getQName());
67 } else if ("port".equals(value.getQName().getLocalName())) {
68 refineContainer = (ContainerSchemaNode) destination.getDataChildByName(value.getQName());
69 } else if ("addresses".equals(value.getQName().getLocalName())) {
70 refineList = (ListSchemaNode) destination.getDataChildByName(value.getQName());
74 assertNotNull(refineList);
75 for (final Map.Entry<Descendant, SchemaNode> entry : refines.entrySet()) {
76 final SchemaNode value = entry.getValue();
77 if ("id".equals(value.getQName().getLocalName())) {
78 refineInnerLeaf = (LeafSchemaNode) refineList.getDataChildByName(value.getQName());
83 assertNotNull(refineLeaf);
84 assertEquals(Optional.of("IP address of target node"), refineLeaf.getDescription());
85 assertEquals(Optional.of("address reference added by refine"), refineLeaf.getReference());
86 assertEquals(Optional.of(Boolean.FALSE), refineLeaf.effectiveConfig());
87 assertFalse(refineLeaf.isMandatory());
88 final Collection<? extends MustDefinition> leafMustConstraints = refineLeaf.getMustConstraints();
89 assertEquals(1, leafMustConstraints.size());
90 final MustDefinition leafMust = leafMustConstraints.iterator().next();
91 assertEquals("ifType != 'ethernet' or (ifType = 'ethernet' and ifMTU = 1500)", leafMust.getXpath().toString());
92 assertEquals(0, refineLeaf.getUnknownSchemaNodes().size());
93 assertEquals(1, usesNode.asEffectiveStatement()
94 .findFirstEffectiveSubstatement(RefineEffectiveStatement.class).orElseThrow().getDeclared()
95 .declaredSubstatements(UnrecognizedStatement.class).size());
98 assertNotNull(refineContainer);
99 final Collection<? extends MustDefinition> mustConstraints = refineContainer.getMustConstraints();
100 assertTrue(mustConstraints.isEmpty());
101 assertEquals(Optional.of("description of port defined by refine"), refineContainer.getDescription());
102 assertEquals(Optional.of("port reference added by refine"), refineContainer.getReference());
103 assertEquals(Optional.of(Boolean.FALSE), refineContainer.effectiveConfig());
104 assertTrue(refineContainer.isPresenceContainer());
107 assertEquals(Optional.of("description of addresses defined by refine"), refineList.getDescription());
108 assertEquals(Optional.of("addresses reference added by refine"), refineList.getReference());
109 assertEquals(Optional.of(Boolean.FALSE), refineList.effectiveConfig());
111 final ElementCountConstraint constraint = refineList.getElementCountConstraint().get();
112 assertEquals((Object) 2, constraint.getMinElements());
113 assertNull(constraint.getMaxElements());
116 assertNotNull(refineInnerLeaf);
117 assertEquals(Optional.of("id of address"), refineInnerLeaf.getDescription());
121 public void testGrouping() {
122 final Collection<? extends GroupingDefinition> groupings = BAZ.getGroupings();
123 assertEquals(1, groupings.size());
124 final GroupingDefinition grouping = groupings.iterator().next();
125 final Collection<? extends DataSchemaNode> children = grouping.getChildNodes();
126 assertEquals(5, children.size());
130 public void testUses() {
131 // suffix _u = added by uses
132 // suffix _g = defined in grouping
136 final Collection<? extends GroupingDefinition> groupings = BAZ.getGroupings();
137 assertEquals(1, groupings.size());
138 final GroupingDefinition grouping = groupings.iterator().next();
140 // get node containing uses
141 final ContainerSchemaNode peer = (ContainerSchemaNode) FOO.getDataChildByName(fooQName("peer"));
142 final ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName(fooQName("destination"));
145 final Collection<? extends UsesNode> uses = destination.getUses();
146 assertEquals(1, uses.size());
148 // check uses process
149 final AnyxmlSchemaNode data_u = (AnyxmlSchemaNode) destination.getDataChildByName(fooQName("data"));
150 assertTrue(data_u.isAddedByUses());
152 final AnyxmlSchemaNode data_g = (AnyxmlSchemaNode) grouping.getDataChildByName(bazQName("data"));
153 assertFalse(data_g.isAddedByUses());
154 assertNotEquals(data_u, data_g);
156 final ChoiceSchemaNode how_u = (ChoiceSchemaNode) destination.getDataChildByName(fooQName("how"));
157 assertIsAddedByUses(how_u, true);
158 assertEquals(2, how_u.getCases().size());
160 final ChoiceSchemaNode how_g = (ChoiceSchemaNode) grouping.getDataChildByName(bazQName("how"));
161 assertIsAddedByUses(how_g, false);
162 assertEquals(2, how_g.getCases().size());
163 assertNotEquals(how_u, how_g);
165 final LeafSchemaNode address_u = (LeafSchemaNode) destination.getDataChildByName(fooQName("address"));
166 assertEquals(Optional.of("1.2.3.4"), address_u.getType().getDefaultValue());
167 assertEquals(Optional.of("IP address of target node"), address_u.getDescription());
168 assertEquals(Optional.of("address reference added by refine"), address_u.getReference());
169 assertEquals(Optional.of(Boolean.FALSE), address_u.effectiveConfig());
170 assertTrue(address_u.isAddedByUses());
171 assertFalse(address_u.isMandatory());
173 final LeafSchemaNode address_g = (LeafSchemaNode) grouping.getDataChildByName(bazQName("address"));
174 assertFalse(address_g.isAddedByUses());
175 assertEquals(Optional.empty(), address_g.getType().getDefaultValue());
176 assertEquals(Optional.of("Target IP address"), address_g.getDescription());
177 assertEquals(Optional.empty(), address_g.getReference());
178 assertEquals(Optional.empty(), address_g.effectiveConfig());
179 assertTrue(address_g.isMandatory());
180 assertNotEquals(address_u, address_g);
182 final ContainerSchemaNode port_u = (ContainerSchemaNode) destination.getDataChildByName(fooQName("port"));
183 assertIsAddedByUses(port_u, true);
185 final ContainerSchemaNode port_g = (ContainerSchemaNode) grouping.getDataChildByName(bazQName("port"));
186 assertIsAddedByUses(port_g, false);
187 assertNotEquals(port_u, port_g);
189 final ListSchemaNode addresses_u = (ListSchemaNode) destination.getDataChildByName(fooQName("addresses"));
190 assertIsAddedByUses(addresses_u, true);
192 final ListSchemaNode addresses_g = (ListSchemaNode) grouping.getDataChildByName(bazQName("addresses"));
193 assertIsAddedByUses(addresses_g, false);
194 assertNotEquals(addresses_u, addresses_g);
196 // grouping defined by 'uses'
197 final Collection<? extends GroupingDefinition> groupings_u = destination.getGroupings();
198 assertEquals(0, groupings_u.size());
200 // grouping defined in 'grouping' node
201 final Collection<? extends GroupingDefinition> groupings_g = grouping.getGroupings();
202 assertEquals(1, groupings_g.size());
203 final GroupingDefinition grouping_g = groupings_g.iterator().next();
204 assertIsAddedByUses(grouping_g, false);
206 assertEquals(0, destination.getUnknownSchemaNodes().size());
208 grouping.asEffectiveStatement().getDeclared().declaredSubstatements(UnrecognizedStatement.class).size());
212 public void testUsesUnderModule() {
213 // suffix _u = added by uses
214 // suffix _g = defined in grouping
217 final Collection<? extends GroupingDefinition> groupings = BAZ.getGroupings();
218 assertEquals(1, groupings.size());
219 final GroupingDefinition grouping = groupings.iterator().next();
222 final Collection<? extends UsesNode> uses = FOO.getUses();
223 assertEquals(1, uses.size());
225 // check uses process
226 final AnyxmlSchemaNode data_u = (AnyxmlSchemaNode) FOO.getDataChildByName(fooQName("data"));
227 assertTrue(data_u.isAddedByUses());
229 final AnyxmlSchemaNode data_g = (AnyxmlSchemaNode) grouping.getDataChildByName(bazQName("data"));
230 assertFalse(data_g.isAddedByUses());
231 assertNotEquals(data_u, data_g);
233 final ChoiceSchemaNode how_u = (ChoiceSchemaNode) FOO.getDataChildByName(fooQName("how"));
234 assertIsAddedByUses(how_u, true);
235 assertFalse(how_u.isAugmenting());
236 final Collection<? extends CaseSchemaNode> cases_u = how_u.getCases();
237 assertEquals(2, cases_u.size());
238 final CaseSchemaNode interval = how_u.findCaseNodes("interval").iterator().next();
239 assertFalse(interval.isAugmenting());
240 final LeafSchemaNode name = (LeafSchemaNode) interval.getDataChildByName(fooQName("name"));
241 assertTrue(name.isAugmenting());
242 final LeafSchemaNode intervalLeaf = (LeafSchemaNode) interval.getDataChildByName(fooQName("interval"));
243 assertFalse(intervalLeaf.isAugmenting());
245 final ChoiceSchemaNode how_g = (ChoiceSchemaNode) grouping.getDataChildByName(bazQName("how"));
246 assertIsAddedByUses(how_g, false);
247 assertNotEquals(how_u, how_g);
249 final LeafSchemaNode address_u = (LeafSchemaNode) FOO.getDataChildByName(fooQName("address"));
250 assertEquals(Optional.empty(), address_u.getType().getDefaultValue());
251 assertEquals(Optional.of("Target IP address"), address_u.getDescription());
252 assertFalse(address_u.getReference().isPresent());
253 assertEquals(Optional.empty(), address_u.effectiveConfig());
254 assertTrue(address_u.isAddedByUses());
256 final LeafSchemaNode address_g = (LeafSchemaNode) grouping.getDataChildByName(bazQName("address"));
257 assertFalse(address_g.isAddedByUses());
258 assertEquals(Optional.empty(), address_g.getType().getDefaultValue());
259 assertEquals(Optional.of("Target IP address"), address_g.getDescription());
260 assertFalse(address_g.getReference().isPresent());
261 assertEquals(Optional.empty(), address_g.effectiveConfig());
262 assertNotEquals(address_u, address_g);
264 final ContainerSchemaNode port_u = (ContainerSchemaNode) FOO.getDataChildByName(fooQName("port"));
265 assertIsAddedByUses(port_u, true);
267 final ContainerSchemaNode port_g = (ContainerSchemaNode) grouping.getDataChildByName(bazQName("port"));
268 assertIsAddedByUses(port_g, false);
269 assertNotEquals(port_u, port_g);
271 final ListSchemaNode addresses_u = (ListSchemaNode) FOO.getDataChildByName(fooQName("addresses"));
272 assertIsAddedByUses(addresses_u, true);
274 final ListSchemaNode addresses_g = (ListSchemaNode) grouping.getDataChildByName(bazQName("addresses"));
275 assertIsAddedByUses(addresses_g, false);
276 assertNotEquals(addresses_u, addresses_g);
278 // grouping defined by 'uses'
279 final Collection<? extends GroupingDefinition> groupings_u = FOO.getGroupings();
280 assertEquals(0, groupings_u.size());
282 // grouping defined in 'grouping' node
283 final Collection<? extends GroupingDefinition> groupings_g = grouping.getGroupings();
284 assertEquals(1, groupings_g.size());
285 final GroupingDefinition grouping_g = groupings_g.iterator().next();
286 assertIsAddedByUses(grouping_g, false);
288 assertEquals(0, grouping.getUnknownSchemaNodes().size());
289 assertEquals(1, grouping.asEffectiveStatement().getDeclared().declaredSubstatements(UnrecognizedStatement.class)
292 final UsesNode un = uses.iterator().next();
293 final Collection<? extends AugmentationSchemaNode> usesAugments = un.getAugmentations();
294 assertEquals(1, usesAugments.size());
295 final AugmentationSchemaNode augment = usesAugments.iterator().next();
296 assertEquals(Optional.of("inner augment"), augment.getDescription());
297 final Collection<? extends DataSchemaNode> children = augment.getChildNodes();
298 assertEquals(1, children.size());
299 final DataSchemaNode leaf = children.iterator().next();
300 assertTrue(leaf instanceof LeafSchemaNode);
301 assertEquals("name", leaf.getQName().getLocalName());
305 public void testCascadeUses() throws Exception {
306 final EffectiveModelContext loadModules = TestUtils.parseYangSource("/grouping-test/cascade-uses.yang");
307 assertEquals(1, loadModules.getModules().size());
309 final Module testModule = Iterables.getOnlyElement(loadModules.findModules("cascade-uses"));
310 final QNameModule namespace = testModule.getQNameModule();
311 final Collection<? extends GroupingDefinition> groupings = testModule.getGroupings();
313 GroupingDefinition gu = null;
314 GroupingDefinition gv = null;
315 GroupingDefinition gx = null;
316 GroupingDefinition gy = null;
317 GroupingDefinition gz = null;
318 GroupingDefinition gzz = null;
319 for (final GroupingDefinition gd : groupings) {
320 final String name = gd.getQName().getLocalName();
351 final QNameModule expectedModule = QNameModule.create(XMLNamespace.of("urn:grouping:cascade-uses"),
352 Revision.of("2013-07-18"));
355 Collection<? extends DataSchemaNode> childNodes = gu.getChildNodes();
356 assertEquals(7, childNodes.size());
358 final LeafSchemaNode leafGroupingU = (LeafSchemaNode) gu.getDataChildByName(
359 QName.create(namespace, "leaf-grouping-U"));
360 assertFalse(leafGroupingU.isAddedByUses());
362 for (final DataSchemaNode childNode : childNodes) {
363 if (!childNode.getQName().equals(leafGroupingU.getQName())) {
364 assertIsAddedByUses(childNode, true);
369 childNodes = gv.getChildNodes();
370 assertEquals(4, childNodes.size());
371 LeafSchemaNode leafGroupingV = null;
372 ContainerSchemaNode containerGroupingV = null;
373 for (final DataSchemaNode childNode : childNodes) {
374 if ("leaf-grouping-V".equals(childNode.getQName().getLocalName())) {
375 leafGroupingV = (LeafSchemaNode) childNode;
376 } else if ("container-grouping-V".equals(childNode.getQName().getLocalName())) {
377 containerGroupingV = (ContainerSchemaNode) childNode;
379 assertIsAddedByUses(childNode, true);
382 assertNotNull(leafGroupingV);
383 assertFalse(leafGroupingV.isAddedByUses());
385 // grouping-V/container-grouping-V
386 assertNotNull(containerGroupingV);
387 assertFalse(containerGroupingV.isAddedByUses());
388 assertEquals(QName.create(expectedModule, "container-grouping-V"), containerGroupingV.getQName());
389 childNodes = containerGroupingV.getChildNodes();
390 assertEquals(2, childNodes.size());
391 for (final DataSchemaNode childNode : childNodes) {
392 assertIsAddedByUses(childNode, true);
395 // grouping-V/container-grouping-V/leaf-grouping-X
396 final LeafSchemaNode leafXinContainerV = (LeafSchemaNode) containerGroupingV.getDataChildByName(
397 QName.create(namespace, "leaf-grouping-X"));
398 assertEquals(QName.create(expectedModule, "leaf-grouping-X"), leafXinContainerV.getQName());
399 // grouping-V/container-grouping-V/leaf-grouping-Y
400 final LeafSchemaNode leafYinContainerV = (LeafSchemaNode) containerGroupingV.getDataChildByName(
401 QName.create(namespace, "leaf-grouping-Y"));
402 assertEquals(QName.create(expectedModule, "leaf-grouping-Y"), leafYinContainerV.getQName());
405 childNodes = gx.getChildNodes();
406 assertEquals(2, childNodes.size());
408 // grouping-X/leaf-grouping-X
409 final LeafSchemaNode leafXinGX = (LeafSchemaNode) gx.getDataChildByName(
410 QName.create(namespace, "leaf-grouping-X"));
411 assertFalse(leafXinGX.isAddedByUses());
412 assertEquals(QName.create(expectedModule, "leaf-grouping-X"), leafXinGX.getQName());
414 // grouping-X/leaf-grouping-Y
415 final LeafSchemaNode leafYinGX = (LeafSchemaNode) gx.getDataChildByName(
416 QName.create(namespace, "leaf-grouping-Y"));
417 assertTrue(leafYinGX.isAddedByUses());
418 assertEquals(QName.create(expectedModule, "leaf-grouping-Y"), leafYinGX.getQName());
421 childNodes = gy.getChildNodes();
422 assertEquals(1, childNodes.size());
424 // grouping-Y/leaf-grouping-Y
425 final LeafSchemaNode leafYinGY = (LeafSchemaNode) gy.getDataChildByName(
426 QName.create(namespace, "leaf-grouping-Y"));
427 assertFalse(leafYinGY.isAddedByUses());
428 assertEquals(QName.create(expectedModule, "leaf-grouping-Y"), leafYinGY.getQName());
431 childNodes = gz.getChildNodes();
432 assertEquals(1, childNodes.size());
434 // grouping-Z/leaf-grouping-Z
435 final LeafSchemaNode leafZinGZ = (LeafSchemaNode) gz.getDataChildByName(
436 QName.create(namespace, "leaf-grouping-Z"));
437 assertFalse(leafZinGZ.isAddedByUses());
438 assertEquals(QName.create(expectedModule, "leaf-grouping-Z"), leafZinGZ.getQName());
441 childNodes = gzz.getChildNodes();
442 assertEquals(1, childNodes.size());
444 // grouping-ZZ/leaf-grouping-ZZ
445 final LeafSchemaNode leafZZinGZZ = (LeafSchemaNode) gzz.getDataChildByName(
446 QName.create(namespace, "leaf-grouping-ZZ"));
447 assertFalse(leafZZinGZZ.isAddedByUses());
448 assertEquals(QName.create(expectedModule, "leaf-grouping-ZZ"), leafZZinGZZ.getQName());
452 public void testAddedByUsesLeafTypeQName() throws Exception {
453 final EffectiveModelContext loadModules = assertEffectiveModelDir("/added-by-uses-leaf-test");
454 assertEquals(2, loadModules.getModules().size());
456 final Module foo = Iterables.getOnlyElement(loadModules.findModules("foo"));
457 final Module imp = Iterables.getOnlyElement(loadModules.findModules("import-module"));
459 final LeafSchemaNode leaf = (LeafSchemaNode)
460 ((ContainerSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(), "my-container")))
461 .getDataChildByName(QName.create(foo.getQNameModule(), "my-leaf"));
463 TypeDefinition<?> impType = null;
464 for (final TypeDefinition<?> typeDefinition : imp.getTypeDefinitions()) {
465 if (typeDefinition.getQName().getLocalName().equals("imp-type")) {
466 impType = typeDefinition;
471 assertNotNull(impType);
472 assertEquals(leaf.getType().getQName(), impType.getQName());
475 private static void assertIsAddedByUses(final GroupingDefinition node, final boolean expected) {
476 assertEquals(expected, node.isAddedByUses());
477 for (DataSchemaNode child : node.getChildNodes()) {
478 assertIsAddedByUses(child, expected);
483 * Check if node has addedByUses flag set to expected value. In case this is
484 * DataNodeContainer/ChoiceNode, check its child nodes/case nodes too.
486 * @param node node to check
487 * @param expected expected value
489 private static void assertIsAddedByUses(final DataSchemaNode node, final boolean expected) {
490 assertEquals(expected, node.isAddedByUses());
491 if (node instanceof DataNodeContainer) {
492 for (DataSchemaNode child : ((DataNodeContainer) node)
494 assertIsAddedByUses(child, expected);
496 } else if (node instanceof ChoiceSchemaNode) {
497 for (CaseSchemaNode caseNode : ((ChoiceSchemaNode) node).getCases()) {
498 assertIsAddedByUses(caseNode, expected);