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 assertTrue(ex.getMessage().contains("Schema for node with name my-container-1 and namespace baz-namespace"
308 + " doesn't exist."));
312 private 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;