package org.tigris.juxy.xpath; import org.tigris.juxy.util.ArgumentAssert; import org.tigris.juxy.util.DocumentsAssertionError; import org.tigris.juxy.util.StringUtil; import org.tigris.juxy.util.XMLComparator; import org.w3c.dom.Node; /** * @author pavel */ public class XPathAssert { private XPathExpr xpath; private AssertionEvaluator evaluator; /** * This assertion evaluates XPath expression to boolean value and asserts that * result is true. This is same as {@link #XPathAssert(String, boolean)} with second argument == true. * @param xpathExpr XPath expression */ public XPathAssert(String xpathExpr) { this(xpathExpr, true); } /** * This assertion evaluates XPath expression to integer and compares it with expected result. * @param xpathExpr XPath expression * @param expectedResult expected result */ public XPathAssert(String xpathExpr, final int expectedResult) { xpath = XPathFactory.newXPath(xpathExpr); evaluator = new AssertionEvaluator() { public void eval(Node node) throws XPathExpressionException { int actual = xpath.toInt(node); if (expectedResult != actual) { throw assertionError(String.valueOf(actual), String.valueOf(expectedResult)); } } }; } /** * This assertion evaluates XPath expression to boolean and compares it with expected result. * @param xpathExpr XPath expression * @param expectedResult expected result */ public XPathAssert(String xpathExpr, final boolean expectedResult) { xpath = XPathFactory.newXPath(xpathExpr); evaluator = new AssertionEvaluator() { public void eval(Node node) throws XPathExpressionException { boolean actual = xpath.toBoolean(node); if (expectedResult != actual) { throw assertionError(String.valueOf(actual), String.valueOf(expectedResult)); } } }; } /** * This assertion evaluates XPath expression to double and compares it with expected result with specified precision. * @param xpathExpr XPath expression * @param expectedResult expected result * @param error error value */ public XPathAssert(String xpathExpr, final double expectedResult, final double error) { xpath = XPathFactory.newXPath(xpathExpr); evaluator = new AssertionEvaluator() { public void eval(Node node) throws XPathExpressionException { double actual = xpath.toDouble(node); if (Math.abs(actual - expectedResult) > error) { throw assertionError(String.valueOf(actual), String.valueOf(expectedResult) + "+-" + String.valueOf(error)); } } }; } /** * This assertion evaluates XPath expression to string and compares it with expected result. * No normalization is performed before comparing. * @param xpathExpr XPath expression * @param expectedResult expected result */ public XPathAssert(String xpathExpr, final String expectedResult) { xpath = XPathFactory.newXPath(xpathExpr); evaluator = new AssertionEvaluator() { public void eval(Node node) throws XPathExpressionException { String actual = xpath.toString(node); if (!expectedResult.equals(actual)) { throw assertionError(actual, expectedResult); } } }; } /** * This assertion evaluates XPath expression to string and compares it with expected result. * XPath expression result can be normalized before comparing. * @param xpathExpr XPath expression * @param expectedResult expected result * @param normalizeBeforeAssert indicates whether normalization of the XPath expression result * should be performed before comparing with expected value (see {@link org.tigris.juxy.util.StringUtil#normalizeAll}) */ public XPathAssert(String xpathExpr, final String expectedResult, final boolean normalizeBeforeAssert) { xpath = XPathFactory.newXPath(xpathExpr); evaluator = new AssertionEvaluator() { public void eval(Node node) throws XPathExpressionException { String actual = xpath.toString(node); actual = normalizeBeforeAssert ? StringUtil.normalizeAll(actual) : actual; if (!expectedResult.equals(actual)) { throw assertionError(actual, expectedResult); } } }; } /** * This assertion evaluates XPath expression to Node and compares it with expected node using {@link org.tigris.juxy.util.XMLComparator} class. * @param xpathExpr XPath expression * @param expectedNode node to compare result with */ public XPathAssert(String xpathExpr, final Node expectedNode) { xpath = XPathFactory.newXPath(xpathExpr); evaluator = new AssertionEvaluator() { public void eval(Node node) throws XPathExpressionException { Node actual = xpath.toNode(node); if (actual == null) { throw new AssertionError("XPath expression " + xpath.getExpression() + " returned null"); } try { XMLComparator.assertEquals(expectedNode, actual); } catch (DocumentsAssertionError error) { throw new AssertionError(error.getMessage()); } } }; } /** * Registers a namespace in the xpath expression. Returns the same XPathAssert object. * @param prefix namespace prefix * @param uri namespace URI * @return same XPathAssert object * @throws XPathExpressionException */ public XPathAssert addNamespace(String prefix, String uri) throws XPathExpressionException { xpath.addNamespace(prefix, uri); return this; } /** * Evaluates this assertion. * @param node node to evaluate assertion on * @throws XPathExpressionException * @throws AssertionError if assertion failed */ public void eval(Node node) throws XPathExpressionException, AssertionError { ArgumentAssert.notNull(node, "Node must not be null"); evaluator.eval(node); } private AssertionError assertionError(final String actual, final String expectedResult) { return new AssertionError(xpath.getExpression() + " expected <" + expectedResult + "> but was <" + actual + ">"); } private interface AssertionEvaluator { void eval(Node node) throws XPathExpressionException, AssertionError; } }