Mark methods as static
[yangtools.git] / yang / yang-data-impl / src / test / java / org / opendaylight / yangtools / yang / data / impl / codec / xml / XmlStreamUtilsTest.java
1 /*
2  * Copyright (c) 2014 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.impl.codec.xml;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14 import com.google.common.base.Optional;
15 import com.google.common.collect.Maps;
16 import java.io.ByteArrayOutputStream;
17 import java.io.File;
18 import java.net.URI;
19 import java.net.URISyntaxException;
20 import java.util.AbstractMap;
21 import java.util.Arrays;
22 import java.util.Map;
23 import javax.xml.stream.XMLOutputFactory;
24 import javax.xml.stream.XMLStreamWriter;
25 import org.custommonkey.xmlunit.Diff;
26 import org.custommonkey.xmlunit.XMLUnit;
27 import org.junit.BeforeClass;
28 import org.junit.Ignore;
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.model.api.DataNodeContainer;
33 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.Module;
36 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
37 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
38 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
39 import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
40 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
41 import org.opendaylight.yangtools.yang.model.util.StringType;
42 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
43 import org.w3c.dom.Document;
44
45 public class XmlStreamUtilsTest {
46
47     public static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newFactory();
48
49     private static SchemaContext schemaContext;
50     private static Module leafRefModule;
51
52     @BeforeClass
53     public static void initialize() throws URISyntaxException {
54         final YangParserImpl yangParser = new YangParserImpl();
55         final File file = new File(XmlStreamUtils.class.getResource("/leafref-test.yang").toURI());
56         schemaContext = yangParser.parseFiles(Arrays.asList(file));
57         assertNotNull(schemaContext);
58         assertEquals(1,schemaContext.getModules().size());
59         leafRefModule = schemaContext.getModules().iterator().next();
60         assertNotNull(leafRefModule);
61     }
62
63
64     @Test
65     public void testWriteAttribute() throws Exception {
66         final ByteArrayOutputStream out = new ByteArrayOutputStream();
67         final XMLStreamWriter writer =  XML_OUTPUT_FACTORY.createXMLStreamWriter(out);
68         writer.writeStartElement("element");
69
70         QName name = getAttrQName("namespace", "2012-12-12", "attr", Optional.of("prefix"));
71         final Map.Entry<QName, String> attributeEntry = new AbstractMap.SimpleEntry<>(name, "value");
72
73         name = getAttrQName("namespace2", "2012-12-12", "attr", Optional.<String>absent());
74         final Map.Entry<QName, String> attributeEntryNoPrefix = new AbstractMap.SimpleEntry<>(name, "value");
75
76         final RandomPrefix randomPrefix = new RandomPrefix();
77         XmlStreamUtils.writeAttribute(writer, attributeEntry, randomPrefix);
78         XmlStreamUtils.writeAttribute(writer, attributeEntryNoPrefix, randomPrefix);
79
80         writer.writeEndElement();
81         writer.close();
82         out.close();
83
84         final String xmlAsString = new String(out.toByteArray());
85
86         final Map<String, String> mappedPrefixes = mapPrefixed(randomPrefix.getPrefixes());
87         assertEquals(2, mappedPrefixes.size());
88         final String randomPrefixValue = mappedPrefixes.get("namespace2");
89
90         final String expectedXmlAsString = "<element xmlns:a=\"namespace\" a:attr=\"value\" xmlns:" + randomPrefixValue + "=\"namespace2\" " + randomPrefixValue + ":attr=\"value\"></element>";
91
92         XMLUnit.setIgnoreAttributeOrder(true);
93         final Document control = XMLUnit.buildControlDocument(expectedXmlAsString);
94         final Document test = XMLUnit.buildTestDocument(xmlAsString);
95         final Diff diff = XMLUnit.compareXML(control, test);
96
97         final boolean identical = diff.identical();
98         assertTrue("Xml differs: " + diff.toString(), identical);
99     }
100
101     /**
102      * One leafref reference to other leafref via relative references
103      */
104     @Test
105     public void testLeafRefRelativeChaining() {
106         getTargetNodeForLeafRef("leafname3",StringType.class);
107     }
108
109     @Test
110     public void testLeafRefRelative() {
111         getTargetNodeForLeafRef("pointToStringLeaf",StringType.class);
112     }
113
114     @Test
115     public void testLeafRefAbsoluteWithSameTarget() {
116         getTargetNodeForLeafRef("absname",InstanceIdentifierType.class);
117     }
118
119     /**
120      * Tests relative path with double point inside path (e. g. "../../lf:interface/../lf:cont2/lf:stringleaf")
121      */
122     @Ignore //ignored because this isn't implemented
123     @Test
124     public void testLeafRefWithDoublePointInPath() {
125         getTargetNodeForLeafRef("lf-with-double-point-inside",StringType.class);
126     }
127
128     @Test
129     public void testLeafRefRelativeAndAbsoluteWithSameTarget() {
130         final TypeDefinition<?> targetNodeForAbsname = getTargetNodeForLeafRef("absname",InstanceIdentifierType.class);
131         final TypeDefinition<?> targetNodeForRelname = getTargetNodeForLeafRef("relname",InstanceIdentifierType.class);
132         assertEquals(targetNodeForAbsname, targetNodeForRelname);
133     }
134
135     private TypeDefinition<?> getTargetNodeForLeafRef(final String nodeName, final Class<?> clas) {
136         final LeafSchemaNode schemaNode = findSchemaNodeWithLeafrefType(leafRefModule, nodeName);
137         assertNotNull(schemaNode);
138         final LeafrefTypeDefinition leafrefTypedef = findLeafrefType(schemaNode);
139         assertNotNull(leafrefTypedef);
140         final TypeDefinition<?> targetBaseType = SchemaContextUtil.getBaseTypeForLeafRef(leafrefTypedef, schemaContext, schemaNode);
141         assertEquals("Wrong class found.", clas, targetBaseType.getClass());
142         return targetBaseType;
143     }
144
145     private static Map<String, String> mapPrefixed(final Iterable<Map.Entry<URI, String>> prefixes) {
146         final Map<String, String> mappedPrefixes = Maps.newHashMap();
147         for (final Map.Entry<URI, String> prefix : prefixes) {
148             mappedPrefixes.put(prefix.getKey().toString(), prefix.getValue());
149         }
150         return mappedPrefixes;
151     }
152
153     private static QName getAttrQName(final String namespace, final String revision, final String localName, final Optional<String> prefix) {
154         if (prefix.isPresent()) {
155             final QName moduleQName = QName.create(namespace, revision, "module");
156             final QNameModule module = QNameModule.create(moduleQName.getNamespace(), moduleQName.getRevision());
157             return QName.create(module, localName);
158         } else {
159             return QName.create(namespace, revision, localName);
160         }
161     }
162
163     private LeafSchemaNode findSchemaNodeWithLeafrefType(final DataNodeContainer module, final String nodeName) {
164         for (final DataSchemaNode childNode : module.getChildNodes()) {
165             if (childNode instanceof DataNodeContainer) {
166                 LeafSchemaNode leafrefFromRecursion = findSchemaNodeWithLeafrefType((DataNodeContainer)childNode, nodeName);
167                 if (leafrefFromRecursion != null) {
168                     return leafrefFromRecursion;
169                 }
170             } else if (childNode.getQName().getLocalName().equals(nodeName) && childNode instanceof LeafSchemaNode) {
171                 final TypeDefinition<?> leafSchemaNodeType = ((LeafSchemaNode)childNode).getType();
172                 if (leafSchemaNodeType instanceof LeafrefTypeDefinition) {
173                     return (LeafSchemaNode)childNode;
174                 }
175             }
176         }
177         return null;
178     }
179
180     private static LeafrefTypeDefinition findLeafrefType(final LeafSchemaNode schemaNode) {
181         final TypeDefinition<?> type = schemaNode.getType();
182         if (type instanceof LeafrefTypeDefinition) {
183             return (LeafrefTypeDefinition)type;
184         }
185         return null;
186     }
187 }