Move netconf-dom-api
[netconf.git] / netconf / netconf-util / src / test / java / org / opendaylight / netconf / util / test / NetconfXmlUnitRecursiveQualifier.java
1 /*
2  * Copyright (c) 2015 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.netconf.util.test;
10
11 import org.custommonkey.xmlunit.ElementNameAndTextQualifier;
12 import org.custommonkey.xmlunit.ElementQualifier;
13 import org.w3c.dom.Element;
14 import org.w3c.dom.Node;
15 import org.w3c.dom.NodeList;
16
17 /**
18  * Custom xmlunit qualifier that doesn't care about order when deeper in the recursion
19  * defaults to comparing element name and text content.
20  */
21 public class NetconfXmlUnitRecursiveQualifier implements ElementQualifier {
22
23     private final ElementQualifier qualifier;
24
25     public NetconfXmlUnitRecursiveQualifier() {
26         this.qualifier = new ElementNameAndTextQualifier();
27     }
28
29     public NetconfXmlUnitRecursiveQualifier(final ElementQualifier qualifier) {
30         this.qualifier = qualifier;
31     }
32
33     @Override
34     public boolean qualifyForComparison(Element currentControl,
35                                         Element currentTest) {
36         return compareNodes(currentControl, currentTest);
37     }
38
39     @SuppressWarnings("checkstyle:IllegalCatch")
40     private boolean compareNodes(Node currentControl, Node currentTest) {
41         try {
42
43             if (!qualifier.qualifyForComparison((Element) currentControl,
44                     (Element) currentTest)) {
45                 return false;
46             }
47
48             NodeList controlNodes;
49             NodeList testNodes;
50
51             if (currentControl.hasChildNodes() && currentTest.hasChildNodes()) {
52                 controlNodes = currentControl.getChildNodes();
53                 testNodes = currentTest.getChildNodes();
54             } else {
55                 return !(currentControl.hasChildNodes() || currentTest.hasChildNodes());
56             }
57
58             return (countNodesWithoutConsecutiveTextNodes(controlNodes)
59                     == countNodesWithoutConsecutiveTextNodes(testNodes)) && checkChildren(controlNodes, testNodes);
60
61         } catch (Exception e) {
62             return false;
63         }
64     }
65
66     private boolean checkChildren(NodeList controlNodes, NodeList testNodes) {
67         for (int i = 0; i < controlNodes.getLength(); i++) {
68             boolean matchFound = false;
69             for (int j = 0; j < testNodes.getLength(); j++) {
70                 Node controlNode = controlNodes.item(i);
71                 Node testNode = testNodes.item(j);
72
73                 if (controlNode.getNodeType() != testNode.getNodeType()) {
74                     continue;
75                 }
76
77                 if (controlNode.getNodeType() == Node.TEXT_NODE) {
78                     if (concatenateText(controlNode).equals(concatenateText(testNode))) {
79                         matchFound = true;
80                         break;
81                     }
82
83                 } else if (compareNodes(controlNode, testNode)) {
84                     matchFound = true;
85                     break;
86                 }
87             }
88             if (!matchFound) {
89                 return false;
90             }
91         }
92
93         return true;
94     }
95
96     private static String concatenateText(Node textNode) {
97         StringBuilder builder = new StringBuilder();
98         Node next = textNode;
99
100         do {
101             if (next.getNodeValue() != null) {
102                 builder.append(next.getNodeValue().trim());
103                 next = next.getNextSibling();
104             }
105         } while (next != null && next.getNodeType() == Node.TEXT_NODE);
106
107         return builder.toString();
108     }
109
110     private static int countNodesWithoutConsecutiveTextNodes(NodeList nodeList) {
111         int count = 0;
112         boolean lastNodeWasText = false;
113         final int length = nodeList.getLength();
114         for (int i = 0; i < length; i++) {
115             Node node = nodeList.item(i);
116             if (!lastNodeWasText || node.getNodeType() != Node.TEXT_NODE) {
117                 count++;
118             }
119             lastNodeWasText = node.getNodeType() == Node.TEXT_NODE;
120         }
121         return count;
122     }
123 }