You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2019/03/27 17:53:28 UTC

[commons-jexl] branch master updated: JEXL-295: add unary plus support and arithmetic positivize method Task #JEXL-295 - Add unary plus operator

This is an automated email from the ASF dual-hosted git repository.

henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git


The following commit(s) were added to refs/heads/master by this push:
     new 1f00432  JEXL-295: add unary plus support and arithmetic positivize method Task #JEXL-295 - Add unary plus operator
1f00432 is described below

commit 1f00432517aa46bdf0197e1e85a007f4076c01ed
Author: henrib <he...@apache.org>
AuthorDate: Wed Mar 27 18:52:49 2019 +0100

    JEXL-295: add unary plus support and arithmetic positivize method
    Task #JEXL-295 - Add unary plus operator
---
 .../org/apache/commons/jexl3/JexlArithmetic.java   | 31 ++++++++++++++++++++++
 .../org/apache/commons/jexl3/JexlOperator.java     |  8 ++++++
 .../apache/commons/jexl3/internal/Debugger.java    |  6 +++++
 .../apache/commons/jexl3/internal/Interpreter.java | 23 +++++++++++++++-
 .../commons/jexl3/internal/ScriptVisitor.java      | 10 +++++--
 .../org/apache/commons/jexl3/parser/Parser.jjt     |  2 ++
 .../apache/commons/jexl3/parser/ParserVisitor.java |  2 ++
 .../org/apache/commons/jexl3/ArithmeticTest.java   | 28 ++++++++++++++++++-
 8 files changed, 106 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
index 2e6114e..6078bab 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
@@ -827,6 +827,37 @@ public class JexlArithmetic {
     }
 
     /**
+     * Absolute (positive) value (unary plus for numbers).
+     *
+     * @param val the value to get the absolute value from
+     * @return the positive value
+     */
+    public Object positivize(Object val) {
+        if (val instanceof Integer) {
+            return Math.abs((Integer) val);
+        } else if (val instanceof Double) {
+            return Math.abs((Double) val);
+        } else if (val instanceof Long) {
+            return Math.abs((Long) val);
+        } else if (val instanceof BigDecimal) {
+            return ((BigDecimal) val).abs();
+        } else if (val instanceof BigInteger) {
+            return ((BigInteger) val).abs();
+        } else if (val instanceof Float) {
+            return Math.abs((Float) val);
+        } else if (val instanceof Short) {
+            return (short) Math.abs((Short) val);
+        } else if (val instanceof Byte) {
+            return (byte) Math.abs((Byte) val);
+        } else if (val instanceof Boolean) {
+            return Boolean.TRUE;
+        } else if (val instanceof AtomicBoolean) {
+            return Boolean.TRUE;
+        }
+        throw new ArithmeticException("Object abs:(" + val + ")");
+    }
+    
+    /**
      * Test if left contains right (right matches/in left).
      * <p>Beware that this method arguments are the opposite of the operator arguments.
      * 'x in y' means 'y contains x'.</p>
diff --git a/src/main/java/org/apache/commons/jexl3/JexlOperator.java b/src/main/java/org/apache/commons/jexl3/JexlOperator.java
index 5bc448e..eab309e 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlOperator.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlOperator.java
@@ -191,6 +191,14 @@ public enum JexlOperator {
      * @see JexlArithmetic#negate
      */
     NEGATE("-", "negate", 1),
+    
+    /**
+     * Absolute operator.
+     * <br><strong>Syntax:</strong> <code>+x</code>
+     * <br><strong>Method:</strong> <code>T plus(L x);</code>.
+     * @see JexlArithmetic#positivize
+     */
+    POSITIVIZE("+", "positivize", 1),
 
     /**
      * Empty operator.
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
index 6ace488..546447d 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
@@ -100,6 +100,7 @@ import org.apache.commons.jexl3.parser.JexlNode;
 import org.apache.commons.jexl3.parser.ParserVisitor;
 
 import java.util.regex.Pattern;
+import org.apache.commons.jexl3.parser.ASTUnaryPlusNode;
 import org.apache.commons.jexl3.parser.StringParser;
 
 /**
@@ -993,6 +994,11 @@ public class Debugger extends ParserVisitor implements JexlInfo.Detail {
     }
 
     @Override
+    protected Object visit(ASTUnaryPlusNode node, Object data) {
+        return prefixChild(node, "+", data);
+    }
+    
+    @Override
     protected Object visit(ASTVar node, Object data) {
         builder.append("var ");
         check(node, node.getName(), data);
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index f6241b1..aaea4d9 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -113,6 +113,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
+import org.apache.commons.jexl3.parser.ASTUnaryPlusNode;
 
 
 /**
@@ -598,7 +599,27 @@ public class Interpreter extends InterpreterBase {
             throw new JexlException(valNode, "- error", xrt);
         }
     }
-
+    
+    @Override
+    protected Object visit(ASTUnaryPlusNode node, Object data) {
+        JexlNode valNode = node.jjtGetChild(0);
+        Object val = valNode.jjtAccept(this, data);
+        try {
+            Object result = operators.tryOverload(node, JexlOperator.POSITIVIZE, val);
+            if (result != JexlEngine.TRY_FAILED) {
+                return result;
+            }
+            Object number = arithmetic.positivize(val);
+            // attempt to recoerce to literal class
+            if (valNode instanceof ASTNumberLiteral && number instanceof Number) {
+                number = arithmetic.narrowNumber((Number) number, ((ASTNumberLiteral) valNode).getLiteralClass());
+            }
+            return number;
+        } catch (ArithmeticException xrt) {
+            throw new JexlException(valNode, "- error", xrt);
+        }
+    }
+    
     @Override
     protected Object visit(ASTBitwiseComplNode node, Object data) {
         Object arg = node.jjtGetChild(0).jjtAccept(this, data);
diff --git a/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java b/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
index bfa1a80..ca33ca3 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
@@ -90,6 +90,7 @@ import org.apache.commons.jexl3.parser.ASTSubNode;
 import org.apache.commons.jexl3.parser.ASTTernaryNode;
 import org.apache.commons.jexl3.parser.ASTTrueNode;
 import org.apache.commons.jexl3.parser.ASTUnaryMinusNode;
+import org.apache.commons.jexl3.parser.ASTUnaryPlusNode;
 import org.apache.commons.jexl3.parser.ASTVar;
 import org.apache.commons.jexl3.parser.ASTWhileStatement;
 import org.apache.commons.jexl3.parser.JexlNode;
@@ -288,8 +289,8 @@ public class ScriptVisitor extends ParserVisitor {
 
     @Override
     protected Object visit(ASTNEWNode node, Object data) {
-
-        return visitNode(node, data);    }
+        return visitNode(node, data);
+    }
 
     @Override
     protected Object visit(ASTAddNode node, Object data) {
@@ -322,6 +323,11 @@ public class ScriptVisitor extends ParserVisitor {
     }
 
     @Override
+    protected Object visit(ASTUnaryPlusNode node, Object data) {
+        return visitNode(node, data);
+    }
+    
+    @Override
     protected Object visit(ASTBitwiseComplNode node, Object data) {
         return visitNode(node, data);
     }
diff --git a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
index 3565ba0..0451b72 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -580,6 +580,8 @@ void UnaryExpression() #void : {}
 {
     <minus> UnaryExpression() #UnaryMinusNode(1)
   |
+    <plus> UnaryExpression() #UnaryPlusNode(1)
+  |
     <tilda> UnaryExpression() #BitwiseComplNode(1)
   |
     <not> UnaryExpression() #NotNode(1)
diff --git a/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java b/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
index c584459..a3d0d59 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
@@ -113,6 +113,8 @@ public abstract class ParserVisitor {
     protected abstract Object visit(ASTModNode node, Object data);
 
     protected abstract Object visit(ASTUnaryMinusNode node, Object data);
+    
+    protected abstract Object visit(ASTUnaryPlusNode node, Object data);
 
     protected abstract Object visit(ASTBitwiseComplNode node, Object data);
 
diff --git a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
index f521088..3a50d66 100644
--- a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
+++ b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
@@ -153,7 +153,33 @@ public class ArithmeticTest extends JexlTestCase {
         asserter.assertExpression("-aBigInteger", new BigInteger("-7"));
         asserter.assertExpression("-aBigDecimal", new BigDecimal("-8.8"));
     }
-
+    
+    /**
+     * test some simple mathematical calculations
+     */
+    @Test
+    public void testUnaryPlusus() throws Exception {
+        asserter.setVariable("aByte", new Byte((byte) -1));
+        asserter.setVariable("aShort", new Short((short) -2));
+        asserter.setVariable("anInteger", new Integer(-3));
+        asserter.setVariable("aLong", new Long(-4));
+        asserter.setVariable("aFloat", new Float(-5.5));
+        asserter.setVariable("aDouble", new Double(-6.6));
+        asserter.setVariable("aBigInteger", new BigInteger("-7"));
+        asserter.setVariable("aBigDecimal", new BigDecimal("-8.8"));
+
+        asserter.assertExpression("+3", new Integer("3"));
+        asserter.assertExpression("+3.0", new Double("3.0"));
+        asserter.assertExpression("+aByte", new Byte((byte) 1));
+        asserter.assertExpression("+aShort", new Short((short) 2));
+        asserter.assertExpression("+anInteger", new Integer(3));
+        asserter.assertExpression("+aLong", new Long(4));
+        asserter.assertExpression("+aFloat", new Float(5.5));
+        asserter.assertExpression("+aDouble", new Double(6.6));
+        asserter.assertExpression("+aBigInteger", new BigInteger("7"));
+        asserter.assertExpression("+aBigDecimal", new BigDecimal("8.8"));
+    }
+    
     /**
      * test some simple mathematical calculations
      */