Always use lazy leaf nodes
[yangtools.git] / yang / yang-data-jaxen / src / test / java / org / opendaylight / yangtools / yang / data / jaxen / DerefXPathFunctionTest.java
1 /*
2  * Copyright (c) 2017 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
9 package org.opendaylight.yangtools.yang.data.jaxen;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertSame;
14 import static org.junit.Assert.assertTrue;
15
16 import com.google.common.collect.BiMap;
17 import com.google.common.collect.HashBiMap;
18 import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.ImmutableMap;
20 import com.google.common.collect.Maps;
21 import java.net.URI;
22 import java.util.Map;
23 import org.jaxen.Function;
24 import org.junit.Test;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.common.QNameModule;
27 import org.opendaylight.yangtools.yang.common.Revision;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
32 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
38 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
39 import org.opendaylight.yangtools.yang.data.jaxen.api.XPathDocument;
40 import org.opendaylight.yangtools.yang.data.jaxen.api.XPathSchemaContext;
41 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
42 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
43
44 public class DerefXPathFunctionTest {
45
46     private static JaxenSchemaContextFactory jaxenSchemaContextFactory = new JaxenSchemaContextFactory();
47
48     private static final QNameModule FOO_MODULE = QNameModule.create(URI.create("foo-ns"), Revision.of("2017-04-03"));
49     private static final QName MY_CONTAINER = QName.create(FOO_MODULE, "my-container");
50     private static final QName MY_INNER_CONTAINER = QName.create(FOO_MODULE, "my-inner-container");
51     private static final QName MY_LIST = QName.create(FOO_MODULE, "my-list");
52     private static final QName KEY_LEAF_A = QName.create(FOO_MODULE, "key-leaf-a");
53     private static final QName KEY_LEAF_B = QName.create(FOO_MODULE, "key-leaf-b");
54     private static final QName IID_LEAF = QName.create(FOO_MODULE, "iid-leaf");
55     private static final QName REFERENCED_LEAF = QName.create(FOO_MODULE, "referenced-leaf");
56     private static final QName REFERENCED_LEAFLIST = QName.create(FOO_MODULE, "referenced-leaf-list");
57     private static final QName ABS_LEAFREF_LEAF = QName.create(FOO_MODULE, "abs-leafref-leaf");
58     private static final QName REL_LEAFREF_LEAF = QName.create(FOO_MODULE, "rel-leafref-leaf");
59     private static final QName LEAFLIST_LEAFREF_LEAF = QName.create(FOO_MODULE, "leaf-list-leafref-leaf");
60     private static final QName ORDINARY_LEAF_A = QName.create(FOO_MODULE, "ordinary-leaf-a");
61     private static final QName ORDINARY_LEAF_B = QName.create(FOO_MODULE, "ordinary-leaf-b");
62
63     @Test
64     public void testDerefFunctionForInstanceIdentifier() throws Exception {
65         final EffectiveModelContext schemaContext = YangParserTestUtils.parseYangResources(DerefXPathFunctionTest.class,
66                 "/yang-xpath-functions-test/deref-function-iid/foo.yang");
67         assertNotNull(schemaContext);
68
69         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
70
71         final LeafNode<?> referencedLeafNode = Builders.leafBuilder().withNodeIdentifier(
72             new NodeIdentifier(REFERENCED_LEAF)).withValue("referenced-leaf-node-value").build();
73
74         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNodeForIIdTest(
75             referencedLeafNode));
76
77         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
78         converterBiMap.put("foo-prefix", FOO_MODULE);
79
80         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
81                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
82
83         final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(
84                 buildPathToIIdLeafNode());
85
86         final Function derefFunction = normalizedNodeContextSupport.getFunctionContext()
87                 .getFunction(null, null, "deref");
88         final Object derefResult = derefFunction.call(normalizedNodeContext, ImmutableList.of());
89         assertNotNull(derefResult);
90         assertTrue(derefResult instanceof LeafNode<?>);
91         assertEquals(referencedLeafNode, derefResult);
92     }
93
94     @Test
95     public void testDerefFunctionForLeafref() throws Exception {
96         // tests absolute and relative leafref that references a leaf node
97         final EffectiveModelContext schemaContext = YangParserTestUtils.parseYangResources(DerefXPathFunctionTest.class,
98                 "/yang-xpath-functions-test/deref-function-leafref/foo.yang");
99         assertNotNull(schemaContext);
100
101         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
102
103         final LeafNode<?> referencedLeafNode = Builders.leafBuilder().withNodeIdentifier(
104                 new NodeIdentifier(REFERENCED_LEAF)).withValue("referenced-leaf-node-value").build();
105
106         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNodeForLeafrefTest(
107                 referencedLeafNode));
108
109         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
110         converterBiMap.put("foo-prefix", FOO_MODULE);
111
112         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
113                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
114
115         final YangInstanceIdentifier absLeafrefPath = YangInstanceIdentifier.of(MY_INNER_CONTAINER)
116                 .node(ABS_LEAFREF_LEAF);
117         NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport.createContext(absLeafrefPath);
118
119         final Function derefFunction = normalizedNodeContextSupport.getFunctionContext()
120                 .getFunction(null, null, "deref");
121         Object derefResult = derefFunction.call(normalizedNodeContext, ImmutableList.of());
122         assertNotNull(derefResult);
123         assertTrue(derefResult instanceof LeafNode<?>);
124         assertEquals(referencedLeafNode, derefResult);
125
126         final YangInstanceIdentifier relLeafrefPath = YangInstanceIdentifier.of(MY_INNER_CONTAINER)
127                 .node(REL_LEAFREF_LEAF);
128         normalizedNodeContext = normalizedNodeContextSupport.createContext(relLeafrefPath);
129
130         derefResult = derefFunction.call(normalizedNodeContext, ImmutableList.of());
131         assertNotNull(derefResult);
132         assertTrue(derefResult instanceof LeafNode<?>);
133         assertEquals(referencedLeafNode, derefResult);
134     }
135
136     @Test
137     public void testDerefFunctionForLeafref2() throws Exception {
138         // tests leafref that references a leaf-list node
139         final EffectiveModelContext schemaContext = YangParserTestUtils.parseYangResources(DerefXPathFunctionTest.class,
140                 "/yang-xpath-functions-test/deref-function-leafref/foo.yang");
141         assertNotNull(schemaContext);
142
143         final XPathSchemaContext jaxenSchemaContext = jaxenSchemaContextFactory.createContext(schemaContext);
144
145         final LeafSetNode<?> referencedLeafListNode = Builders.leafSetBuilder().withNodeIdentifier(
146                 new NodeIdentifier(REFERENCED_LEAFLIST))
147                 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
148                         new NodeWithValue<>(REFERENCED_LEAFLIST, "referenced-node-entry-value-a"))
149                         .withValue("referenced-node-entry-value-a").build())
150                 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
151                         new NodeWithValue<>(REFERENCED_LEAFLIST, "referenced-node-entry-value-b"))
152                         .withValue("referenced-node-entry-value-b").build())
153                 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
154                         new NodeWithValue<>(REFERENCED_LEAFLIST, "referenced-node-entry-value-c"))
155                         .withValue("referenced-node-entry-value-c").build())
156                 .build();
157
158         final XPathDocument jaxenDocument = jaxenSchemaContext.createDocument(buildMyContainerNodeForLeafrefTest(
159                 referencedLeafListNode));
160
161         final BiMap<String, QNameModule> converterBiMap = HashBiMap.create();
162         converterBiMap.put("foo-prefix", FOO_MODULE);
163
164         final NormalizedNodeContextSupport normalizedNodeContextSupport = NormalizedNodeContextSupport.create(
165                 (JaxenDocument) jaxenDocument, Maps.asConverter(converterBiMap));
166
167         final YangInstanceIdentifier leafListLeafrefPath = YangInstanceIdentifier.of(MY_INNER_CONTAINER)
168                 .node(LEAFLIST_LEAFREF_LEAF);
169         final NormalizedNodeContext normalizedNodeContext = normalizedNodeContextSupport
170                 .createContext(leafListLeafrefPath);
171
172         final Function derefFunction = normalizedNodeContextSupport.getFunctionContext()
173                 .getFunction(null, null, "deref");
174         Object derefResult = derefFunction.call(normalizedNodeContext, ImmutableList.of());
175         assertNotNull(derefResult);
176         assertTrue(derefResult instanceof NormalizedNode<?, ?>);
177
178         final LeafSetEntryNode<?> referencedLeafListNodeEntry = referencedLeafListNode.getChild(
179                 new NodeWithValue<>(REFERENCED_LEAFLIST, "referenced-node-entry-value-b")).get();
180         assertSame(referencedLeafListNodeEntry, derefResult);
181     }
182
183     private static ContainerNode buildMyContainerNodeForIIdTest(final LeafNode<?> referencedLeafNode) {
184         final Map<QName, Object> keyValues = ImmutableMap.of(KEY_LEAF_A, "key-value-a", KEY_LEAF_B, "key-value-b");
185         final YangInstanceIdentifier iidPath = YangInstanceIdentifier.of(MY_CONTAINER).node(MY_LIST)
186                 .node(NodeIdentifierWithPredicates.of(MY_LIST, keyValues)).node(REFERENCED_LEAF);
187
188         final LeafNode<?> iidLeafNode = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(IID_LEAF))
189                 .withValue(iidPath).build();
190
191         final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(MY_LIST))
192                 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
193                         NodeIdentifierWithPredicates.of(MY_LIST, keyValues))
194                         .withChild(iidLeafNode)
195                         .withChild(referencedLeafNode).build())
196                 .build();
197
198         final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
199                 new NodeIdentifier(MY_CONTAINER)).withChild(myListNode).build();
200         return myContainerNode;
201     }
202
203     private static YangInstanceIdentifier buildPathToIIdLeafNode() {
204         final Map<QName, Object> keyValues = ImmutableMap.of(KEY_LEAF_A, "key-value-a", KEY_LEAF_B, "key-value-b");
205         final YangInstanceIdentifier path = YangInstanceIdentifier.of(MY_LIST)
206                 .node(NodeIdentifierWithPredicates.of(MY_LIST, keyValues)).node(IID_LEAF);
207         return path;
208     }
209
210     // variant for a leafref that references a leaf
211     private static ContainerNode buildMyContainerNodeForLeafrefTest(final LeafNode<?> referencedLeafNode) {
212         final Map<QName, Object> keyValues = ImmutableMap.of(KEY_LEAF_A, "value-a", KEY_LEAF_B, "value-b");
213
214         final LeafNode<?> absLeafrefNode = Builders.leafBuilder()
215                 .withNodeIdentifier(new NodeIdentifier(ABS_LEAFREF_LEAF))
216                 .withValue("referenced-leaf-node-value").build();
217         final LeafNode<?> relLeafrefNode = Builders.leafBuilder()
218                 .withNodeIdentifier(new NodeIdentifier(REL_LEAFREF_LEAF))
219                 .withValue("referenced-leaf-node-value").build();
220         final LeafNode<?> ordinaryLeafANode = Builders.leafBuilder().withNodeIdentifier(
221                 new NodeIdentifier(ORDINARY_LEAF_A)).withValue("value-a").build();
222         final LeafNode<?> ordinaryLeafBNode = Builders.leafBuilder().withNodeIdentifier(
223                 new NodeIdentifier(ORDINARY_LEAF_B)).withValue("value-b").build();
224
225         final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(MY_LIST))
226                 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
227                         NodeIdentifierWithPredicates.of(MY_LIST, keyValues))
228                         .withChild(referencedLeafNode).build())
229                 .build();
230
231         final ContainerNode myInnerContainerNode = Builders.containerBuilder().withNodeIdentifier(
232                 new NodeIdentifier(MY_INNER_CONTAINER))
233                 .withChild(absLeafrefNode)
234                 .withChild(relLeafrefNode)
235                 .withChild(ordinaryLeafANode)
236                 .withChild(ordinaryLeafBNode).build();
237
238         final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
239                 new NodeIdentifier(MY_CONTAINER))
240                 .withChild(myListNode)
241                 .withChild(myInnerContainerNode).build();
242         return myContainerNode;
243     }
244
245     // variant for a leafref that references a leaf-list
246     private static ContainerNode buildMyContainerNodeForLeafrefTest(final LeafSetNode<?> referencedLeafListNode) {
247         final LeafNode<?> leafListLeafrefNode = Builders.leafBuilder().withNodeIdentifier(
248                 new NodeIdentifier(LEAFLIST_LEAFREF_LEAF)).withValue("referenced-node-entry-value-b").build();
249
250         final LeafNode<?> ordinaryLeafANode = Builders.leafBuilder().withNodeIdentifier(
251                 new NodeIdentifier(ORDINARY_LEAF_A)).withValue("value-a").build();
252         final LeafNode<?> ordinaryLeafBNode = Builders.leafBuilder().withNodeIdentifier(
253                 new NodeIdentifier(ORDINARY_LEAF_B)).withValue("value-b").build();
254
255         final ContainerNode myInnerContainerNode = Builders.containerBuilder().withNodeIdentifier(
256                 new NodeIdentifier(MY_INNER_CONTAINER))
257                 .withChild(leafListLeafrefNode)
258                 .withChild(ordinaryLeafANode)
259                 .withChild(ordinaryLeafBNode).build();
260
261         final Map<QName, Object> keyValues = ImmutableMap.of(KEY_LEAF_A, "value-a", KEY_LEAF_B, "value-b");
262
263         final MapNode myListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(MY_LIST))
264                 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
265                         NodeIdentifierWithPredicates.of(MY_LIST, keyValues))
266                         .withChild(referencedLeafListNode).build())
267                 .build();
268
269         final ContainerNode myContainerNode = Builders.containerBuilder().withNodeIdentifier(
270                 new NodeIdentifier(MY_CONTAINER))
271                 .withChild(myListNode)
272                 .withChild(myInnerContainerNode).build();
273         return myContainerNode;
274     }
275 }