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
9 package org.opendaylight.yangtools.yang.data.codec.xml;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
16 import com.google.common.collect.ImmutableList;
17 import java.io.IOException;
18 import java.io.InputStream;
20 import java.net.URISyntaxException;
21 import java.util.Collections;
22 import java.util.HashMap;
24 import javax.xml.parsers.ParserConfigurationException;
25 import javax.xml.stream.XMLInputFactory;
26 import javax.xml.stream.XMLStreamException;
27 import javax.xml.stream.XMLStreamReader;
28 import org.junit.BeforeClass;
29 import org.junit.Test;
30 import org.opendaylight.yangtools.yang.common.QName;
31 import org.opendaylight.yangtools.yang.common.QNameModule;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
36 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
44 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
45 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
46 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
47 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
49 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
50 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
51 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
52 import org.xml.sax.SAXException;
54 public class XmlToNormalizedNodesTest {
56 private static SchemaContext schemaContext;
57 private static ContainerSchemaNode outerContainerSchema;
58 private static ContainerSchemaNode parentContainerSchema;
60 private static QNameModule fooModule;
61 private static QName parentContainer;
63 private static QNameModule bazModule;
64 private static QName outerContainer;
66 private static QName myContainer1;
67 private static QName myKeyedList;
68 private static QName myKeyLeaf;
69 private static QName myLeafInList1;
70 private static QName myLeafInList2;
71 private static QName myLeaf1;
72 private static QName myLeafList;
74 private static QName myContainer2;
75 private static QName innerContainer;
76 private static QName myLeaf2;
77 private static QName myLeaf3;
78 private static QName myChoice;
79 private static QName myLeafInCase2;
81 private static QName myContainer3;
82 private static QName myDoublyKeyedList;
83 private static QName myFirstKeyLeaf;
84 private static QName mySecondKeyLeaf;
85 private static QName myLeafInList3;
88 public static void setup() {
89 fooModule = QNameModule.create(URI.create("foo-namespace"));
90 parentContainer = QName.create(fooModule, "parent-container");
92 bazModule = QNameModule.create(URI.create("baz-namespace"));
93 outerContainer = QName.create(bazModule, "outer-container");
95 myContainer1 = QName.create(bazModule, "my-container-1");
96 myKeyedList = QName.create(bazModule, "my-keyed-list");
97 myKeyLeaf = QName.create(bazModule, "my-key-leaf");
98 myLeafInList1 = QName.create(bazModule, "my-leaf-in-list-1");
99 myLeafInList2 = QName.create(bazModule, "my-leaf-in-list-2");
100 myLeaf1 = QName.create(bazModule, "my-leaf-1");
101 myLeafList = QName.create(bazModule, "my-leaf-list");
103 myContainer2 = QName.create(bazModule, "my-container-2");
104 innerContainer = QName.create(bazModule, "inner-container");
105 myLeaf2 = QName.create(bazModule, "my-leaf-2");
106 myLeaf3 = QName.create(bazModule, "my-leaf-3");
107 myChoice = QName.create(bazModule, "my-choice");
108 myLeafInCase2 = QName.create(bazModule, "my-leaf-in-case-2");
110 myContainer3 = QName.create(bazModule, "my-container-3");
111 myDoublyKeyedList = QName.create(bazModule, "my-doubly-keyed-list");
112 myFirstKeyLeaf = QName.create(bazModule, "my-first-key-leaf");
113 mySecondKeyLeaf = QName.create(bazModule, "my-second-key-leaf");
114 myLeafInList3 = QName.create(bazModule, "my-leaf-in-list-3");
116 schemaContext = YangParserTestUtils.parseYangResourceDirectory("/");
117 parentContainerSchema = (ContainerSchemaNode) SchemaContextUtil.findNodeInSchemaContext(schemaContext,
118 ImmutableList.of(parentContainer));
119 outerContainerSchema = (ContainerSchemaNode) SchemaContextUtil.findNodeInSchemaContext(schemaContext,
120 ImmutableList.of(outerContainer));
124 public void testComplexXmlParsing() throws IOException, URISyntaxException, ReactorException, XMLStreamException,
125 ParserConfigurationException, SAXException {
126 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/baz.xml");
128 final XMLInputFactory factory = XMLInputFactory.newInstance();
129 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
131 final NormalizedNodeResult result = new NormalizedNodeResult();
132 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
134 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
135 xmlParser.parse(reader);
140 final NormalizedNode<?, ?> transformedInput = result.getResult();
141 assertNotNull(transformedInput);
143 final NormalizedNode<?, ?> expectedNormalizedNode = buildOuterContainerNode();
144 assertNotNull(expectedNormalizedNode);
146 assertEquals(expectedNormalizedNode, transformedInput);
150 public void testSimpleXmlParsing() throws IOException, URISyntaxException, ReactorException, XMLStreamException,
151 ParserConfigurationException, SAXException {
152 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/foo.xml");
154 final XMLInputFactory factory = XMLInputFactory.newInstance();
155 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
157 final NormalizedNodeResult result = new NormalizedNodeResult();
158 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
160 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
161 xmlParser.parse(reader);
163 final NormalizedNode<?, ?> transformedInput = result.getResult();
164 assertNotNull(transformedInput);
168 public void shouldFailOnDuplicateLeaf() throws ReactorException, XMLStreamException, IOException,
169 ParserConfigurationException, SAXException, URISyntaxException {
170 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo.xml");
172 final XMLInputFactory factory = XMLInputFactory.newInstance();
173 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
175 final NormalizedNodeResult result = new NormalizedNodeResult();
176 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
178 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
180 xmlParser.parse(reader);
181 fail("IllegalStateException should have been thrown because of duplicate leaf.");
182 } catch (IllegalStateException ex) {
183 assertTrue(ex.getMessage().contains("Duplicate element \"decimal64-leaf\" in XML input"));
189 public void shouldFailOnDuplicateAnyXml() throws ReactorException, XMLStreamException, IOException,
190 ParserConfigurationException, SAXException, URISyntaxException {
191 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo-2.xml");
193 final XMLInputFactory factory = XMLInputFactory.newInstance();
194 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
196 final NormalizedNodeResult result = new NormalizedNodeResult();
197 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
199 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
201 xmlParser.parse(reader);
202 fail("IllegalStateException should have been thrown because of duplicate anyxml");
203 } catch (IllegalStateException ex) {
204 assertTrue(ex.getMessage().contains("Duplicate element \"my-anyxml\" in XML input"));
209 public void shouldFailOnDuplicateContainer() throws ReactorException, XMLStreamException, IOException,
210 ParserConfigurationException, SAXException, URISyntaxException {
211 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo-3.xml");
213 final XMLInputFactory factory = XMLInputFactory.newInstance();
214 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
216 final NormalizedNodeResult result = new NormalizedNodeResult();
217 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
219 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
221 xmlParser.parse(reader);
222 fail("IllegalStateException should have been thrown because of duplicate container");
223 } catch (IllegalStateException ex) {
224 assertTrue(ex.getMessage().contains("Duplicate element \"leaf-container\" in XML input"));
229 public void shouldFailOnUnterminatedLeafElement() throws ReactorException, XMLStreamException, IOException,
230 ParserConfigurationException, SAXException, URISyntaxException {
231 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz.xml");
233 final XMLInputFactory factory = XMLInputFactory.newInstance();
234 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
236 final NormalizedNodeResult result = new NormalizedNodeResult();
237 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
239 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
241 xmlParser.parse(reader);
242 fail("XMLStreamException should have been thrown because of unterminated leaf element.");
243 } catch (XMLStreamException ex) {
244 assertTrue(ex.getMessage().contains("elementGetText() function expects text only elment but "
245 + "START_ELEMENT was encountered."));
250 public void shouldFailOnUnterminatedLeafElement2() throws ReactorException, XMLStreamException, IOException,
251 ParserConfigurationException, SAXException, URISyntaxException {
252 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-2.xml");
254 final XMLInputFactory factory = XMLInputFactory.newInstance();
255 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
257 final NormalizedNodeResult result = new NormalizedNodeResult();
258 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
260 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
262 xmlParser.parse(reader);
263 fail("XMLStreamException should have been thrown because of unterminated leaf element.");
264 } catch (XMLStreamException ex) {
265 assertTrue(ex.getMessage().contains("The element type \"my-leaf-1\" must be terminated by the matching "
266 + "end-tag \"</my-leaf-1>\"."));
271 public void shouldFailOnUnterminatedContainerElement() throws ReactorException, XMLStreamException, IOException,
272 ParserConfigurationException, SAXException, URISyntaxException {
273 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-4.xml");
275 final XMLInputFactory factory = XMLInputFactory.newInstance();
276 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
278 final NormalizedNodeResult result = new NormalizedNodeResult();
279 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
281 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
283 xmlParser.parse(reader);
284 fail("XMLStreamException should have been thrown because of unterminated container element.");
285 } catch (XMLStreamException ex) {
286 assertTrue(ex.getMessage().contains("The element type \"my-container-1\" must be terminated by the "
287 + "matching end-tag \"</my-container-1>\"."));
292 public void shouldFailOnUnknownChildNode() throws ReactorException, XMLStreamException, IOException,
293 ParserConfigurationException, SAXException, URISyntaxException {
294 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-3.xml");
296 final XMLInputFactory factory = XMLInputFactory.newInstance();
297 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
299 final NormalizedNodeResult result = new NormalizedNodeResult();
300 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
302 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
304 xmlParser.parse(reader);
305 fail("IllegalStateException should have been thrown because of an unknown child node.");
306 } catch (IllegalStateException ex) {
307 assertEquals("Schema for node with name my-container-1 and namespace baz-namespace doesn't exist at "
308 + "AbsoluteSchemaPath{path=[(baz-namespace)outer-container, (baz-namespace)my-container-1]}",
313 private NormalizedNode<?, ?> buildOuterContainerNode() {
315 MapNode myKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myKeyedList))
316 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
317 new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue1"))
318 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
319 .withValue("listleafvalue1").build())
320 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
321 .withValue("listleafvalue2").build()).build())
322 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
323 new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue2"))
324 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
325 .withValue("listleafvalue12").build())
326 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
327 .withValue("listleafvalue22").build()).build()).build();
329 LeafNode<?> myLeaf1Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf1))
330 .withValue("value1").build();
332 LeafSetNode<?> myLeafListNode = Builders.leafSetBuilder().withNodeIdentifier(new NodeIdentifier(myLeafList))
333 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
334 new NodeWithValue<>(myLeafList, "lflvalue1")).withValue("lflvalue1").build())
335 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
336 new NodeWithValue<>(myLeafList, "lflvalue2")).withValue("lflvalue2").build()).build();
338 ContainerNode myContainer1Node = Builders.containerBuilder().withNodeIdentifier(
339 new NodeIdentifier(myContainer1))
340 .withChild(myKeyedListNode)
341 .withChild(myLeaf1Node)
342 .withChild(myLeafListNode).build();
345 ContainerNode innerContainerNode = Builders.containerBuilder().withNodeIdentifier(
346 new NodeIdentifier(innerContainer))
347 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf2))
348 .withValue("value2").build()).build();
350 LeafNode<?> myLeaf3Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf3))
351 .withValue("value3").build();
353 ChoiceNode myChoiceNode = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(myChoice))
354 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInCase2))
355 .withValue("case2value").build()).build();
357 ContainerNode myContainer2Node = Builders.containerBuilder().withNodeIdentifier(
358 new NodeIdentifier(myContainer2))
359 .withChild(innerContainerNode)
360 .withChild(myLeaf3Node)
361 .withChild(myChoiceNode).build();
364 Map<QName, Object> keys = new HashMap<>();
365 keys.put(myFirstKeyLeaf, "listkeyvalue1");
366 keys.put(mySecondKeyLeaf, "listkeyvalue2");
368 MapNode myDoublyKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myDoublyKeyedList))
369 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
370 new NodeIdentifierWithPredicates(myDoublyKeyedList, keys))
371 .withChild(Builders.leafBuilder().withNodeIdentifier(
372 new NodeIdentifier(myLeafInList3)).withValue("listleafvalue1").build()).build())
375 AugmentationNode myDoublyKeyedListAugNode = Builders.augmentationBuilder().withNodeIdentifier(
376 new AugmentationIdentifier(Collections.singleton(myDoublyKeyedList)))
377 .withChild(myDoublyKeyedListNode).build();
379 ContainerNode myContainer3Node = Builders.containerBuilder().withNodeIdentifier(
380 new NodeIdentifier(myContainer3))
381 .withChild(myDoublyKeyedListAugNode).build();
383 AugmentationNode myContainer3AugNode = Builders.augmentationBuilder().withNodeIdentifier(
384 new AugmentationIdentifier(Collections.singleton(myContainer3)))
385 .withChild(myContainer3Node).build();
387 ContainerNode outerContainerNode = Builders.containerBuilder().withNodeIdentifier(
388 new NodeIdentifier(outerContainer))
389 .withChild(myContainer1Node)
390 .withChild(myContainer2Node)
391 .withChild(myContainer3AugNode).build();
393 return outerContainerNode;