blob: 4c01164aa791121e581bbec6d848e1b96e6aff88 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/*
* $Id$
*/
package org.apache.qetest.xsl;
import java.io.PrintWriter;
import java.util.Vector;
import org.w3c.dom.Attr;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
/**
* Defines XSLTC's XML/HTML/Text diff comparator to check or diff two files.
* This comparator uses the expanded name instead of the qname to compare
* element names. Also, for simplicity, it ignores NS declaration attributes.
*
* //@todo Use expanded name for attributes as well
*
* @author Scott_Boag@lotus.com
* @author Shane_Curcuru@lotus.com
* @author Santiago.PericasGeertsen@sun.com
* @version $Id$
*/
public class XHTComparatorXSLTC extends XHTComparator
{
/**
* The contract is: when you enter here the gold and test nodes are the same type,
* both non-null, and both in the same basic position in the tree.
* //@todo verify caller really performs for the contract -sc
*
* This overridden method does additional checking of namespaces
* and local names, instead of just getNodeName().
*
* @param gold gold or expected node
* @param test actual node
* @param reporter PrintWriter to dump status info to
* @param warning[] if any whitespace diffs found
*
* @return true if pass, false if any problems encountered
*/
boolean diff(Node gold, Node test, PrintWriter reporter,
boolean[] warning)
{
String name1 = gold.getLocalName();
String name2 = test.getLocalName();
// If both there but not equal, fail
if ((null != name1) && (null != name2) &&!name1.equals(name2))
{
reporter.println(MISMATCH_NODE + nodeTypeString(gold) + SEPARATOR
+ nodeTypeString(test) + SEPARATOR
+ "name does not equal test node");
return false;
}
else if ((null != name1) && (null == name2))
{
reporter.println(MISSING_TEST_NODE + nodeTypeString(gold)
+ SEPARATOR + nodeTypeString(test) + SEPARATOR
+ "name missing on test");
return false;
}
else if ((null == name1) && (null != name2))
{
reporter.println(MISSING_GOLD_NODE + nodeTypeString(gold)
+ SEPARATOR + nodeTypeString(test) + SEPARATOR
+ "name missing on gold");
return false;
}
String uri1 = gold.getNamespaceURI();
String uri2 = test.getNamespaceURI();
// If both there but not equal, fail
if ((null != uri1) && (null != uri2) && !uri1.equals(uri2))
{
reporter.println(MISMATCH_NODE + nodeTypeString(gold) + SEPARATOR
+ nodeTypeString(test) + SEPARATOR
+ "namespace URI does not equal test node");
return false;
}
else if ((null != uri1) && (null == uri2))
{
reporter.println(MISSING_TEST_NODE + nodeTypeString(gold)
+ SEPARATOR + nodeTypeString(test) + SEPARATOR
+ "namespace URI missing on test");
return false;
}
else if ((null == uri1) && (null != uri2))
{
reporter.println(MISSING_GOLD_NODE + nodeTypeString(gold)
+ SEPARATOR + nodeTypeString(test) + SEPARATOR
+ "namespace URI missing on gold");
return false;
}
String value1 = gold.getNodeValue();
String value2 = test.getNodeValue();
if ((null != value1) && (null != value2) &&!value1.equals(value2))
{
reporter.println(MISMATCH_VALUE + nodeTypeString(gold) + "len="
+ value1.length() + SEPARATOR
+ nodeTypeString(test) + "len=" + value2.length()
+ SEPARATOR + "lengths do not match");
// Limit length we output to logs; extremely long values
// are more hassle than they're worth (at that point,
// it's either obvious what the problem is, or it's
// such a small problem that you'll need to manually
// compare the files separately
if (value1.length() > maxDisplayLen)
value1 = value1.substring(0, maxDisplayLen);
if (value2.length() > maxDisplayLen)
value2 = value2.substring(0, maxDisplayLen);
reporter.println(MISMATCH_VALUE_GOLD + nodeTypeString(gold) + SEPARATOR + "\n" + value1);
reporter.println(MISMATCH_VALUE_TEXT + nodeTypeString(test) + SEPARATOR + "\n" + value2);
return false;
}
else if ((null != value1) && (null == value2))
{
reporter.println(MISSING_TEST_VALUE + nodeTypeString(gold) + "-"
+ value1 + SEPARATOR + nodeTypeString(test)
+ SEPARATOR + "test no value");
return false;
}
else if ((null == value1) && (null != value2))
{
reporter.println(MISSING_GOLD_VALUE + nodeTypeString(gold)
+ SEPARATOR + nodeTypeString(test) + "-" + value2
+ SEPARATOR + "gold no value");
return false;
}
switch (gold.getNodeType())
{
case Node.DOCUMENT_NODE :
{
// Why don't we do anything here? -sc
}
break;
case Node.ELEMENT_NODE :
{
// Explicitly ignore attribute ordering
// TODO do we need to make this settable for testing purposes? -sc
NamedNodeMap goldAttrs = gold.getAttributes();
NamedNodeMap testAttrs = test.getAttributes();
if ((null != goldAttrs) && (null == testAttrs))
{
reporter.println(MISMATCH_ATTRIBUTE + nodeTypeString(gold)
+ SEPARATOR + nodeTypeString(test) + SEPARATOR
+ "test no attrs");
return false;
}
else if ((null == goldAttrs) && (null != testAttrs))
{
reporter.println(MISMATCH_ATTRIBUTE + nodeTypeString(gold)
+ SEPARATOR + nodeTypeString(test) + SEPARATOR
+ "gold no attrs");
return false;
}
// Remove NS declarations from gold attribute list
Vector nsDeclarations = new Vector();
int length = goldAttrs.getLength();
for (int i = 0; i < length; i++) {
final String name = goldAttrs.item(i).getNodeName();
if (name.startsWith("xmlns")) {
nsDeclarations.addElement(name);
}
}
length = nsDeclarations.size();
for (int i = 0; i < length; i++) {
goldAttrs.removeNamedItem((String) nsDeclarations.elementAt(i));
}
// Remove NS declarations from test attribute list
nsDeclarations.removeAllElements(); // Use JDK 1.1.x methods
length = testAttrs.getLength();
for (int i = 0; i < length; i++) {
final String name = testAttrs.item(i).getNodeName();
if (name.startsWith("xmlns")) {
nsDeclarations.addElement(name);
}
}
length = nsDeclarations.size();
for (int i = 0; i < length; i++) {
testAttrs.removeNamedItem((String) nsDeclarations.elementAt(i));
}
int gn = goldAttrs.getLength();
int tn = testAttrs.getLength();
if (gn != tn)
{
reporter.println(MISMATCH_ATTRIBUTE + nodeTypeString(gold)
+ "-" + gn + SEPARATOR + nodeTypeString(test)
+ "-" + tn + SEPARATOR
+ "attribte count mismatch");
// TODO: add output of each set of attrs for comparisons
return false;
}
// TODO verify this checks the full list of attributes both ways,
// from gold->test and from test->gold -sc
for (int i = 0; i < gn; i++)
{
Attr goldAttr = (Attr) goldAttrs.item(i);
String goldAttrLocalName = goldAttr.getLocalName();
String goldAttrNamespaceURI = goldAttr.getNamespaceURI();
String goldAttrName = goldAttr.getName();
Node testAttr;
if (goldAttrNamespaceURI != null && goldAttrLocalName != null) {
testAttr = testAttrs.getNamedItemNS(goldAttrNamespaceURI,goldAttrLocalName);
} else {
testAttr = testAttrs.getNamedItem(goldAttrName);
}
if (null == testAttr)
{
reporter.println(MISMATCH_ATTRIBUTE + nodeTypeString(gold)
+ "-" + goldAttrName + SEPARATOR
+ nodeTypeString(test) + SEPARATOR
+ "missing attribute on test");
return false;
}
if (!diff(goldAttr, testAttr, reporter, warning))
{
return false;
}
}
}
break;
case Node.CDATA_SECTION_NODE :{}
break;
case Node.ENTITY_REFERENCE_NODE :{}
break;
case Node.ATTRIBUTE_NODE :{}
break;
case Node.COMMENT_NODE :{}
break;
case Node.ENTITY_NODE :{}
break;
case Node.NOTATION_NODE :{}
break;
case Node.PROCESSING_INSTRUCTION_NODE :{}
break;
case Node.TEXT_NODE :{}
break;
default :{}
}
Node try2[] = new Node[2];
Node goldChild = gold.getFirstChild();
Node testChild = test.getFirstChild();
if (!basicChildCompare(goldChild, testChild, reporter, warning, try2))
return false;
goldChild = try2[0];
testChild = try2[1];
while (null != goldChild)
{
if (!diff(goldChild, testChild, reporter, warning))
return false;
goldChild = goldChild.getNextSibling();
testChild = testChild.getNextSibling();
if (!basicChildCompare(goldChild, testChild, reporter, warning,
try2))
return false;
goldChild = try2[0];
testChild = try2[1];
}
return true;
} // end of diff()
}