2 * Copyright (c) 2013 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
8 package org.opendaylight.yangtools.yang.data.impl;
10 import groovy.lang.Binding;
11 import groovy.lang.GroovyShell;
12 import groovy.lang.Script;
14 import java.io.ByteArrayInputStream;
15 import java.io.ByteArrayOutputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.InputStreamReader;
19 import java.io.PrintStream;
20 import java.io.Reader;
21 import java.io.StringWriter;
22 import java.lang.reflect.Method;
23 import java.text.MessageFormat;
24 import java.util.ArrayList;
25 import java.util.List;
28 import javax.xml.transform.OutputKeys;
29 import javax.xml.transform.Transformer;
30 import javax.xml.transform.TransformerException;
31 import javax.xml.transform.TransformerFactory;
32 import javax.xml.transform.dom.DOMSource;
33 import javax.xml.transform.stream.StreamResult;
35 import org.custommonkey.xmlunit.Diff;
36 import org.junit.Assert;
37 import org.opendaylight.yangtools.yang.common.QName;
38 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
39 import org.opendaylight.yangtools.yang.data.api.Node;
40 import org.opendaylight.yangtools.yang.model.api.Module;
41 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
42 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
43 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46 import org.w3c.dom.Document;
47 import org.xml.sax.SAXException;
50 * @author michal.rehak
53 public abstract class NodeHelper {
55 private static final Logger LOG = LoggerFactory.getLogger(NodeHelper.class);
57 /** xml source of example network configuration */
58 public static final String NETWORK_XML =
59 "<network xmlns=\"urn:opendaylight:controller:network\">\n" +
63 " <topology-id>topId_01</topology-id>\n" +
66 " <node-id>nodeId_02</node-id>\n" +
67 " <supporting-ne>networkId_02</supporting-ne>\n" +
68 " <termination-points>\n" +
69 " <termination-point>\n" +
70 " <tp-id>tpId_03</tp-id>\n" +
71 " </termination-point>\n" +
72 " </termination-points>\n" +
75 " <node-id>nodeId_16</node-id>\n" +
76 " <supporting-ne>networkId_17</supporting-ne>\n" +
77 " <termination-points>\n" +
78 " <termination-point>\n" +
79 " <tp-id>tpId_18</tp-id>\n" +
80 " </termination-point>\n" +
81 " </termination-points>\n" +
84 " <node-id>nodeId_19</node-id>\n" +
85 " <supporting-ne>networkId_20</supporting-ne>\n" +
86 " <termination-points>\n" +
87 " <termination-point>\n" +
88 " <tp-id>tpId_18</tp-id>\n" +
89 " </termination-point>\n" +
90 " <termination-point>\n" +
91 " <tp-id>tpId_19</tp-id>\n" +
92 " </termination-point>\n" +
93 " </termination-points>\n" +
98 " <link-id>linkId_04</link-id>\n" +
100 " <source-node>nodeId_05</source-node>\n" +
101 " <source-tp>tpId_06</source-tp>\n" +
104 " <dest-node>nodeId_07</dest-node>\n" +
105 " <dest-tp>tpId_08</dest-tp>\n" +
106 " </destination>\n" +
109 " <link-id>linkId_11</link-id>\n" +
111 " <source-node>nodeId_12</source-node>\n" +
112 " <source-tp>tpId_13</source-tp>\n" +
115 " <dest-node>nodeId_14</dest-node>\n" +
116 " <dest-tp>tpId_15</dest-tp>\n" +
117 " </destination>\n" +
122 " <network-elements>\n" +
123 " <network-element>\n" +
124 " <element-id>ntElementId_09</element-id>\n" +
125 " </network-element>\n" +
126 " <network-element>\n" +
127 " <element-id>ntElementId_10</element-id>\n" +
128 " </network-element>\n" +
129 " </network-elements>\n" +
132 private static String domTreeString(final Document domTree) throws TransformerException {
133 TransformerFactory transformerFact = TransformerFactory.newInstance();
134 transformerFact.setAttribute("indent-number", 4);
135 Transformer transformer = transformerFact.newTransformer();
136 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
137 //initialize StreamResult with File object to save to file
138 StreamResult result = new StreamResult(new StringWriter());
139 DOMSource source = new DOMSource(domTree);
140 transformer.transform(source, result);
141 return result.getWriter().toString();
149 private static void dumpDoc(final Document domTree, final PrintStream out) throws Exception {
150 out.println(domTreeString(domTree));
153 public static void dumpDoc(final Document domTree, final Logger logger) throws TransformerException {
154 logger.info("{}", domTreeString(domTree));
159 * @return example tree, see {@link #NETWORK_XML}
161 public static CompositeNode buildTestConfigTree(final QName qName) {
162 List<Node<?>> value = new ArrayList<Node<?>>();
163 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "element-id"), null, "ntElementId_09"));
164 CompositeNode ntElementNode1 = NodeFactory.createImmutableCompositeNode(QName.create(qName, "network-element"),
166 assignParentToChildren(ntElementNode1);
168 value = new ArrayList<Node<?>>();
169 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "element-id"), null, "ntElementId_10"));
170 CompositeNode ntElementNode2 = NodeFactory.createImmutableCompositeNode(QName.create(qName, "network-element"),
172 assignParentToChildren(ntElementNode2);
174 value = new ArrayList<Node<?>>();
175 value.add(ntElementNode1);
176 value.add(ntElementNode2);
177 CompositeNode ntElementsNode = NodeFactory.createImmutableCompositeNode(
178 QName.create(qName, "network-elements"), null, value);
179 assignParentToChildren(ntElementsNode);
181 value = new ArrayList<Node<?>>();
182 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "dest-node"), null, "nodeId_07"));
183 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "dest-tp"), null, "tpId_08"));
184 CompositeNode destination = NodeFactory.createImmutableCompositeNode(
185 QName.create(qName, "destination"), null,
187 assignParentToChildren(destination);
189 value = new ArrayList<Node<?>>();
190 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "source-node"), null, "nodeId_05"));
191 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "source-tp"), null, "tpId_06"));
192 CompositeNode source = NodeFactory.createImmutableCompositeNode(
193 QName.create(qName, "source"), null, value);
194 assignParentToChildren(source);
196 value = new ArrayList<Node<?>>();
197 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "link-id"), null, "linkId_04"));
199 value.add(destination);
200 CompositeNode link1 = NodeFactory.createImmutableCompositeNode(
201 QName.create(qName, "link"), null, value);
202 assignParentToChildren(link1);
204 value = new ArrayList<Node<?>>();
205 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "dest-node"), null, "nodeId_14"));
206 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "dest-tp"), null, "tpId_15"));
207 destination = NodeFactory.createImmutableCompositeNode(
208 QName.create(qName, "destination"), null, value);
209 assignParentToChildren(destination);
211 value = new ArrayList<Node<?>>();
212 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "source-node"), null, "nodeId_12"));
213 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "source-tp"), null, "tpId_13"));
214 source = NodeFactory.createImmutableCompositeNode(
215 QName.create(qName, "source"), null, value);
216 assignParentToChildren(source);
218 value = new ArrayList<Node<?>>();
219 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "link-id"), null, "linkId_11"));
221 value.add(destination);
222 CompositeNode link2 = NodeFactory.createImmutableCompositeNode(
223 QName.create(qName, "link"), null, value);
224 assignParentToChildren(link2);
226 value = new ArrayList<Node<?>>();
229 CompositeNode links = NodeFactory.createImmutableCompositeNode(
230 QName.create(qName, "links"), null, value);
231 assignParentToChildren(links);
234 value = new ArrayList<Node<?>>();
235 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "tp-id"), null, "tpId_03"));
236 CompositeNode terminationPointNode1 = NodeFactory.createImmutableCompositeNode(
237 QName.create(qName, "termination-point"), null, value);
238 assignParentToChildren(terminationPointNode1);
240 value = new ArrayList<Node<?>>();
241 value.add(terminationPointNode1);
242 CompositeNode terminationPointsNode = NodeFactory.createImmutableCompositeNode(
243 QName.create(qName, "termination-points"), null, value);
244 assignParentToChildren(terminationPointsNode);
246 value = new ArrayList<Node<?>>();
247 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "node-id"), null, "nodeId_02"));
248 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "supporting-ne"), null, "networkId_02"));
249 value.add(terminationPointsNode);
250 CompositeNode node1Node = NodeFactory.createImmutableCompositeNode(
251 QName.create(qName, "node"), null, value);
252 assignParentToChildren(node1Node);
254 value = new ArrayList<Node<?>>();
255 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "tp-id"), null, "tpId_18"));
256 terminationPointNode1 = NodeFactory.createImmutableCompositeNode(
257 QName.create(qName, "termination-point"),
259 assignParentToChildren(terminationPointNode1);
261 value = new ArrayList<Node<?>>();
262 value.add(terminationPointNode1);
263 terminationPointsNode = NodeFactory.createImmutableCompositeNode(
264 QName.create(qName, "termination-points"),
266 assignParentToChildren(terminationPointsNode);
268 value = new ArrayList<Node<?>>();
269 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "node-id"), null, "nodeId_16"));
270 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "supporting-ne"), null, "networkId_17"));
271 value.add(terminationPointsNode);
272 CompositeNode node2Node = NodeFactory.createImmutableCompositeNode(
273 QName.create(qName, "node"), null, value);
274 assignParentToChildren(node2Node);
276 value = new ArrayList<Node<?>>();
277 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "tp-id"), null, "tpId_18"));
278 terminationPointNode1 = NodeFactory.createImmutableCompositeNode(
279 QName.create(qName, "termination-point"),
281 assignParentToChildren(terminationPointNode1);
283 value = new ArrayList<Node<?>>();
284 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "tp-id"), null, "tpId_19"));
285 CompositeNode terminationPointNode2 = NodeFactory.createImmutableCompositeNode(
286 QName.create(qName, "termination-point"), null, value);
287 assignParentToChildren(terminationPointNode2);
289 value = new ArrayList<Node<?>>();
290 value.add(terminationPointNode1);
291 value.add(terminationPointNode2);
292 terminationPointsNode = NodeFactory.createImmutableCompositeNode(
293 QName.create(qName, "termination-points"),
295 assignParentToChildren(terminationPointsNode);
297 value = new ArrayList<Node<?>>();
298 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "node-id"), null, "nodeId_19"));
299 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "supporting-ne"), null, "networkId_20"));
300 value.add(terminationPointsNode);
301 CompositeNode node3Node = NodeFactory.createImmutableCompositeNode(
302 QName.create(qName, "node"), null, value);
303 assignParentToChildren(node3Node);
305 value = new ArrayList<Node<?>>();
306 value.add(node1Node);
307 value.add(node2Node);
308 value.add(node3Node);
309 CompositeNode nodesNode = NodeFactory.createImmutableCompositeNode(
310 QName.create(qName, "nodes"), null, value);
311 assignParentToChildren(nodesNode);
313 value = new ArrayList<Node<?>>();
315 value.add(nodesNode);
316 value.add(NodeFactory.createImmutableSimpleNode(QName.create(qName, "topology-id"), null, "topId_01"));
317 CompositeNode topology = NodeFactory.createImmutableCompositeNode(
318 QName.create(qName, "topology"), null, value);
319 assignParentToChildren(topology);
321 value = new ArrayList<Node<?>>();
323 CompositeNode topologies = NodeFactory.createImmutableCompositeNode(
324 QName.create(qName, "topologies"), null,
326 assignParentToChildren(topologies);
328 value = new ArrayList<Node<?>>();
329 value.add(topologies);
330 value.add(ntElementsNode);
331 CompositeNode network = NodeFactory.createImmutableCompositeNode(
332 QName.create(qName, "network"), null, value);
333 assignParentToChildren(network);
341 public static void assignParentToChildren(final CompositeNode parentNode) {
342 for (Node<?> child : parentNode.getValue()) {
343 ((AbstractNodeTO<?>) child).setParent(parentNode);
348 * @return schema context of controller-network.yang
350 public static SchemaContext loadSchemaContext() {
351 YangModelParser yParser = new YangParserImpl();
352 List<InputStream> yangInputStreams = new ArrayList<>();
353 yangInputStreams.add(NodeHelper.class.getResourceAsStream(
354 "/controller-network.yang"));
355 yangInputStreams.add(NodeHelper.class.getResourceAsStream(
356 "/ietf-inet-types@2010-09-24.yang"));
357 Set<Module> modules = yParser
358 .parseYangModelsFromStreams(yangInputStreams);
359 return yParser.resolveSchemaContext(modules);
367 public static CompositeNode loadConfigByGroovy(final String scriptName) throws Exception {
368 InputStream configStream = NodeHelper.class.getResourceAsStream(scriptName);
369 Binding binding = new Binding();
370 GroovyShell gShell = new GroovyShell(binding);
371 LOG.debug("groovy: starting script parse.. {}", scriptName);
372 Script configScript = gShell.parse(new InputStreamReader(configStream));
373 LOG.debug("groovy: starting script.. {}", scriptName);
375 LOG.debug("groovy: digging result");
376 Object xmlGen = binding.getVariable("xmlGen");
377 LOG.debug("xmlGen = {}", xmlGen);
378 Method getter = xmlGen.getClass().getDeclaredMethod("getBuilder", new Class[0]);
379 MyNodeBuilder builder = (MyNodeBuilder) getter.invoke(xmlGen, new Object[0]);
381 return builder.getRootNode();
385 * @param pattern , e.g.: <pre>"//{0}:network/{1}:xx[text() = 'sss']"</pre>
386 * @param nsArg , e.g.: <pre>{"uri:ns1", "uri:ns2"}</pre>
387 * @return pattern with namespaces: <pre>//uri:ns1:network/uri:ns2:xx[text() = ''sss'']"</pre>
389 public static String AddNamespaceToPattern(final String pattern, final Object... nsArg) {
391 String patternNs = pattern.replaceAll("'", "''");
393 ns = new Object[]{""};
395 // add ':' into pattern after placeholders
396 patternNs = patternNs.replaceAll("(\\{[0-9]+\\})", "$1:");
399 return MessageFormat.format(patternNs, ns);
407 * @throws SAXException
408 * @throws IOException
410 public static void compareXmlTree(final Document tree, final String xmlFile, final Class<?> clazz) throws Exception,
411 SAXException, IOException {
412 ByteArrayOutputStream actualRaw = new ByteArrayOutputStream();
413 dumpDoc(tree, new PrintStream(actualRaw));
414 Reader actualReader = new InputStreamReader(new ByteArrayInputStream(actualRaw.toByteArray()));
416 Reader expectedReader = new InputStreamReader(clazz.getResourceAsStream(xmlFile));
417 Diff myDiff = new Diff(expectedReader, actualReader);
418 myDiff.overrideDifferenceListener(new IgnoreWhiteCharsDiffListener());
420 boolean similar = myDiff.similar();
422 LOG.info("{}", new String(actualRaw.toByteArray()));
424 Assert.assertEquals(myDiff.toString(), true, similar);