net.javacrumbs.smock.common.EnhancedDiff Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2009-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.javacrumbs.smock.common;
import java.io.IOException;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
* Diff that ignores "${IGNORE}" placeholder and is able to correctly compare namespace prefixes in the attribute values.
* @author Lukas Krecan
*
*/
public final class EnhancedDiff extends Diff {
public EnhancedDiff(Document controlDoc, Document testDoc) {
super(controlDoc, testDoc);
}
EnhancedDiff(String control, String test) throws SAXException, IOException {
super(control, test);
}
public int differenceFound(Difference difference) {
//ignore dissimilarities
if (difference.isRecoverable())
{
return RETURN_ACCEPT_DIFFERENCE;
}
if ("${IGNORE}".equals(difference.getControlNodeDetail().getValue())) {
return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
}
else if (isDifferenceOnlyInAttributeValuePrefix(difference))
{
return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
}
else
{
return super.differenceFound(difference);
}
}
/**
* Returns true iff difference is only in attribute value namespace prefix but the corresponding namespace is same.
* @param difference
* @return
*/
protected final boolean isDifferenceOnlyInAttributeValuePrefix(Difference difference) {
Node testNode = difference.getTestNodeDetail().getNode();
if (testNode==null)
{
return false;
}
String testNodeValue = testNode.getNodeValue();
Node controlNode = difference.getControlNodeDetail().getNode();
String controlNodeValue = controlNode.getNodeValue();
if (isAttr(testNode) && isAttr(controlNode) && (hasNsPrefix(testNodeValue) || hasNsPrefix(controlNodeValue)))
{
String testValueNsResolved = resolveNamespaces(testNode, testNodeValue);
String controlValueNsResolved = resolveNamespaces(controlNode, controlNodeValue);
return testValueNsResolved.equals(controlValueNsResolved);
}
return false;
}
/**
* Replaces namespace prefixes with their URLs.
* @param node
* @param value
* @return
*/
private String resolveNamespaces(Node node, String value) {
int prefixLength = value.indexOf(':');
if (prefixLength>=0)
{
String prefix = value.substring(0, prefixLength);
String nsUri = node.lookupNamespaceURI(prefix);
if (nsUri==null)//prefix not resolved, let's use prefix instead
{
nsUri = prefix;
}
return nsUri+value.substring(prefixLength);
}
else
{
String nsUri = node.lookupNamespaceURI(null);
return nsUri+":"+value;
}
}
private boolean hasNsPrefix(String testNodeValue) {
return testNodeValue.contains(":");
}
private boolean isAttr(Node testNode) {
return testNode instanceof Attr;
}
}