Attach aggragate javadocs to aggragator
[yangtools.git] / yang / yang-data-codec-xml / src / test / java / org / opendaylight / yangtools / yang / data / codec / xml / XmlStreamUtilsTest.java
1 /*
2  * Copyright (c) 2016 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.codec.xml;
10
11 import static org.hamcrest.CoreMatchers.containsString;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertThat;
15 import static org.junit.Assert.assertTrue;
16
17 import java.io.ByteArrayOutputStream;
18 import java.net.URI;
19 import java.util.AbstractMap;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.Optional;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25 import javax.xml.stream.XMLOutputFactory;
26 import javax.xml.stream.XMLStreamWriter;
27 import org.custommonkey.xmlunit.Diff;
28 import org.custommonkey.xmlunit.XMLUnit;
29 import org.junit.AfterClass;
30 import org.junit.BeforeClass;
31 import org.junit.Ignore;
32 import org.junit.Test;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.common.QNameModule;
35 import org.opendaylight.yangtools.yang.common.Revision;
36 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
37 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.Module;
40 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
41 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
42 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
43 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
44 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
45 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
46 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
47 import org.w3c.dom.Document;
48
49 public class XmlStreamUtilsTest {
50
51     public static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newFactory();
52
53     private static SchemaContext schemaContext;
54     private static Module leafRefModule;
55
56     @BeforeClass
57     public static void initialize() {
58         schemaContext = YangParserTestUtils.parseYangResource("/leafref-test.yang");
59         assertNotNull(schemaContext);
60         assertEquals(1, schemaContext.getModules().size());
61         leafRefModule = schemaContext.getModules().iterator().next();
62         assertNotNull(leafRefModule);
63     }
64
65     @AfterClass
66     public static void cleanup() {
67         leafRefModule = null;
68         schemaContext = null;
69     }
70
71     @Test
72     public void testWriteAttribute() throws Exception {
73         final ByteArrayOutputStream out = new ByteArrayOutputStream();
74         final XMLStreamWriter writer = XML_OUTPUT_FACTORY.createXMLStreamWriter(out);
75         writer.writeStartElement("element");
76
77         QName name = getAttrQName("namespace", "2012-12-12", "attr", Optional.of("prefix"));
78         final Map.Entry<QName, String> attributeEntry = new AbstractMap.SimpleEntry<>(name, "value");
79
80         name = getAttrQName("namespace2", "2012-12-12", "attr", Optional.empty());
81         final Map.Entry<QName, String> attributeEntryNoPrefix = new AbstractMap.SimpleEntry<>(name, "value");
82
83         final RandomPrefix randomPrefix = new RandomPrefix(null);
84         XMLStreamWriterUtils.writeAttribute(writer, attributeEntry, randomPrefix);
85         XMLStreamWriterUtils.writeAttribute(writer, attributeEntryNoPrefix, randomPrefix);
86
87         writer.writeEndElement();
88         writer.close();
89         out.close();
90
91         final String xmlAsString = new String(out.toByteArray());
92
93         final Map<String, String> mappedPrefixes = mapPrefixed(randomPrefix.getPrefixes());
94         assertEquals(2, mappedPrefixes.size());
95         final String randomPrefixValue = mappedPrefixes.get("namespace2");
96
97         final String expectedXmlAsString = "<element xmlns:a=\"namespace\" a:attr=\"value\" xmlns:" + randomPrefixValue
98                 + "=\"namespace2\" " + randomPrefixValue + ":attr=\"value\"></element>";
99
100         XMLUnit.setIgnoreAttributeOrder(true);
101         final Document control = XMLUnit.buildControlDocument(expectedXmlAsString);
102         final Document test = XMLUnit.buildTestDocument(xmlAsString);
103         final Diff diff = XMLUnit.compareXML(control, test);
104
105         final boolean identical = diff.identical();
106         assertTrue("Xml differs: " + diff.toString(), identical);
107     }
108
109     @Test
110     public void testWriteIdentityRef() throws Exception {
111         final ByteArrayOutputStream out = new ByteArrayOutputStream();
112         final XMLStreamWriter writer = XML_OUTPUT_FACTORY.createXMLStreamWriter(out);
113
114         writer.writeStartElement("element");
115         final QNameModule parent = QNameModule.create(URI.create("parent:uri"), Revision.of("2000-01-01"));
116         XMLStreamWriterUtils.write(writer, null, QName.create(parent, "identity"), parent);
117         writer.writeEndElement();
118
119         writer.writeStartElement("elementDifferent");
120         XMLStreamWriterUtils.write(writer, null, QName.create("different:namespace", "identity"), parent);
121         writer.writeEndElement();
122
123         writer.close();
124         out.close();
125
126         final String xmlAsString = new String(out.toByteArray()).replaceAll("\\s*", "");
127         assertThat(xmlAsString, containsString("element>identity"));
128
129         final Pattern prefixedIdentityPattern = Pattern.compile(".*\"different:namespace\">(.*):identity.*");
130         final Matcher matcher = prefixedIdentityPattern.matcher(xmlAsString);
131         assertTrue("Xml: " + xmlAsString + " should match: " + prefixedIdentityPattern, matcher.matches());
132     }
133
134     /**
135      * One leafref reference to other leafref via relative references.
136      */
137     @Test
138     public void testLeafRefRelativeChaining() {
139         getTargetNodeForLeafRef("leafname3", StringTypeDefinition.class);
140     }
141
142     @Test
143     public void testLeafRefRelative() {
144         getTargetNodeForLeafRef("pointToStringLeaf", StringTypeDefinition.class);
145     }
146
147     @Test
148     public void testLeafRefAbsoluteWithSameTarget() {
149         getTargetNodeForLeafRef("absname", InstanceIdentifierTypeDefinition.class);
150     }
151
152     /**
153      * Tests relative path with double point inside path (e. g. "../../lf:interface/../lf:cont2/lf:stringleaf")
154      */
155     // ignored because this isn't implemented
156     @Ignore
157     @Test
158     public void testLeafRefWithDoublePointInPath() {
159         getTargetNodeForLeafRef("lf-with-double-point-inside", StringTypeDefinition.class);
160     }
161
162     @Test
163     public void testLeafRefRelativeAndAbsoluteWithSameTarget() {
164         final TypeDefinition<?> targetNodeForAbsname = getTargetNodeForLeafRef("absname",
165             InstanceIdentifierTypeDefinition.class);
166         final TypeDefinition<?> targetNodeForRelname = getTargetNodeForLeafRef("relname",
167             InstanceIdentifierTypeDefinition.class);
168         assertEquals(targetNodeForAbsname, targetNodeForRelname);
169     }
170
171     private TypeDefinition<?> getTargetNodeForLeafRef(final String nodeName, final Class<?> clas) {
172         final LeafSchemaNode schemaNode = findSchemaNodeWithLeafrefType(leafRefModule, nodeName);
173         assertNotNull(schemaNode);
174         final LeafrefTypeDefinition leafrefTypedef = findLeafrefType(schemaNode);
175         assertNotNull(leafrefTypedef);
176         final TypeDefinition<?> targetBaseType = SchemaContextUtil.getBaseTypeForLeafRef(leafrefTypedef, schemaContext,
177                 schemaNode);
178         assertTrue("Wrong class found.", clas.isInstance(targetBaseType));
179         return targetBaseType;
180     }
181
182     private static Map<String, String> mapPrefixed(final Iterable<Map.Entry<URI, String>> prefixes) {
183         final Map<String, String> mappedPrefixes = new HashMap<>();
184         for (final Map.Entry<URI, String> prefix : prefixes) {
185             mappedPrefixes.put(prefix.getKey().toString(), prefix.getValue());
186         }
187         return mappedPrefixes;
188     }
189
190     private static QName getAttrQName(final String namespace, final String revision, final String localName,
191             final Optional<String> prefix) {
192         if (prefix.isPresent()) {
193             final QName moduleQName = QName.create(namespace, revision, "module");
194             final QNameModule module = QNameModule.create(moduleQName.getNamespace(), moduleQName.getRevision());
195             return QName.create(module, localName);
196         }
197         return QName.create(namespace, revision, localName);
198     }
199
200     private LeafSchemaNode findSchemaNodeWithLeafrefType(final DataNodeContainer module, final String nodeName) {
201         for (final DataSchemaNode childNode : module.getChildNodes()) {
202             if (childNode instanceof DataNodeContainer) {
203                 LeafSchemaNode leafrefFromRecursion = findSchemaNodeWithLeafrefType((DataNodeContainer) childNode,
204                         nodeName);
205                 if (leafrefFromRecursion != null) {
206                     return leafrefFromRecursion;
207                 }
208             } else if (childNode.getQName().getLocalName().equals(nodeName) && childNode instanceof LeafSchemaNode) {
209                 final TypeDefinition<?> leafSchemaNodeType = ((LeafSchemaNode) childNode).getType();
210                 if (leafSchemaNodeType instanceof LeafrefTypeDefinition) {
211                     return (LeafSchemaNode) childNode;
212                 }
213             }
214         }
215         return null;
216     }
217
218     private static LeafrefTypeDefinition findLeafrefType(final LeafSchemaNode schemaNode) {
219         final TypeDefinition<?> type = schemaNode.getType();
220         if (type instanceof LeafrefTypeDefinition) {
221             return (LeafrefTypeDefinition) type;
222         }
223         return null;
224     }
225 }