From: <bo...@us...> - 2014-12-01 04:05:08
|
Revision: 561 http://sourceforge.net/p/xmlunit/code/561 Author: bodewig Date: 2014-12-01 04:05:05 +0000 (Mon, 01 Dec 2014) Log Message: ----------- more porting work Modified Paths: -------------- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java 2014-11-30 05:13:52 UTC (rev 560) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java 2014-12-01 04:05:05 UTC (rev 561) @@ -418,21 +418,18 @@ XPathContext controlContext, ProcessingInstruction test, XPathContext testContext) { - ComparisonResult lastResult = + return new ComparisonChain( compare(new Comparison(ComparisonType.PROCESSING_INSTRUCTION_TARGET, control, getXPath(controlContext), control.getTarget(), test, getXPath(testContext), - test.getTarget())); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } - - return compare(new Comparison(ComparisonType.PROCESSING_INSTRUCTION_DATA, - control, getXPath(controlContext), - control.getData(), - test, getXPath(testContext), - test.getData())); + test.getTarget()))) + .andThen(comparer(new Comparison(ComparisonType.PROCESSING_INSTRUCTION_DATA, + control, getXPath(controlContext), + control.getData(), + test, getXPath(testContext), + test.getData()))) + .getFinalResult(); } /** @@ -539,6 +536,8 @@ if (!mustChangeControlContext && !mustChangeTestContext) { return ComparisonResult.EQUAL; } + boolean attributePresentOnBothSides = mustChangeControlContext + && mustChangeTestContext; try { if (mustChangeControlContext) { @@ -551,34 +550,24 @@ testContext.addAttribute(q); testContext.navigateToAttribute(q); } - ComparisonResult lastResult = + return new ComparisonChain( compare(new Comparison(ComparisonType.ATTR_NAME_LOOKUP, controlAttr, getXPath(controlContext), mustChangeControlContext, testAttr, getXPath(testContext), - mustChangeTestContext)); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } - if (mustChangeControlContext && mustChangeTestContext) { - lastResult = - compareAttributeExplicitness(controlAttr, controlContext, - testAttr, testContext); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } - QName controlQName = valueAsQName(controlAttr); - QName testQName = valueAsQName(testAttr); - lastResult = - compare(new Comparison(ComparisonType.ATTR_VALUE, - controlAttr, - getXPath(controlContext), - controlQName.toString(), - testAttr, - getXPath(testContext), - testQName.toString())); - } - return lastResult; + mustChangeTestContext))) + .andIfTrueThen(attributePresentOnBothSides, + compareAttributeExplicitness(controlAttr, controlContext, + testAttr, testContext)) + .andIfTrueThen(attributePresentOnBothSides, + comparer(new Comparison(ComparisonType.ATTR_VALUE, + controlAttr, + getXPath(controlContext), + valueAsQName(controlAttr).toString(), + testAttr, + getXPath(testContext), + valueAsQName(testAttr).toString()))) + .getFinalResult(); } finally { if (mustChangeControlContext) { controlContext.navigateToParent(); @@ -596,28 +585,25 @@ XPathContext controlContext, Attr test, XPathContext testContext) { - ComparisonResult lastResult = + return new ComparisonChain( compareAttributeExplicitness(control, controlContext, test, - testContext); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } - - return compare(new Comparison(ComparisonType.ATTR_VALUE, - control, getXPath(controlContext), - control.getValue(), - test, getXPath(testContext), - test.getValue())); + testContext).apply()) + .andThen(comparer(new Comparison(ComparisonType.ATTR_VALUE, + control, getXPath(controlContext), + control.getValue(), + test, getXPath(testContext), + test.getValue()))) + .getFinalResult(); } /** * Compares whether two attributes are specified explicitly. */ - private ComparisonResult + private DeferredComparison compareAttributeExplicitness(Attr control, XPathContext controlContext, Attr test, XPathContext testContext) { return - compare(new Comparison(ComparisonType.ATTR_VALUE_EXPLICITLY_SPECIFIED, + comparer(new Comparison(ComparisonType.ATTR_VALUE_EXPLICITLY_SPECIFIED, control, getXPath(controlContext), control.getSpecified(), test, getXPath(testContext), Modified: trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs =================================================================== --- trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs 2014-11-30 05:13:52 UTC (rev 560) +++ trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs 2014-12-01 04:05:05 UTC (rev 561) @@ -560,7 +560,6 @@ test, GetXPath(testContext), mustChangeTestContext))) .AndIfTrueThen(attributePresentOnBothSides, - () => CompareAttributeExplicitness(control, controlContext, test, testContext)) .AndIfTrueThen(attributePresentOnBothSides, @@ -591,7 +590,7 @@ XPathContext testContext) { return new ComparisonChain( CompareAttributeExplicitness(control, controlContext, - test, testContext)) + test, testContext)()) .AndThen(Comparer(new Comparison(ComparisonType.ATTR_VALUE, control, GetXPath(controlContext), control.Value, @@ -603,17 +602,17 @@ /// <summary> // Compares whether two attributes are specified explicitly. /// </summary> - private ComparisonResult + private Func<ComparisonResult> CompareAttributeExplicitness(XmlAttribute control, XPathContext controlContext, XmlAttribute test, XPathContext testContext) { return - Compare(new Comparison(ComparisonType.ATTR_VALUE_EXPLICITLY_SPECIFIED, - control, GetXPath(controlContext), - control.Specified, - test, GetXPath(testContext), - test.Specified)); + Comparer(new Comparison(ComparisonType.ATTR_VALUE_EXPLICITLY_SPECIFIED, + control, GetXPath(controlContext), + control.Specified, + test, GetXPath(testContext), + test.Specified)); } /// <summary> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bo...@us...> - 2014-12-01 20:42:31
|
Revision: 562 http://sourceforge.net/p/xmlunit/code/562 Author: bodewig Date: 2014-12-01 20:42:22 +0000 (Mon, 01 Dec 2014) Log Message: ----------- completely remove lastResult logic Modified Paths: -------------- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java 2014-12-01 04:05:05 UTC (rev 561) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java 2014-12-01 20:42:22 UTC (rev 562) @@ -291,123 +291,182 @@ * Compares elements node properties, in particular the element's * name and its attributes. */ - private ComparisonResult compareElements(Element control, - XPathContext controlContext, - Element test, - XPathContext testContext) { - ComparisonResult lastResult = + private ComparisonResult compareElements(final Element control, + final XPathContext controlContext, + final Element test, + final XPathContext testContext) { + return new ComparisonChain( compare(new Comparison(ComparisonType.ELEMENT_TAG_NAME, control, getXPath(controlContext), Nodes.getQName(control).getLocalPart(), test, getXPath(testContext), - Nodes.getQName(test).getLocalPart())); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } + Nodes.getQName(test).getLocalPart()))) + .andThen(new DeferredComparison() { + public ComparisonResult apply() { + return compareElementAttributes(control, controlContext, + test, testContext); + } + }) + .getFinalResult(); + } - Attributes controlAttributes = splitAttributes(control.getAttributes()); + /** + * Compares element's attributes. + */ + private ComparisonResult compareElementAttributes(final Element control, + final XPathContext controlContext, + final Element test, + final XPathContext testContext) { + final Attributes controlAttributes = splitAttributes(control.getAttributes()); controlContext .addAttributes(Linqy.map(controlAttributes.remainingAttributes, QNAME_MAPPER)); - Attributes testAttributes = splitAttributes(test.getAttributes()); + final Attributes testAttributes = splitAttributes(test.getAttributes()); testContext .addAttributes(Linqy.map(testAttributes.remainingAttributes, QNAME_MAPPER)); - lastResult = + return new ComparisonChain( compare(new Comparison(ComparisonType.ELEMENT_NUM_ATTRIBUTES, control, getXPath(controlContext), controlAttributes.remainingAttributes.size(), test, getXPath(testContext), - testAttributes.remainingAttributes.size())); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; + testAttributes.remainingAttributes.size()))) + .andThen(new DeferredComparison() { + public ComparisonResult apply() { + return compareXsiType(controlAttributes.type, controlContext, + testAttributes.type, testContext); + } + }) + .andThen(comparer(new Comparison(ComparisonType.SCHEMA_LOCATION, + control, getXPath(controlContext), + controlAttributes.schemaLocation != null + ? controlAttributes.schemaLocation.getValue() + : null, + test, getXPath(testContext), + testAttributes.schemaLocation != null + ? testAttributes.schemaLocation.getValue() + : null))) + .andThen(comparer(new Comparison(ComparisonType.NO_NAMESPACE_SCHEMA_LOCATION, + control, getXPath(controlContext), + controlAttributes.noNamespaceSchemaLocation != null ? + controlAttributes.noNamespaceSchemaLocation.getValue() + : null, + test, getXPath(testContext), + testAttributes.noNamespaceSchemaLocation != null + ? testAttributes.noNamespaceSchemaLocation.getValue() + : null))) + .andThen(new NormalAttributeComparer(control, controlContext, + controlAttributes, test, + testContext, testAttributes)) + .getFinalResult(); + } + + private class NormalAttributeComparer implements DeferredComparison { + private final Set<Attr> foundTestAttributes = new HashSet<Attr>(); + private final Element control, test; + private final XPathContext controlContext, testContext; + private final Attributes controlAttributes, testAttributes; + + private NormalAttributeComparer(Element control, + XPathContext controlContext, + Attributes controlAttributes, + Element test, + XPathContext testContext, + Attributes testAttributes) { + this.control = control; + this.controlContext = controlContext; + this.controlAttributes = controlAttributes; + this.test = test; + this.testContext = testContext; + this.testAttributes = testAttributes; } - Set<Attr> foundTestAttributes = new HashSet<Attr>(); - for (Attr controlAttr : controlAttributes.remainingAttributes) { - final Attr testAttr = - findMatchingAttr(testAttributes.remainingAttributes, - controlAttr); + public ComparisonResult apply() { + ComparisonChain chain = new ComparisonChain(); + for (final Attr controlAttr : controlAttributes.remainingAttributes) { + final Attr testAttr = + findMatchingAttr(testAttributes.remainingAttributes, + controlAttr); - controlContext.navigateToAttribute(Nodes.getQName(controlAttr)); - try { - lastResult = - compare(new Comparison(ComparisonType.ATTR_NAME_LOOKUP, - control, getXPath(controlContext), - Boolean.TRUE, - test, getXPath(testContext), - Boolean.valueOf(testAttr != null))); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } + controlContext.navigateToAttribute(Nodes.getQName(controlAttr)); + try { + chain.andThen( + comparer(new Comparison(ComparisonType.ATTR_NAME_LOOKUP, + control, getXPath(controlContext), + Boolean.TRUE, + test, getXPath(testContext), + Boolean.valueOf(testAttr != null)))); - if (testAttr != null) { - testContext.navigateToAttribute(Nodes.getQName(testAttr)); - try { - lastResult = compareNodes(controlAttr, controlContext, - testAttr, testContext); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; + if (testAttr != null) { + testContext.navigateToAttribute(Nodes.getQName(testAttr)); + try { + chain.andThen(new DeferredComparison() { + public ComparisonResult apply() { + return compareNodes(controlAttr, + controlContext, + testAttr, + testContext); + } + }); + foundTestAttributes.add(testAttr); + } finally { + testContext.navigateToParent(); } - - foundTestAttributes.add(testAttr); - } finally { - testContext.navigateToParent(); } + } finally { + controlContext.navigateToParent(); } - } finally { - controlContext.navigateToParent(); } + return chain.andThen(new ControlAttributePresentComparer(control, + controlContext, + test, testContext, + testAttributes, + foundTestAttributes)) + .getFinalResult(); } + } + + private class ControlAttributePresentComparer implements DeferredComparison { - for (Attr testAttr : testAttributes.remainingAttributes) { - testContext.navigateToAttribute(Nodes.getQName(testAttr)); - try { - lastResult = - compare(new Comparison(ComparisonType.ATTR_NAME_LOOKUP, - control, getXPath(controlContext), - Boolean.valueOf(foundTestAttributes.contains(testAttr)), - test, getXPath(testContext), - Boolean.TRUE)); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } - } finally { - testContext.navigateToParent(); - } - } + private final Set<Attr> foundTestAttributes; + private final Element control, test; + private final XPathContext controlContext, testContext; + private final Attributes testAttributes; - lastResult = compareXsiType(controlAttributes.type, controlContext, - testAttributes.type, testContext); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; + private ControlAttributePresentComparer(Element control, + XPathContext controlContext, + Element test, + XPathContext testContext, + Attributes testAttributes, + Set<Attr> foundTestAttributes) { + this.control = control; + this.controlContext = controlContext; + this.test = test; + this.testContext = testContext; + this.testAttributes = testAttributes; + this.foundTestAttributes = foundTestAttributes; } - lastResult = - compare(new Comparison(ComparisonType.SCHEMA_LOCATION, - control, getXPath(controlContext), - controlAttributes.schemaLocation != null - ? controlAttributes.schemaLocation.getValue() - : null, - test, getXPath(testContext), - testAttributes.schemaLocation != null - ? testAttributes.schemaLocation.getValue() - : null)); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; + public ComparisonResult apply() { + ComparisonChain chain = new ComparisonChain(); + for (Attr testAttr : testAttributes.remainingAttributes) { + testContext.navigateToAttribute(Nodes.getQName(testAttr)); + try { + chain.andThen(comparer(new Comparison(ComparisonType.ATTR_NAME_LOOKUP, + control, getXPath(controlContext), + Boolean + .valueOf(foundTestAttributes + .contains(testAttr)), + test, getXPath(testContext), + Boolean.TRUE))); + } finally { + testContext.navigateToParent(); + } + } + return chain.getFinalResult(); } - return - compare(new Comparison(ComparisonType.NO_NAMESPACE_SCHEMA_LOCATION, - control, getXPath(controlContext), - controlAttributes.noNamespaceSchemaLocation != null ? - controlAttributes.noNamespaceSchemaLocation.getValue() - : null, - test, getXPath(testContext), - testAttributes.noNamespaceSchemaLocation != null - ? testAttributes.noNamespaceSchemaLocation.getValue() - : null)); } /** @@ -439,11 +498,10 @@ * couldn't be matched to one of the "other" list.</p> */ private ComparisonResult compareNodeLists(Iterable<Node> controlSeq, - XPathContext controlContext, + final XPathContext controlContext, Iterable<Node> testSeq, - XPathContext testContext) { - // if there are no children on either Node, the result is equal - ComparisonResult lastResult = ComparisonResult.EQUAL; + final XPathContext testContext) { + ComparisonChain chain = new ComparisonChain(); Iterable<Map.Entry<Node, Node>> matches = getNodeMatcher().match(controlSeq, testSeq); @@ -451,9 +509,9 @@ List<Node> testList = Linqy.asList(testSeq); Set<Node> seen = new HashSet<Node>(); for (Map.Entry<Node, Node> pair : matches) { - Node control = pair.getKey(); + final Node control = pair.getKey(); seen.add(control); - Node test = pair.getValue(); + final Node test = pair.getValue(); seen.add(test); int controlIndex = controlList.indexOf(control); int testIndex = testList.indexOf(test); @@ -461,67 +519,92 @@ controlContext.navigateToChild(controlIndex); testContext.navigateToChild(testIndex); try { - lastResult = - compare(new Comparison(ComparisonType.CHILD_NODELIST_SEQUENCE, - control, getXPath(controlContext), - Integer.valueOf(controlIndex), - test, getXPath(testContext), - Integer.valueOf(testIndex))); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } - - lastResult = compareNodes(control, controlContext, - test, testContext); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; - } + chain.andThen(comparer(new Comparison(ComparisonType.CHILD_NODELIST_SEQUENCE, + control, getXPath(controlContext), + Integer.valueOf(controlIndex), + test, getXPath(testContext), + Integer.valueOf(testIndex)))) + .andThen(new DeferredComparison() { + public ComparisonResult apply() { + return compareNodes(control, controlContext, + test, testContext); + } + }); } finally { testContext.navigateToParent(); controlContext.navigateToParent(); } } - final int controlSize = controlList.size(); - for (int i = 0; i < controlSize; i++) { - if (!seen.contains(controlList.get(i))) { - controlContext.navigateToChild(i); - try { - lastResult = - compare(new Comparison(ComparisonType.CHILD_LOOKUP, - controlList.get(i), - getXPath(controlContext), - controlList.get(i), - null, null, null)); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; + return chain.andThen(new UnmatchedControlNodes(controlList, controlContext, seen)) + .andThen(new UnmatchedTestNodes(testList, testContext, seen)) + .getFinalResult(); + } + + private class UnmatchedControlNodes implements DeferredComparison { + private final List<Node> controlList; + private final XPathContext controlContext; + private final Set<Node> seen; + + private UnmatchedControlNodes(List<Node> controlList, XPathContext controlContext, + Set<Node> seen) { + this.controlList = controlList; + this.controlContext = controlContext; + this.seen = seen; + } + + public ComparisonResult apply() { + ComparisonChain chain = new ComparisonChain(); + final int controlSize = controlList.size(); + for (int i = 0; i < controlSize; i++) { + if (!seen.contains(controlList.get(i))) { + controlContext.navigateToChild(i); + try { + chain.andThen(comparer(new Comparison(ComparisonType.CHILD_LOOKUP, + controlList.get(i), + getXPath(controlContext), + controlList.get(i), + null, null, null))); + } finally { + controlContext.navigateToParent(); } - } finally { - controlContext.navigateToParent(); } } + return chain.getFinalResult(); } + } + + private class UnmatchedTestNodes implements DeferredComparison { + private final List<Node> testList; + private final XPathContext testContext; + private final Set<Node> seen; + + private UnmatchedTestNodes(List<Node> testList, XPathContext testContext, + Set<Node> seen) { + this.testList = testList; + this.testContext = testContext; + this.seen = seen; + } - final int testSize = testList.size(); - for (int i = 0; i < testSize; i++) { - if (!seen.contains(testList.get(i))) { - testContext.navigateToChild(i); - try { - lastResult = - compare(new Comparison(ComparisonType.CHILD_LOOKUP, - null, null, null, - testList.get(i), - getXPath(testContext), - testList.get(i))); - if (lastResult == ComparisonResult.CRITICAL) { - return lastResult; + public ComparisonResult apply() { + ComparisonChain chain = new ComparisonChain(); + final int testSize = testList.size(); + for (int i = 0; i < testSize; i++) { + if (!seen.contains(testList.get(i))) { + testContext.navigateToChild(i); + try { + chain.andThen(comparer(new Comparison(ComparisonType.CHILD_LOOKUP, + null, null, null, + testList.get(i), + getXPath(testContext), + testList.get(i)))); + } finally { + testContext.navigateToParent(); } - } finally { - testContext.navigateToParent(); } } + return chain.getFinalResult(); } - return lastResult; } /** Modified: trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs =================================================================== --- trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs 2014-12-01 04:05:05 UTC (rev 561) +++ trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs 2014-12-01 20:42:22 UTC (rev 562) @@ -296,18 +296,18 @@ control.Name, test, GetXPath(testContext), test.Name))) - .AndThen(() => CompareAttributes(control, controlContext, - test, testContext)) + .AndThen(() => CompareElementAttributes(control, controlContext, + test, testContext)) .FinalResult; } /// <summary> /// Compares element's attributes. /// </summary> - private ComparisonResult CompareAttributes(XmlElement control, - XPathContext controlContext, - XmlElement test, - XPathContext testContext) { + private ComparisonResult CompareElementAttributes(XmlElement control, + XPathContext controlContext, + XmlElement test, + XPathContext testContext) { Attributes controlAttributes = SplitAttributes(control.Attributes); controlContext .AddAttributes(controlAttributes.RemainingAttributes @@ -484,47 +484,59 @@ } return chain - .AndThen(() => { - ComparisonChain secondChain = new ComparisonChain(); - int controlSize = controlList.Count; - for (int i = 0; i < controlSize; i++) { - if (!seen.ContainsKey(controlList[i])) { - controlContext.NavigateToChild(i); - try { - secondChain - .AndThen(Comparer(new Comparison(ComparisonType.CHILD_LOOKUP, - controlList[i], - GetXPath(controlContext), - controlList[i], - null, null, null))); - } finally { - controlContext.NavigateToParent(); - } - } + .AndThen(UnmatchedControlNodes(controlList, controlContext, seen)) + .AndThen(UnmatchedTestNodes(testList, testContext, seen)) + .FinalResult; + } + + private Func<ComparisonResult> UnmatchedControlNodes(IList<XmlNode> controlList, + XPathContext controlContext, + IDictionary<XmlNode, object> seen) { + return () => { + ComparisonChain chain = new ComparisonChain(); + int controlSize = controlList.Count; + for (int i = 0; i < controlSize; i++) { + if (!seen.ContainsKey(controlList[i])) { + controlContext.NavigateToChild(i); + try { + chain + .AndThen(Comparer(new Comparison(ComparisonType.CHILD_LOOKUP, + controlList[i], + GetXPath(controlContext), + controlList[i], + null, null, null))); + } finally { + controlContext.NavigateToParent(); } - return secondChain.FinalResult; - }) - .AndThen(() => { - ComparisonChain thirdChain = new ComparisonChain(); - int testSize = testList.Count; - for (int i = 0; i < testSize; i++) { - if (!seen.ContainsKey(testList[i])) { - testContext.NavigateToChild(i); - try { - thirdChain - .AndThen(Comparer(new Comparison(ComparisonType.CHILD_LOOKUP, - null, null, null, - testList[i], - GetXPath(testContext), - testList[i]))); - } finally { - testContext.NavigateToParent(); - } - } + } + } + return chain.FinalResult; + }; + } + + private Func<ComparisonResult> UnmatchedTestNodes(IList<XmlNode> testList, + XPathContext testContext, + IDictionary<XmlNode, object> seen) { + return () => { + ComparisonChain chain = new ComparisonChain(); + int testSize = testList.Count; + for (int i = 0; i < testSize; i++) { + if (!seen.ContainsKey(testList[i])) { + testContext.NavigateToChild(i); + try { + chain + .AndThen(Comparer(new Comparison(ComparisonType.CHILD_LOOKUP, + null, null, null, + testList[i], + GetXPath(testContext), + testList[i]))); + } finally { + testContext.NavigateToParent(); } - return thirdChain.FinalResult; - }) - .FinalResult; + } + } + return chain.FinalResult; + }; } /// <summary> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |