Author: henrib Date: Thu Jan 7 18:00:07 2010 New Revision: 896944 URL: http://svn.apache.org/viewvc?rev=896944&view=rev Log: JEXL-46; adding Perl-like regular-expression operators (=~ and !~)
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java?rev=896944&r1=896943&r2=896944&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Debugger.java Thu Jan 7 18:00:07 2010 @@ -31,6 +31,7 @@ import org.apache.commons.jexl2.parser.ASTConstructorNode; import org.apache.commons.jexl2.parser.ASTDivNode; import org.apache.commons.jexl2.parser.ASTEQNode; +import org.apache.commons.jexl2.parser.ASTERNode; import org.apache.commons.jexl2.parser.ASTEmptyFunction; import org.apache.commons.jexl2.parser.ASTFalseNode; import org.apache.commons.jexl2.parser.ASTFloatLiteral; @@ -50,6 +51,7 @@ import org.apache.commons.jexl2.parser.ASTModNode; import org.apache.commons.jexl2.parser.ASTMulNode; import org.apache.commons.jexl2.parser.ASTNENode; +import org.apache.commons.jexl2.parser.ASTNRNode; import org.apache.commons.jexl2.parser.ASTNotNode; import org.apache.commons.jexl2.parser.ASTNullLiteral; import org.apache.commons.jexl2.parser.ASTOrNode; @@ -361,6 +363,11 @@ } /** {...@inheritdoc} */ + public Object visit(ASTERNode node, Object data) { + return infixChildren(node, " =~ ", false, data); + } + + /** {...@inheritdoc} */ public Object visit(ASTFalseNode node, Object data) { return check(node, "false", data); } @@ -527,6 +534,11 @@ } /** {...@inheritdoc} */ + public Object visit(ASTNRNode node, Object data) { + return infixChildren(node, " !~ ", false, data); + } + + /** {...@inheritdoc} */ public Object visit(ASTNotNode node, Object data) { builder.append("!"); accept(node.jjtGetChild(0), data); Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java?rev=896944&r1=896943&r2=896944&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/Interpreter.java Thu Jan 7 18:00:07 2010 @@ -45,6 +45,7 @@ import org.apache.commons.jexl2.parser.ASTConstructorNode; import org.apache.commons.jexl2.parser.ASTDivNode; import org.apache.commons.jexl2.parser.ASTEQNode; +import org.apache.commons.jexl2.parser.ASTERNode; import org.apache.commons.jexl2.parser.ASTEmptyFunction; import org.apache.commons.jexl2.parser.ASTFalseNode; import org.apache.commons.jexl2.parser.ASTFunctionNode; @@ -64,6 +65,7 @@ import org.apache.commons.jexl2.parser.ASTModNode; import org.apache.commons.jexl2.parser.ASTMulNode; import org.apache.commons.jexl2.parser.ASTNENode; +import org.apache.commons.jexl2.parser.ASTNRNode; import org.apache.commons.jexl2.parser.ASTNotNode; import org.apache.commons.jexl2.parser.ASTNullLiteral; import org.apache.commons.jexl2.parser.ASTOrNode; @@ -659,6 +661,17 @@ } /** {...@inheritdoc} */ + public Object visit(ASTERNode node, Object data) { + Object left = node.jjtGetChild(0).jjtAccept(this, data); + Object right = node.jjtGetChild(1).jjtAccept(this, data); + try { + return arithmetic.matches(left, right) ? Boolean.TRUE : Boolean.FALSE; + } catch (RuntimeException xrt) { + throw new JexlException(node, ">= error", xrt); + } + } + + /** {...@inheritdoc} */ public Object visit(ASTIdentifier node, Object data) { String name = node.image; if (data == null) { @@ -972,6 +985,17 @@ } /** {...@inheritdoc} */ + public Object visit(ASTNRNode node, Object data) { + Object left = node.jjtGetChild(0).jjtAccept(this, data); + Object right = node.jjtGetChild(1).jjtAccept(this, data); + try { + return arithmetic.matches(left, right) ? Boolean.FALSE : Boolean.TRUE; + } catch (RuntimeException xrt) { + throw new JexlException(node, ">= error", xrt); + } + } + + /** {...@inheritdoc} */ public Object visit(ASTNotNode node, Object data) { Object val = node.jjtGetChild(0).jjtAccept(this, data); return arithmetic.toBoolean(val) ? Boolean.FALSE : Boolean.TRUE; Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java?rev=896944&r1=896943&r2=896944&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/JexlArithmetic.java Thu Jan 7 18:00:07 2010 @@ -470,7 +470,31 @@ BigInteger result = l.subtract(r); return narrowBigInteger(left, right, result); } - + + /** + * Test if left regexp matches right. + * + * @param left first value + * @param right second value + * @return test result. + */ + public boolean matches(Object left, Object right) { + if (left == null && right == null) { + //if both are null L == R + return true; + } + if (left == null || right == null) { + // we know both aren't null, therefore L != R + return false; + } + final String arg = left.toString(); + if (right instanceof java.util.regex.Pattern) { + return ((java.util.regex.Pattern) right).matcher(arg).matches(); + } else { + return arg.matches(right.toString()); + } + } + /** * Test if left and right are equal. * Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt?rev=896944&r1=896943&r2=896944&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/parser/Parser.jjt Thu Jan 7 18:00:07 2010 @@ -295,6 +295,10 @@ ">=" AdditiveExpression() #GENode(2) | "ge" AdditiveExpression() #GENode(2) + | + "=~" AdditiveExpression() #ERNode(2) // equals regexp + | + "!~" AdditiveExpression() #NRNode(2) // not equals regexp )? } Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java?rev=896944&r1=896943&r2=896944&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/ArithmeticTest.java Thu Jan 7 18:00:07 2010 @@ -151,7 +151,26 @@ asserter.assertExpression("B10 / I2", new BigInteger("5")); asserter.assertExpression("B10 / L2", new BigInteger("5")); } - + + + public void testRegexp() throws Exception { + asserter.setVariable("str", "abc456"); + asserter.assertExpression("str =~ '.*456'", Boolean.TRUE); + asserter.assertExpression("str !~ 'ABC.*'", Boolean.TRUE); + asserter.setVariable("match", "abc.*"); + asserter.setVariable("nomatch", ".*123"); + asserter.assertExpression("str =~ match", Boolean.TRUE); + asserter.assertExpression("str !~ match", Boolean.FALSE); + asserter.assertExpression("str !~ nomatch", Boolean.TRUE); + asserter.assertExpression("str =~ nomatch", Boolean.FALSE); + asserter.setVariable("match", java.util.regex.Pattern.compile("abc.*")); + asserter.setVariable("nomatch", java.util.regex.Pattern.compile(".*123")); + asserter.assertExpression("str =~ match", Boolean.TRUE); + asserter.assertExpression("str !~ match", Boolean.FALSE); + asserter.assertExpression("str !~ nomatch", Boolean.TRUE); + asserter.assertExpression("str =~ nomatch", Boolean.FALSE); + } + /** * * if silent, all arith exception return 0.0