From: <bo...@us...> - 2010-08-13 13:10:22
|
Revision: 425 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=425&view=rev Author: bodewig Date: 2010-08-13 13:10:16 +0000 (Fri, 13 Aug 2010) Log Message: ----------- start recursion support Modified Paths: -------------- trunk/xmlunit/src/buildtools/codegen.xslt trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java.xml trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/IterableNodeList.java trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.xml trunk/xmlunit/src/main/net-core/util/Convert.cs trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs Modified: trunk/xmlunit/src/buildtools/codegen.xslt =================================================================== --- trunk/xmlunit/src/buildtools/codegen.xslt 2010-08-13 11:54:14 UTC (rev 424) +++ trunk/xmlunit/src/buildtools/codegen.xslt 2010-08-13 13:10:16 UTC (rev 425) @@ -122,6 +122,10 @@ <xsl:call-template name="if-return-boilerplate"/> </xsl:template> + <xsl:template match="if-return-boilerplate"> + <xsl:call-template name="if-return-boilerplate"/> + </xsl:template> + <xsl:template name="if-return-boilerplate"> if (lastResult == ComparisonResult.CRITICAL) { return lastResult; Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java.xml =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java.xml 2010-08-13 11:54:14 UTC (rev 424) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java.xml 2010-08-13 13:10:16 UTC (rev 425) @@ -17,8 +17,10 @@ summary="Difference engine based on DOM." extends="AbstractDifferenceEngine"> + <import reference="java.util.List"/> <import reference="javax.xml.transform.Source"/> <import reference="net.sf.xmlunit.util.Convert"/> + <import reference="net.sf.xmlunit.util.IterableNodeList"/> <import reference="org.w3c.dom.Attr"/> <import reference="org.w3c.dom.CharacterData"/> <import reference="org.w3c.dom.Document"/> @@ -237,7 +239,36 @@ } private ComparisonResult compareNodeLists(NodeList control, NodeList test) { - return ComparisonResult.EQUAL; + List<Node> controlList = IterableNodeList.asList(control); + List<Node> testList = IterableNodeList.asList(test); + Match lastMatch = new Match(null, -1); +]]></literal> + <lastResultDef/> + // if there are no children on either Node, the result is equal + lastResult = ComparisonResult.EQUAL; + <literal><![CDATA[ + for (int i = 0; i < controlList.size(); i++) { + Match testMatch = findMatchingNode(controlList.get(i), testList, + lastMatch.index); + if (testMatch != null) { +]]></literal> + <compareMethodExpr method="compareNodes" + controlExpr="controlList.get(i)" + testExpr="testMatch.node"/> + <literal><![CDATA[ + lastMatch = testMatch; + } else { + lastResult = + compare(new Comparison(ComparisonType.CHILD_LOOKUP, + controlList.get(i), null, + controlList.get(i), + null, null, null)); +]]></literal> + <if-return-boilerplate/> + <literal><![CDATA[ + } + } + return lastResult; } private ComparisonResult compareAttributes(Attr control, Attr test) { @@ -250,7 +281,8 @@ test, null, test.getValue())); } - private static Attr findMatchingAttr(NamedNodeMap map, Attr attrToMatch) { + private static Attr findMatchingAttr(final NamedNodeMap map, + final Attr attrToMatch) { if (attrToMatch.getNamespaceURI() == null) { return (Attr) map.getNamedItem(attrToMatch.getName()); } else { @@ -259,5 +291,39 @@ } } + private Match findMatchingNode(final Node searchFor, + final List<Node> searchIn, + final int indexOfLastMatch) { + final int searchSize = searchIn.size(); + for (int i = indexOfLastMatch + 1; i < searchSize; i++) { + if (nodesMatch(searchFor, searchIn.get(i))) { + return new Match(searchIn.get(i), i); + } + } + for (int i = 0; i < indexOfLastMatch; i++) { + if (nodesMatch(searchFor, searchIn.get(i))) { + return new Match(searchIn.get(i), i); + } + } + return null; + } + + private boolean nodesMatch(final Node n1, final Node n2) { + ComparisonResult r = + compare(new Comparison(ComparisonType.NODE_TYPE, + n1, null, n1.getNodeType(), + n2, null, n2.getNodeType())); + return r == ComparisonResult.EQUAL; + } + + private class Match { + private final Node node; + private final int index; + private Match(Node match, int index) { + this.node = match; + this.index = index; + } + } + ]]></literal> </class> \ No newline at end of file Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/IterableNodeList.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/IterableNodeList.java 2010-08-13 11:54:14 UTC (rev 424) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/IterableNodeList.java 2010-08-13 13:10:16 UTC (rev 425) @@ -13,7 +13,9 @@ */ package net.sf.xmlunit.util; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -46,4 +48,22 @@ return current < length; } } + + /** + * Turns the iterable into a list. + */ + public static List<Node> asList(IterableNodeList l) { + ArrayList<Node> a = new ArrayList<Node>(l.length); + for (Node n : l) { + a.add(n); + } + return a; + } + + /** + * Turns the NodeList into a list. + */ + public static List<Node> asList(NodeList l) { + return asList(new IterableNodeList(l)); + } } Modified: trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.xml =================================================================== --- trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.xml 2010-08-13 11:54:14 UTC (rev 424) +++ trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.xml 2010-08-13 13:10:16 UTC (rev 425) @@ -18,6 +18,7 @@ extends="AbstractDifferenceEngine"> <import reference="System"/> + <import reference="System.Collections.Generic"/> <import reference="System.Xml"/> <literal><![CDATA[ @@ -234,7 +235,40 @@ private ComparisonResult CompareNodeLists(XmlNodeList control, XmlNodeList test) { - return ComparisonResult.EQUAL; + List<XmlNode> controlList = + new List<XmlNode>(net.sf.xmlunit.util.Convert + .Cast<XmlNode>(control)); + List<XmlNode> testList = + new List<XmlNode>(net.sf.xmlunit.util.Convert + .Cast<XmlNode>(test)); + Match lastMatch = new Match(null, -1); +]]></literal> + <lastResultDef/> + // if there are no children on either Node, the result is equal + lastResult = ComparisonResult.EQUAL; + <literal><![CDATA[ + for (int i = 0; i < controlList.Count; i++) { + Match testMatch = FindMatchingNode(controlList[i], testList, + lastMatch.index); + if (testMatch != null) { +]]></literal> + <compareMethodExpr method="CompareNodes" + controlExpr="controlList[i]" + testExpr="testMatch.node"/> + <literal><![CDATA[ + lastMatch = testMatch; + } else { + lastResult = + Compare(new Comparison(ComparisonType.CHILD_LOOKUP, + controlList[i], null, + controlList[i], + null, null, null)); +]]></literal> + <if-return-boilerplate/> + <literal><![CDATA[ + } + } + return lastResult; } private ComparisonResult CompareAttributes(XmlAttribute control, @@ -258,5 +292,39 @@ as XmlAttribute; } } + + private Match FindMatchingNode(XmlNode searchFor, + IList<XmlNode> searchIn, + int indexOfLastMatch) { + int searchSize = searchIn.Count; + for (int i = indexOfLastMatch + 1; i < searchSize; i++) { + if (NodesMatch(searchFor, searchIn[i])) { + return new Match(searchIn[i], i); + } + } + for (int i = 0; i < indexOfLastMatch; i++) { + if (NodesMatch(searchFor, searchIn[i])) { + return new Match(searchIn[i], i); + } + } + return null; + } + + private bool NodesMatch(XmlNode n1, XmlNode n2) { + ComparisonResult r = + Compare(new Comparison(ComparisonType.NODE_TYPE, + n1, null, n1.NodeType, + n2, null, n2.NodeType)); + return r == ComparisonResult.EQUAL; + } + + internal class Match { + internal readonly XmlNode node; + internal readonly int index; + internal Match(XmlNode match, int index) { + this.node = match; + this.index = index; + } + } ]]></literal> </class> \ No newline at end of file Modified: trunk/xmlunit/src/main/net-core/util/Convert.cs =================================================================== --- trunk/xmlunit/src/main/net-core/util/Convert.cs 2010-08-13 11:54:14 UTC (rev 424) +++ trunk/xmlunit/src/main/net-core/util/Convert.cs 2010-08-13 13:10:16 UTC (rev 425) @@ -12,6 +12,7 @@ limitations under the License. */ +using System.Collections; using System.Collections.Generic; using System.Xml; using net.sf.xmlunit.input; @@ -72,5 +73,11 @@ } return man; } + + public static IEnumerable<T> Cast<T>(IEnumerable i) { + foreach (T t in i) { + yield return t; + } + } } } Modified: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java =================================================================== --- trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java 2010-08-13 11:54:14 UTC (rev 424) +++ trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java 2010-08-13 13:10:16 UTC (rev 425) @@ -185,7 +185,7 @@ d.compareNodes(fooCDATASection, fooCDATASection)); assertEquals(ComparisonResult.CRITICAL, d.compareNodes(fooCDATASection, barCDATASection)); - + assertEquals(ComparisonResult.EQUAL, d.compareNodes(fooComment, fooText)); assertEquals(ComparisonResult.CRITICAL, @@ -467,4 +467,36 @@ assertEquals(ComparisonResult.CRITICAL, d.compareNodes(a1, a3)); assertEquals(1, ex.invoked); } + + @Test public void naiveRecursion() { + Element e1 = doc.createElement("foo"); + Element e2 = doc.createElement("foo"); + Element c1 = doc.createElement("bar"); + e1.appendChild(c1); + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.CHILD_LOOKUP); + d.addDifferenceListener(ex); + DifferenceEvaluator ev = new DifferenceEvaluator() { + public ComparisonResult evaluate(Comparison comparison, + ComparisonResult outcome) { + if (comparison.getType() == ComparisonType.CHILD_NODELIST_LENGTH) { + return ComparisonResult.EQUAL; + } + return DifferenceEvaluators.DefaultStopWhenDifferent + .evaluate(comparison, outcome); + } + }; + d.setDifferenceEvaluator(ev); + assertEquals(ComparisonResult.CRITICAL, d.compareNodes(e1, e2)); + assertEquals(1, ex.invoked); + + Element c2 = doc.createElement("bar"); + e2.appendChild(c2); + d = new DOMDifferenceEngine(); + ex = new DiffExpecter(ComparisonType.CHILD_LOOKUP); + d.addDifferenceListener(ex); + d.setDifferenceEvaluator(ev); + assertEquals(ComparisonResult.EQUAL, d.compareNodes(e1, e2)); + assertEquals(0, ex.invoked); + } } Modified: trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs =================================================================== --- trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs 2010-08-13 11:54:14 UTC (rev 424) +++ trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs 2010-08-13 13:10:16 UTC (rev 425) @@ -172,7 +172,7 @@ d.CompareNodes(fooCDataSection, fooCDataSection)); Assert.AreEqual(ComparisonResult.CRITICAL, d.CompareNodes(fooCDataSection, barCDataSection)); - + Assert.AreEqual(ComparisonResult.EQUAL, d.CompareNodes(fooComment, fooText)); Assert.AreEqual(ComparisonResult.CRITICAL, @@ -460,5 +460,37 @@ Assert.AreEqual(ComparisonResult.CRITICAL, d.CompareNodes(a1, a3)); Assert.AreEqual(1, ex.invoked); } + + [Test] + public void NaiveRecursion() { + XmlElement e1 = doc.CreateElement("foo"); + XmlElement e2 = doc.CreateElement("foo"); + XmlElement c1 = doc.CreateElement("bar"); + e1.AppendChild(c1); + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.CHILD_LOOKUP); + d.DifferenceListener += ex.ComparisonPerformed; + DifferenceEvaluator ev = delegate(Comparison comparison, + ComparisonResult outcome) { + if (comparison.Type == ComparisonType.CHILD_NODELIST_LENGTH) { + return ComparisonResult.EQUAL; + } + return DifferenceEvaluators.DefaultStopWhenDifferent(comparison, + outcome); + }; + d.DifferenceEvaluator = ev; + Assert.AreEqual(ComparisonResult.CRITICAL, d.CompareNodes(e1, e2)); + Assert.AreEqual(1, ex.invoked); + + XmlElement c2 = doc.CreateElement("bar"); + e2.AppendChild(c2); + d = new DOMDifferenceEngine(); + ex = new DiffExpecter(ComparisonType.CHILD_LOOKUP); + d.DifferenceListener += ex.ComparisonPerformed; + d.DifferenceEvaluator = ev; + Assert.AreEqual(ComparisonResult.EQUAL, d.CompareNodes(e1, e2)); + Assert.AreEqual(0, ex.invoked); + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |