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