/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.netconf.util.test; import org.custommonkey.xmlunit.ElementNameAndTextQualifier; import org.custommonkey.xmlunit.ElementQualifier; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Custom xmlunit qualifier that doesn't care about order when deeper in the recursion * defaults to comparing element name and text content */ public class NetconfXmlUnitRecursiveQualifier implements ElementQualifier { private final ElementQualifier qualifier; public NetconfXmlUnitRecursiveQualifier() { this.qualifier = new ElementNameAndTextQualifier(); } public NetconfXmlUnitRecursiveQualifier(final ElementQualifier qualifier) { this.qualifier = qualifier; } @Override public boolean qualifyForComparison(Element currentControl, Element currentTest) { return compareNodes(currentControl, currentTest); } private boolean compareNodes(Node currentControl, Node currentTest) { try { if (!qualifier.qualifyForComparison((Element) currentControl, (Element) currentTest)) { return false; } NodeList controlNodes; NodeList testNodes; if (currentControl.hasChildNodes() && currentTest.hasChildNodes()) { controlNodes = currentControl.getChildNodes(); testNodes = currentTest.getChildNodes(); } else { return !(currentControl.hasChildNodes() || currentTest.hasChildNodes()); } return (countNodesWithoutConsecutiveTextNodes(controlNodes) == countNodesWithoutConsecutiveTextNodes(testNodes)) && checkChildren(controlNodes, testNodes); } catch (Exception e) { return false; } } private boolean checkChildren(NodeList controlNodes, NodeList testNodes) { for (int i = 0; i < controlNodes.getLength(); i++) { boolean matchFound = false; for (int j = 0; j < testNodes.getLength(); j++) { Node controlNode = controlNodes.item(i); Node testNode = testNodes.item(j); if (controlNode.getNodeType() != testNode.getNodeType()) { continue; } if (controlNode.getNodeType() == Node.TEXT_NODE) { if (concatenateText(controlNode).equals(concatenateText(testNode))) { matchFound = true; break; } } else if (compareNodes(controlNode, testNode)) { matchFound = true; break; } } if (!matchFound) { return false; } } return true; } private static String concatenateText(Node textNode) { StringBuilder builder = new StringBuilder(); Node next = textNode; do { if (next.getNodeValue() != null) { builder.append(next.getNodeValue().trim()); next = next.getNextSibling(); } } while (next != null && next.getNodeType() == Node.TEXT_NODE); return builder.toString(); } private static int countNodesWithoutConsecutiveTextNodes(NodeList l) { int count = 0; boolean lastNodeWasText = false; final int length = l.getLength(); for (int i = 0; i < length; i++) { Node n = l.item(i); if (!lastNodeWasText || n.getNodeType() != Node.TEXT_NODE) { count++; } lastNodeWasText = n.getNodeType() == Node.TEXT_NODE; } return count; } }