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.common.SimpleDateFormatUtil;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
36 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
37 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
44 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
45 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
46 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
47 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
48 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
50 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
51 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
52 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
53 import org.xml.sax.SAXException;
55 public class XmlToNormalizedNodesTest {
57 private static SchemaContext schemaContext;
58 private static ContainerSchemaNode outerContainerSchema;
59 private static ContainerSchemaNode parentContainerSchema;
61 private static QNameModule fooModule;
62 private static QName parentContainer;
64 private static QNameModule bazModule;
65 private static QName outerContainer;
67 private static QName myContainer1;
68 private static QName myKeyedList;
69 private static QName myKeyLeaf;
70 private static QName myLeafInList1;
71 private static QName myLeafInList2;
72 private static QName myLeaf1;
73 private static QName myLeafList;
75 private static QName myContainer2;
76 private static QName innerContainer;
77 private static QName myLeaf2;
78 private static QName myLeaf3;
79 private static QName myChoice;
80 private static QName myLeafInCase2;
82 private static QName myContainer3;
83 private static QName myDoublyKeyedList;
84 private static QName myFirstKeyLeaf;
85 private static QName mySecondKeyLeaf;
86 private static QName myLeafInList3;
89 public static void setup() throws Exception {
90 fooModule = QNameModule.create(new URI("foo-namespace"), SimpleDateFormatUtil.getRevisionFormat().parse(
92 parentContainer = QName.create(fooModule, "parent-container");
94 bazModule = QNameModule.create(new URI("baz-namespace"), SimpleDateFormatUtil.getRevisionFormat().parse(
96 outerContainer = QName.create(bazModule, "outer-container");
98 myContainer1 = QName.create(bazModule, "my-container-1");
99 myKeyedList = QName.create(bazModule, "my-keyed-list");
100 myKeyLeaf = QName.create(bazModule, "my-key-leaf");
101 myLeafInList1 = QName.create(bazModule, "my-leaf-in-list-1");
102 myLeafInList2 = QName.create(bazModule, "my-leaf-in-list-2");
103 myLeaf1 = QName.create(bazModule, "my-leaf-1");
104 myLeafList = QName.create(bazModule, "my-leaf-list");
106 myContainer2 = QName.create(bazModule, "my-container-2");
107 innerContainer = QName.create(bazModule, "inner-container");
108 myLeaf2 = QName.create(bazModule, "my-leaf-2");
109 myLeaf3 = QName.create(bazModule, "my-leaf-3");
110 myChoice = QName.create(bazModule, "my-choice");
111 myLeafInCase2 = QName.create(bazModule, "my-leaf-in-case-2");
113 myContainer3 = QName.create(bazModule, "my-container-3");
114 myDoublyKeyedList = QName.create(bazModule, "my-doubly-keyed-list");
115 myFirstKeyLeaf = QName.create(bazModule, "my-first-key-leaf");
116 mySecondKeyLeaf = QName.create(bazModule, "my-second-key-leaf");
117 myLeafInList3 = QName.create(bazModule, "my-leaf-in-list-3");
119 schemaContext = YangParserTestUtils.parseYangResourceDirectory("/");
120 parentContainerSchema = (ContainerSchemaNode) SchemaContextUtil.findNodeInSchemaContext(schemaContext,
121 ImmutableList.of(parentContainer));
122 outerContainerSchema = (ContainerSchemaNode) SchemaContextUtil.findNodeInSchemaContext(schemaContext,
123 ImmutableList.of(outerContainer));
127 public void testComplexXmlParsing() throws IOException, URISyntaxException, ReactorException, XMLStreamException,
128 ParserConfigurationException, SAXException {
129 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/baz.xml");
131 final XMLInputFactory factory = XMLInputFactory.newInstance();
132 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
134 final NormalizedNodeResult result = new NormalizedNodeResult();
135 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
137 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
138 xmlParser.parse(reader);
143 final NormalizedNode<?, ?> transformedInput = result.getResult();
144 assertNotNull(transformedInput);
146 final NormalizedNode<?, ?> expectedNormalizedNode = buildOuterContainerNode();
147 assertNotNull(expectedNormalizedNode);
149 assertEquals(expectedNormalizedNode, transformedInput);
153 public void testSimpleXmlParsing() throws IOException, URISyntaxException, ReactorException, XMLStreamException,
154 ParserConfigurationException, SAXException {
155 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/foo.xml");
157 final XMLInputFactory factory = XMLInputFactory.newInstance();
158 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
160 final NormalizedNodeResult result = new NormalizedNodeResult();
161 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
163 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
164 xmlParser.parse(reader);
166 final NormalizedNode<?, ?> transformedInput = result.getResult();
167 assertNotNull(transformedInput);
171 public void shouldFailOnDuplicateLeaf() throws ReactorException, XMLStreamException, IOException,
172 ParserConfigurationException, SAXException, URISyntaxException {
173 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo.xml");
175 final XMLInputFactory factory = XMLInputFactory.newInstance();
176 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
178 final NormalizedNodeResult result = new NormalizedNodeResult();
179 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
181 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
183 xmlParser.parse(reader);
184 fail("IllegalStateException should have been thrown because of duplicate leaf.");
185 } catch (IllegalStateException ex) {
186 assertTrue(ex.getMessage().contains("Duplicate element \"decimal64-leaf\" in XML input"));
192 public void shouldFailOnDuplicateAnyXml() throws ReactorException, XMLStreamException, IOException,
193 ParserConfigurationException, SAXException, URISyntaxException {
194 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo-2.xml");
196 final XMLInputFactory factory = XMLInputFactory.newInstance();
197 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
199 final NormalizedNodeResult result = new NormalizedNodeResult();
200 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
202 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
204 xmlParser.parse(reader);
205 fail("IllegalStateException should have been thrown because of duplicate anyxml");
206 } catch (IllegalStateException ex) {
207 assertTrue(ex.getMessage().contains("Duplicate element \"my-anyxml\" in XML input"));
212 public void shouldFailOnDuplicateContainer() throws ReactorException, XMLStreamException, IOException,
213 ParserConfigurationException, SAXException, URISyntaxException {
214 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-foo-3.xml");
216 final XMLInputFactory factory = XMLInputFactory.newInstance();
217 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
219 final NormalizedNodeResult result = new NormalizedNodeResult();
220 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
222 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, parentContainerSchema);
224 xmlParser.parse(reader);
225 fail("IllegalStateException should have been thrown because of duplicate container");
226 } catch (IllegalStateException ex) {
227 assertTrue(ex.getMessage().contains("Duplicate element \"leaf-container\" in XML input"));
232 public void shouldFailOnUnterminatedLeafElement() throws ReactorException, XMLStreamException, IOException,
233 ParserConfigurationException, SAXException, URISyntaxException {
234 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz.xml");
236 final XMLInputFactory factory = XMLInputFactory.newInstance();
237 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
239 final NormalizedNodeResult result = new NormalizedNodeResult();
240 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
242 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
244 xmlParser.parse(reader);
245 fail("XMLStreamException should have been thrown because of unterminated leaf element.");
246 } catch (XMLStreamException ex) {
247 assertTrue(ex.getMessage().contains("elementGetText() function expects text only elment but "
248 + "START_ELEMENT was encountered."));
253 public void shouldFailOnUnterminatedLeafElement2() throws ReactorException, XMLStreamException, IOException,
254 ParserConfigurationException, SAXException, URISyntaxException {
255 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-2.xml");
257 final XMLInputFactory factory = XMLInputFactory.newInstance();
258 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
260 final NormalizedNodeResult result = new NormalizedNodeResult();
261 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
263 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
265 xmlParser.parse(reader);
266 fail("XMLStreamException should have been thrown because of unterminated leaf element.");
267 } catch (XMLStreamException ex) {
268 assertTrue(ex.getMessage().contains("The element type \"my-leaf-1\" must be terminated by the matching "
269 + "end-tag \"</my-leaf-1>\"."));
274 public void shouldFailOnUnterminatedContainerElement() throws ReactorException, XMLStreamException, IOException,
275 ParserConfigurationException, SAXException, URISyntaxException {
276 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-4.xml");
278 final XMLInputFactory factory = XMLInputFactory.newInstance();
279 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
281 final NormalizedNodeResult result = new NormalizedNodeResult();
282 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
284 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
286 xmlParser.parse(reader);
287 fail("XMLStreamException should have been thrown because of unterminated container element.");
288 } catch (XMLStreamException ex) {
289 assertTrue(ex.getMessage().contains("The element type \"my-container-1\" must be terminated by the "
290 + "matching end-tag \"</my-container-1>\"."));
295 public void shouldFailOnUnknownChildNode() throws ReactorException, XMLStreamException, IOException,
296 ParserConfigurationException, SAXException, URISyntaxException {
297 final InputStream resourceAsStream = XmlToNormalizedNodesTest.class.getResourceAsStream("/invalid-baz-3.xml");
299 final XMLInputFactory factory = XMLInputFactory.newInstance();
300 final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
302 final NormalizedNodeResult result = new NormalizedNodeResult();
303 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
305 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, outerContainerSchema);
307 xmlParser.parse(reader);
308 fail("IllegalStateException should have been thrown because of an unknown child node.");
309 } catch (IllegalStateException ex) {
310 assertTrue(ex.getMessage().contains("Schema for node with name my-container-1 and namespace baz-namespace"
311 + " doesn't exist."));
315 private NormalizedNode<?, ?> buildOuterContainerNode() {
317 MapNode myKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myKeyedList))
318 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
319 new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue1"))
320 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
321 .withValue("listleafvalue1").build())
322 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
323 .withValue("listleafvalue2").build()).build())
324 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
325 new NodeIdentifierWithPredicates(myKeyedList, myKeyLeaf, "listkeyvalue2"))
326 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList1))
327 .withValue("listleafvalue12").build())
328 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInList2))
329 .withValue("listleafvalue22").build()).build()).build();
331 LeafNode<?> myLeaf1Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf1))
332 .withValue("value1").build();
334 LeafSetNode<?> myLeafListNode = Builders.leafSetBuilder().withNodeIdentifier(new NodeIdentifier(myLeafList))
335 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
336 new NodeWithValue<>(myLeafList, "lflvalue1")).withValue("lflvalue1").build())
337 .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(
338 new NodeWithValue<>(myLeafList, "lflvalue2")).withValue("lflvalue2").build()).build();
340 ContainerNode myContainer1Node = Builders.containerBuilder().withNodeIdentifier(
341 new NodeIdentifier(myContainer1))
342 .withChild(myKeyedListNode)
343 .withChild(myLeaf1Node)
344 .withChild(myLeafListNode).build();
347 ContainerNode innerContainerNode = Builders.containerBuilder().withNodeIdentifier(
348 new NodeIdentifier(innerContainer))
349 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf2))
350 .withValue("value2").build()).build();
352 LeafNode<?> myLeaf3Node = Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeaf3))
353 .withValue("value3").build();
355 ChoiceNode myChoiceNode = Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(myChoice))
356 .withChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(myLeafInCase2))
357 .withValue("case2value").build()).build();
359 ContainerNode myContainer2Node = Builders.containerBuilder().withNodeIdentifier(
360 new NodeIdentifier(myContainer2))
361 .withChild(innerContainerNode)
362 .withChild(myLeaf3Node)
363 .withChild(myChoiceNode).build();
366 Map<QName, Object> keys = new HashMap<>();
367 keys.put(myFirstKeyLeaf, "listkeyvalue1");
368 keys.put(mySecondKeyLeaf, "listkeyvalue2");
370 MapNode myDoublyKeyedListNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(myDoublyKeyedList))
371 .withChild(Builders.mapEntryBuilder().withNodeIdentifier(
372 new NodeIdentifierWithPredicates(myDoublyKeyedList, keys))
373 .withChild(Builders.leafBuilder().withNodeIdentifier(
374 new NodeIdentifier(myLeafInList3)).withValue("listleafvalue1").build()).build())
377 AugmentationNode myDoublyKeyedListAugNode = Builders.augmentationBuilder().withNodeIdentifier(
378 new AugmentationIdentifier(Collections.singleton(myDoublyKeyedList)))
379 .withChild(myDoublyKeyedListNode).build();
381 ContainerNode myContainer3Node = Builders.containerBuilder().withNodeIdentifier(
382 new NodeIdentifier(myContainer3))
383 .withChild(myDoublyKeyedListAugNode).build();
385 AugmentationNode myContainer3AugNode = Builders.augmentationBuilder().withNodeIdentifier(
386 new AugmentationIdentifier(Collections.singleton(myContainer3)))
387 .withChild(myContainer3Node).build();
389 ContainerNode outerContainerNode = Builders.containerBuilder().withNodeIdentifier(
390 new NodeIdentifier(outerContainer))
391 .withChild(myContainer1Node)
392 .withChild(myContainer2Node)
393 .withChild(myContainer3AugNode).build();
395 return outerContainerNode;