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.test.util.YangParserTestUtils;
51 import org.xml.sax.SAXException;
53 public class XmlToNormalizedNodesTest {
55 private static SchemaContext schemaContext;
56 private static ContainerSchemaNode outerContainerSchema;
57 private static ContainerSchemaNode parentContainerSchema;
59 private static QNameModule fooModule;
60 private static QName parentContainer;
62 private static QNameModule bazModule;
63 private static QName outerContainer;
65 private static QName myContainer1;
66 private static QName myKeyedList;
67 private static QName myKeyLeaf;
68 private static QName myLeafInList1;
69 private static QName myLeafInList2;
70 private static QName myLeaf1;
71 private static QName myLeafList;
73 private static QName myContainer2;
74 private static QName innerContainer;
75 private static QName myLeaf2;
76 private static QName myLeaf3;
77 private static QName myChoice;
78 private static QName myLeafInCase2;
80 private static QName myContainer3;
81 private static QName myDoublyKeyedList;
82 private static QName myFirstKeyLeaf;
83 private static QName mySecondKeyLeaf;
84 private static QName myLeafInList3;
87 public static void setup() {
88 fooModule = QNameModule.create(URI.create("foo-namespace"));
89 parentContainer = QName.create(fooModule, "parent-container");
91 bazModule = QNameModule.create(URI.create("baz-namespace"));
92 outerContainer = QName.create(bazModule, "outer-container");
94 myContainer1 = QName.create(bazModule, "my-container-1");
95 myKeyedList = QName.create(bazModule, "my-keyed-list");
96 myKeyLeaf = QName.create(bazModule, "my-key-leaf");
97 myLeafInList1 = QName.create(bazModule, "my-leaf-in-list-1");
98 myLeafInList2 = QName.create(bazModule, "my-leaf-in-list-2");
99 myLeaf1 = QName.create(bazModule, "my-leaf-1");
100 myLeafList = QName.create(bazModule, "my-leaf-list");
102 myContainer2 = QName.create(bazModule, "my-container-2");
103 innerContainer = QName.create(bazModule, "inner-container");
104 myLeaf2 = QName.create(bazModule, "my-leaf-2");
105 myLeaf3 = QName.create(bazModule, "my-leaf-3");
106 myChoice = QName.create(bazModule, "my-choice");
107 myLeafInCase2 = QName.create(bazModule, "my-leaf-in-case-2");
109 myContainer3 = QName.create(bazModule, "my-container-3");
110 myDoublyKeyedList = QName.create(bazModule, "my-doubly-keyed-list");
111 myFirstKeyLeaf = QName.create(bazModule, "my-first-key-leaf");
112 mySecondKeyLeaf = QName.create(bazModule, "my-second-key-leaf");
113 myLeafInList3 = QName.create(bazModule, "my-leaf-in-list-3");
115 schemaContext = YangParserTestUtils.parseYangResourceDirectory("/");
116 parentContainerSchema = (ContainerSchemaNode) SchemaContextUtil.findNodeInSchemaContext(schemaContext,
117 ImmutableList.of(parentContainer));
118 outerContainerSchema = (ContainerSchemaNode) SchemaContextUtil.findNodeInSchemaContext(schemaContext,
119 ImmutableList.of(outerContainer));
123 public void testComplexXmlParsing() throws IOException, SAXException, URISyntaxException, XMLStreamException,
124 ParserConfigurationException {
125 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/baz.xml");
127 final XMLInputFactory factory = XMLInputFactory.newInstance();
128 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
130 final NormalizedNodeResult result = new NormalizedNodeResult();
131 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
133 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
134 xmlParser.parse(reader);
139 final NormalizedNode<?, ?> transformedInput = result.getResult();
140 assertNotNull(transformedInput);
142 final NormalizedNode<?, ?> expectedNormalizedNode = buildOuterContainerNode();
143 assertNotNull(expectedNormalizedNode);
145 assertEquals(expectedNormalizedNode, transformedInput);
149 public void testSimpleXmlParsing() throws IOException, URISyntaxException, XMLStreamException,
150 ParserConfigurationException, SAXException {
151 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/foo.xml");
153 final XMLInputFactory factory = XMLInputFactory.newInstance();
154 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
156 final NormalizedNodeResult result = new NormalizedNodeResult();
157 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
159 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
160 xmlParser.parse(reader);
162 final NormalizedNode<?, ?> transformedInput = result.getResult();
163 assertNotNull(transformedInput);
167 public void shouldFailOnDuplicateLeaf() throws XMLStreamException, IOException,
168 ParserConfigurationException, SAXException, URISyntaxException {
169 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo.xml");
171 final XMLInputFactory factory = XMLInputFactory.newInstance();
172 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
174 final NormalizedNodeResult result = new NormalizedNodeResult();
175 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
177 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
179 xmlParser.parse(reader);
180 fail("IllegalStateException should have been thrown because of duplicate leaf.");
181 } catch (IllegalStateException ex) {
182 assertTrue(ex.getMessage().contains("Duplicate element \"decimal64-leaf\" in XML input"));
188 public void shouldFailOnDuplicateAnyXml() throws XMLStreamException, IOException,
189 ParserConfigurationException, SAXException, URISyntaxException {
190 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo-2.xml");
192 final XMLInputFactory factory = XMLInputFactory.newInstance();
193 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
195 final NormalizedNodeResult result = new NormalizedNodeResult();
196 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
198 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
200 xmlParser.parse(reader);
201 fail("IllegalStateException should have been thrown because of duplicate anyxml");
202 } catch (IllegalStateException ex) {
203 assertTrue(ex.getMessage().contains("Duplicate element \"my-anyxml\" in XML input"));
208 public void shouldFailOnDuplicateContainer() throws XMLStreamException, IOException,
209 ParserConfigurationException, SAXException, URISyntaxException {
210 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo-3.xml");
212 final XMLInputFactory factory = XMLInputFactory.newInstance();
213 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
215 final NormalizedNodeResult result = new NormalizedNodeResult();
216 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
218 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
220 xmlParser.parse(reader);
221 fail("IllegalStateException should have been thrown because of duplicate container");
222 } catch (IllegalStateException ex) {
223 assertTrue(ex.getMessage().contains("Duplicate element \"leaf-container\" in XML input"));
228 public void shouldFailOnUnterminatedLeafElement() throws XMLStreamException, IOException,
229 ParserConfigurationException, SAXException, URISyntaxException {
230 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz.xml");
232 final XMLInputFactory factory = XMLInputFactory.newInstance();
233 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
235 final NormalizedNodeResult result = new NormalizedNodeResult();
236 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
238 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
240 xmlParser.parse(reader);
241 fail("XMLStreamException should have been thrown because of unterminated leaf element.");
242 } catch (XMLStreamException ex) {
243 assertTrue(ex.getMessage().contains("elementGetText() function expects text only elment but "
244 + "START_ELEMENT was encountered."));
249 public void shouldFailOnUnterminatedLeafElement2() throws XMLStreamException, IOException,
250 ParserConfigurationException, SAXException, URISyntaxException {
251 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-2.xml");
253 final XMLInputFactory factory = XMLInputFactory.newInstance();
254 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
256 final NormalizedNodeResult result = new NormalizedNodeResult();
257 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
259 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
261 xmlParser.parse(reader);
262 fail("XMLStreamException should have been thrown because of unterminated leaf element.");
263 } catch (XMLStreamException ex) {
264 assertTrue(ex.getMessage().contains("The element type \"my-leaf-1\" must be terminated by the matching "
265 + "end-tag \"</my-leaf-1>\"."));
270 public void shouldFailOnUnterminatedContainerElement() throws XMLStreamException, IOException,
271 ParserConfigurationException, SAXException, URISyntaxException {
272 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-4.xml");
274 final XMLInputFactory factory = XMLInputFactory.newInstance();
275 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
277 final NormalizedNodeResult result = new NormalizedNodeResult();
278 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
280 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
282 xmlParser.parse(reader);
283 fail("XMLStreamException should have been thrown because of unterminated container element.");
284 } catch (XMLStreamException ex) {
285 assertTrue(ex.getMessage().contains("The element type \"my-container-1\" must be terminated by the "
286 + "matching end-tag \"</my-container-1>\"."));
291 public void shouldFailOnUnknownChildNode() throws XMLStreamException, IOException,
292 ParserConfigurationException, SAXException, URISyntaxException {
293 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-3.xml");
295 final XMLInputFactory factory = XMLInputFactory.newInstance();
296 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
298 final NormalizedNodeResult result = new NormalizedNodeResult();
299 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
301 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
303 xmlParser.parse(reader);
304 fail("IllegalStateException should have been thrown because of an unknown child node.");
305 } catch (IllegalStateException ex) {
306 assertEquals("Schema for node with name my-container-1 and namespace baz-namespace doesn't exist at "
307 + "AbsoluteSchemaPath{path=[(baz-namespace)outer-container, (baz-namespace)my-container-1]}",
312 private static NormalizedNode<?, ?> buildOuterContainerNode() {
314 MapNode myKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myKeyedList))
315 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
316 new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue1"))
317 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
318 .withValue("listleafvalue1").build())
319 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
320 .withValue("listleafvalue2").build()).build())
321 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
322 new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue2"))
323 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
324 .withValue("listleafvalue12").build())
325 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
326 .withValue("listleafvalue22").build()).build()).build();
328 LeafNode<?> myLeaf1Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf1))
329 .withValue("value1").build();
331 LeafSetNode<?> myLeafListNode = Builders.leafSetBuilder().withNodeIdentifier(new NodeIdentifier(myLeafList))
332 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
333 new NodeWithValue<>(myLeafList, "lflvalue1")).withValue("lflvalue1").build())
334 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
335 new NodeWithValue<>(myLeafList, "lflvalue2")).withValue("lflvalue2").build()).build();
337 ContainerNode myContainer1Node = Builders.containerBuilder().withNodeIdentifier(
338 new NodeIdentifier(myContainer1))
339 .withChild(myKeyedListNode)
340 .withChild(myLeaf1Node)
341 .withChild(myLeafListNode).build();
344 ContainerNode innerContainerNode = Builders.containerBuilder().withNodeIdentifier(
345 new NodeIdentifier(innerContainer))
346 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf2))
347 .withValue("value2").build()).build();
349 LeafNode<?> myLeaf3Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf3))
350 .withValue("value3").build();
352 ChoiceNode myChoiceNode = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(myChoice))
353 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInCase2))
354 .withValue("case2value").build()).build();
356 ContainerNode myContainer2Node = Builders.containerBuilder().withNodeIdentifier(
357 new NodeIdentifier(myContainer2))
358 .withChild(innerContainerNode)
359 .withChild(myLeaf3Node)
360 .withChild(myChoiceNode).build();
363 Map<QName, Object> keys = new HashMap<>();
364 keys.put(myFirstKeyLeaf, "listkeyvalue1");
365 keys.put(mySecondKeyLeaf, "listkeyvalue2");
367 MapNode myDoublyKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myDoublyKeyedList))
368 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
369 new NodeIdentifierWithPredicates(myDoublyKeyedList, keys))
370 .withChild(Builders.leafBuilder().withNodeIdentifier(
371 new NodeIdentifier(myLeafInList3)).withValue("listleafvalue1").build()).build())
374 AugmentationNode myDoublyKeyedListAugNode = Builders.augmentationBuilder().withNodeIdentifier(
375 new AugmentationIdentifier(Collections.singleton(myDoublyKeyedList)))
376 .withChild(myDoublyKeyedListNode).build();
378 ContainerNode myContainer3Node = Builders.containerBuilder().withNodeIdentifier(
379 new NodeIdentifier(myContainer3))
380 .withChild(myDoublyKeyedListAugNode).build();
382 AugmentationNode myContainer3AugNode = Builders.augmentationBuilder().withNodeIdentifier(
383 new AugmentationIdentifier(Collections.singleton(myContainer3)))
384 .withChild(myContainer3Node).build();
386 ContainerNode outerContainerNode = Builders.containerBuilder().withNodeIdentifier(
387 new NodeIdentifier(outerContainer))
388 .withChild(myContainer1Node)
389 .withChild(myContainer2Node)
390 .withChild(myContainer3AugNode).build();
392 return outerContainerNode;