Author: cbrisson
Date: Sat Oct  8 15:59:05 2016
New Revision: 1763913

URL: http://svn.apache.org/viewvc?rev=1763913&view=rev
Log:
1) added missing unary negate math operator

2) bugfix and AST nodes hierarchy cleaning:
   ASTBinaryOperator <--- ASTMathOperator <--- ASTAddNode, ASTSubstractNode, ...
                     <--- ASTComparisonOperator <--- ASTLTNode, ASTLENode, ...
                     <--- ASTLogicalOperator <--- ASTAndNode, ASTOrNode

The ASTBinaryOperator defines the new abstract method getLiteralOperator(), 
which returns the string representing the operator. It is used when calculating 
the error message which is displayed whenever something goes wrong (since at 
runtime tokens are freed to reduce memory usage, arithmetic errors where 
sometimes throwing NPEs before this reeng)

3) test cases for 1) and 2)



Added:
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTBinaryOperator.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLogicalOperator.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java
Modified:
    velocity/engine/trunk/src/changes/changes.xml
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAddNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAndNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTEQNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTExpression.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGENode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGTNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLENode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLTNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMulNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNotNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTOrNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSubtractNode.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/MathUtils.java
    
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java
    velocity/engine/trunk/velocity-engine-core/src/main/parser/Parser.jjt
    
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/ArithmeticTestCase.java
    
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/SetTestCase.java

Modified: velocity/engine/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/changes/changes.xml?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- velocity/engine/trunk/src/changes/changes.xml (original)
+++ velocity/engine/trunk/src/changes/changes.xml Sat Oct  8 15:59:05 2016
@@ -28,6 +28,10 @@
     <release version="2.0" date="In Subversion">
 
       <action type="add" dev="cbrisson">
+       Added unary negate math operator
+      </action>
+      
+      <action type="add" dev="cbrisson">
         Add a configurable space gobbling feature, to control indentation in 
the generated code.
         <br/>
         Possible values for the 'space.gobbling' configuration key:

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAddNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAddNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAddNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAddNode.java
 Sat Oct  8 15:59:05 2016
@@ -75,6 +75,12 @@ public class ASTAddNode extends ASTMathN
         return null;
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return "+";
+    }
+
     public Number perform(Number left, Number right, InternalContextAdapter 
context)
     {
         return MathUtils.add(left, right);

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAndNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAndNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAndNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTAndNode.java
 Sat Oct  8 15:59:05 2016
@@ -21,7 +21,6 @@ package org.apache.velocity.runtime.pars
 
 import org.apache.velocity.context.InternalContextAdapter;
 import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.TemplateInitException;
 import org.apache.velocity.runtime.parser.Parser;
 
 /**
@@ -32,7 +31,7 @@ import org.apache.velocity.runtime.parse
  * @author <a href="mailto:ge...@optonline.net";>Geir Magnusson Jr.</a>
  * @version $Id$
  */
-public class ASTAndNode extends SimpleNode
+public class ASTAndNode extends ASTLogicalOperator
 {
     /**
      * @param id
@@ -51,6 +50,12 @@ public class ASTAndNode extends SimpleNo
         super(p, id);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return "&&";
+    }
+
     /**
      * @see 
org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor,
 java.lang.Object)
      */
@@ -110,17 +115,5 @@ public class ASTAndNode extends SimpleNo
 
         return false;
     }
-    
-    /**
-     * @throws TemplateInitException
-     * @see 
org.apache.velocity.runtime.parser.node.Node#init(org.apache.velocity.context.InternalContextAdapter,
 java.lang.Object)
-     */
-    public Object init( InternalContextAdapter context, Object data) throws 
TemplateInitException
-    {
-       Object obj = super.init(context, data);
-       cleanupParserAndTokens(); // drop reference to Parser and all JavaCC 
Tokens
-       return obj;
-    }
-
 }
 

Added: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTBinaryOperator.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTBinaryOperator.java?rev=1763913&view=auto
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTBinaryOperator.java
 (added)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTBinaryOperator.java
 Sat Oct  8 15:59:05 2016
@@ -0,0 +1,46 @@
+package org.apache.velocity.runtime.parser.node;
+
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.exception.TemplateInitException;
+import org.apache.velocity.runtime.parser.Parser;
+
+public abstract class ASTBinaryOperator extends SimpleNode
+{
+    public ASTBinaryOperator(int id)
+    {
+        super(id);
+    }
+
+    public ASTBinaryOperator(Parser p, int id)
+    {
+        super(p, id);
+    }
+
+    /**
+     * @throws TemplateInitException
+     * @see 
org.apache.velocity.runtime.parser.node.Node#init(org.apache.velocity.context.InternalContextAdapter,
 java.lang.Object)
+     */
+    public Object init( InternalContextAdapter context, Object data) throws 
TemplateInitException
+    {
+        Object obj = super.init(context, data);
+        cleanupParserAndTokens(); // drop reference to Parser and all JavaCC 
Tokens
+        return obj;
+    }
+
+    /**
+     * get the string representing the mathematical operator
+     * @return operator string
+     */
+    public abstract String getLiteralOperator();
+
+    @Override
+    public String literal()
+    {
+        StringBuilder builder = new StringBuilder();
+        builder.append(jjtGetChild(0).literal());
+        builder.append(' ');
+        builder.append(getLiteralOperator());
+        builder.append(' ');
+        return builder.toString();
+    }
+}

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTComparisonNode.java
 Sat Oct  8 15:59:05 2016
@@ -21,7 +21,6 @@ package org.apache.velocity.runtime.pars
 
 import org.apache.velocity.context.InternalContextAdapter;
 import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.TemplateInitException;
 import org.apache.velocity.exception.VelocityException;
 import org.apache.velocity.runtime.RuntimeConstants;
 import org.apache.velocity.runtime.parser.Parser;
@@ -35,7 +34,7 @@ import org.apache.velocity.util.StringUt
  * @author <a href="mailto:p...@antaramusic.de";>Peter Romianowski</a>
  * @author Nathan Bubna
  */
-public abstract class ASTComparisonNode extends SimpleNode
+public abstract class ASTComparisonNode extends ASTBinaryOperator
 {
     /**
      * @param id
@@ -123,6 +122,17 @@ public abstract class ASTComparisonNode
         return null;
     }
 
+    /**
+     * get the string representing the mathematical operator
+     * @return operator string
+     */
+    public abstract String getLiteralOperator();
+
+    /**
+     * performs the actual comparison
+     * @param compareResult
+     * @return comparison result
+     */
     public abstract boolean numberTest(int compareResult);
 
     public boolean compareNonNumber(Object left, Object right)
@@ -151,17 +161,4 @@ public abstract class ASTComparisonNode
     {
         return Boolean.valueOf(evaluate(context));
     }
-    
-    /**
-     * @throws TemplateInitException
-     * @see 
org.apache.velocity.runtime.parser.node.Node#init(org.apache.velocity.context.InternalContextAdapter,
 java.lang.Object)
-     */
-    public Object init( InternalContextAdapter context, Object data) throws 
TemplateInitException
-    {
-       Object obj = super.init(context, data);
-       cleanupParserAndTokens(); // drop reference to Parser and all JavaCC 
Tokens
-       return obj;
-    }
-    
-
 }

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTDivNode.java
 Sat Oct  8 15:59:05 2016
@@ -54,6 +54,12 @@ public class ASTDivNode extends ASTMathN
         super(p, id);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return "/";
+    }
+
     public Number perform(Number left, Number right, InternalContextAdapter 
context)
     {
         /*

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTEQNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTEQNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTEQNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTEQNode.java
 Sat Oct  8 15:59:05 2016
@@ -51,6 +51,12 @@ public class ASTEQNode extends ASTCompar
         return left == right || DuckType.asNull(left == null ? right : left);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return "==";
+    }
+
     public boolean numberTest(int compareResult)
     {
         return compareResult == 0;

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTExpression.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTExpression.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTExpression.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTExpression.java
 Sat Oct  8 15:59:05 2016
@@ -83,4 +83,10 @@ public class ASTExpression extends Simpl
        cleanupParserAndTokens(); // drop reference to Parser and all JavaCC 
Tokens
        return obj;
     }
+
+    @Override
+    public String literal()
+    {
+        return jjtGetChild(0).literal();
+    }
 }

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGENode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGENode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGENode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGENode.java
 Sat Oct  8 15:59:05 2016
@@ -36,6 +36,12 @@ public class ASTGENode extends ASTCompar
         super(p, id);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return ">=";
+    }
+
     public boolean numberTest(int compareResult)
     {
         return compareResult >= 0;

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGTNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGTNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGTNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTGTNode.java
 Sat Oct  8 15:59:05 2016
@@ -36,6 +36,12 @@ public class ASTGTNode extends ASTCompar
         super(p, id);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return ">";
+    }
+
     public boolean numberTest(int compareResult)
     {
         return compareResult == 1;

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLENode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLENode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLENode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLENode.java
 Sat Oct  8 15:59:05 2016
@@ -36,6 +36,12 @@ public class ASTLENode extends ASTCompar
         super(p, id);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return "<=";
+    }
+
     public boolean numberTest(int compareResult)
     {
         return compareResult <= 0;

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLTNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLTNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLTNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLTNode.java
 Sat Oct  8 15:59:05 2016
@@ -36,6 +36,12 @@ public class ASTLTNode extends ASTCompar
         super(p, id);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return "<";
+    }
+
     public boolean numberTest(int compareResult)
     {
         return compareResult == -1;

Added: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLogicalOperator.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLogicalOperator.java?rev=1763913&view=auto
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLogicalOperator.java
 (added)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTLogicalOperator.java
 Sat Oct  8 15:59:05 2016
@@ -0,0 +1,29 @@
+package org.apache.velocity.runtime.parser.node;
+
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.exception.TemplateInitException;
+import org.apache.velocity.runtime.parser.Parser;
+
+public abstract class ASTLogicalOperator extends ASTBinaryOperator
+{
+    public ASTLogicalOperator(int id)
+    {
+        super(id);
+    }
+
+    public ASTLogicalOperator(Parser p, int id)
+    {
+        super(p, id);
+    }
+
+    /**
+     * @throws TemplateInitException
+     * @see 
org.apache.velocity.runtime.parser.node.Node#init(org.apache.velocity.context.InternalContextAdapter,
 java.lang.Object)
+     */
+    public Object init( InternalContextAdapter context, Object data) throws 
TemplateInitException
+    {
+        Object obj = super.init(context, data);
+        cleanupParserAndTokens(); // drop reference to Parser and all JavaCC 
Tokens
+        return obj;
+    }
+}

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMathNode.java
 Sat Oct  8 15:59:05 2016
@@ -40,7 +40,7 @@ import org.apache.velocity.util.DuckType
  * @author Nathan Bubna
  * @version $Id: ASTMathNode.java 517553 2007-03-13 06:09:58Z wglass $
  */
-public abstract class ASTMathNode extends SimpleNode
+public abstract class ASTMathNode extends ASTBinaryOperator
 {
     protected boolean strictMode = false;
 

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTModNode.java
 Sat Oct  8 15:59:05 2016
@@ -88,5 +88,11 @@ public class ASTModNode extends ASTMathN
        return obj;
     }
     
+    @Override
+    public String getLiteralOperator()
+    {
+        return "%";
+    }
+
 }
 

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMulNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMulNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMulNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMulNode.java
 Sat Oct  8 15:59:05 2016
@@ -70,6 +70,12 @@ public class ASTMulNode extends ASTMathN
        return obj;
     }
     
+    @Override
+    public String getLiteralOperator()
+    {
+        return "*";
+    }
+
 }
 
 

Added: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java?rev=1763913&view=auto
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java
 (added)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNegateNode.java
 Sat Oct  8 15:59:05 2016
@@ -0,0 +1,90 @@
+package org.apache.velocity.runtime.parser.node;
+
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.exception.MathException;
+import org.apache.velocity.exception.MethodInvocationException;
+import org.apache.velocity.exception.TemplateInitException;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.parser.Parser;
+import org.apache.velocity.util.DuckType;
+
+public class ASTNegateNode extends SimpleNode
+{
+    protected boolean strictMode = false;
+
+    public ASTNegateNode(int i)
+    {
+        super(i);
+    }
+
+    public ASTNegateNode(Parser p, int i)
+    {
+        super(p, i);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object init(InternalContextAdapter context, Object data) throws 
TemplateInitException
+    {
+        super.init(context, data);
+        /* save a literal image now (needed in case of error) */
+        strictMode = rsvc.getBoolean(RuntimeConstants.STRICT_MATH, false);
+        cleanupParserAndTokens();
+        return data;
+    }
+
+    /**
+     * @see 
org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor,
 java.lang.Object)
+     */
+    public Object jjtAccept(ParserVisitor visitor, Object data)
+    {
+        return visitor.visit(this, data);
+    }
+
+    /**
+     * @see 
org.apache.velocity.runtime.parser.node.SimpleNode#evaluate(org.apache.velocity.context.InternalContextAdapter)
+     */
+    public boolean evaluate( InternalContextAdapter context)
+            throws MethodInvocationException
+    {
+        return jjtGetChild(0).evaluate(context);
+    }
+
+    /**
+     * @see 
org.apache.velocity.runtime.parser.node.SimpleNode#value(org.apache.velocity.context.InternalContextAdapter)
+     */
+    public Object value( InternalContextAdapter context)
+            throws MethodInvocationException
+    {
+        Object value = jjtGetChild(0).evaluate( context );
+        try
+        {
+            value = DuckType.asNumber(value);
+        }
+        catch (NumberFormatException nfe) {}
+        if (!(value instanceof Number))
+        {
+            String msg = "Argument of unary negate (" +
+                    jjtGetChild(0).literal() +
+                    ") " +
+                    (value == null ? "has a null value." : "is not a Number.");
+            if (strictMode)
+            {
+                log.error(msg);
+                throw new MathException(msg);
+            }
+            else
+            {
+                log.debug(msg);
+                return null;
+            }
+        }
+        return MathUtils.negate((Number) value);
+    }
+    @Override
+    public String literal()
+    {
+        return "-" + jjtGetChild(0).literal();
+    }
+}

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNotNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNotNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNotNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTNotNode.java
 Sat Oct  8 15:59:05 2016
@@ -86,4 +86,10 @@ public class ASTNotNode extends SimpleNo
        cleanupParserAndTokens(); // drop reference to Parser and all JavaCC 
Tokens
        return obj;
     }
+
+    @Override
+    public String literal()
+    {
+        return "!" + jjtGetChild(0).literal();
+    }
 }

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTOrNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTOrNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTOrNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTOrNode.java
 Sat Oct  8 15:59:05 2016
@@ -21,7 +21,6 @@ package org.apache.velocity.runtime.pars
 
 import org.apache.velocity.context.InternalContextAdapter;
 import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.TemplateInitException;
 import org.apache.velocity.runtime.parser.Parser;
 
 /**
@@ -32,7 +31,7 @@ import org.apache.velocity.runtime.parse
  * @author <a href="mailto:ge...@optonline.net";>Geir Magnusson Jr.</a>
  * @version $Id$
 */
-public class ASTOrNode extends SimpleNode
+public class ASTOrNode extends ASTLogicalOperator
 {
     /**
      * @param id
@@ -51,6 +50,12 @@ public class ASTOrNode extends SimpleNod
         super(p, id);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return "||";
+    }
+
     /**
      * @see 
org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor,
 java.lang.Object)
      */
@@ -106,18 +111,6 @@ public class ASTOrNode extends SimpleNod
 
         return false;
     }
-    
-    /**
-     * @throws TemplateInitException
-     * @see 
org.apache.velocity.runtime.parser.node.Node#init(org.apache.velocity.context.InternalContextAdapter,
 java.lang.Object)
-     */
-    public Object init( InternalContextAdapter context, Object data) throws 
TemplateInitException
-    {
-       Object obj = super.init(context, data);
-       cleanupParserAndTokens(); // drop reference to Parser and all JavaCC 
Tokens
-       return obj;
-    }
-
 }
 
 

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSubtractNode.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSubtractNode.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSubtractNode.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTSubtractNode.java
 Sat Oct  8 15:59:05 2016
@@ -53,6 +53,12 @@ public class ASTSubtractNode extends AST
         super(p, id);
     }
 
+    @Override
+    public String getLiteralOperator()
+    {
+        return "-";
+    }
+
     public Number perform(Number left, Number right, InternalContextAdapter 
context)
     {
         return MathUtils.subtract(left, right);

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/MathUtils.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/MathUtils.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/MathUtils.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/MathUtils.java
 Sat Oct  8 15:59:05 2016
@@ -213,7 +213,7 @@ public abstract class MathUtils
         {
             return Long.valueOf(value);
         }
-        return BigInteger.valueOf( value);
+        return BigInteger.valueOf(value);
     }
 
     /**
@@ -228,9 +228,9 @@ public abstract class MathUtils
     {
         if ( typesBySize.indexOf( op1.getClass()) > typesBySize.indexOf( 
op2.getClass()))
         {
-            return wrapPrimitive( value, op1.getClass());
+            return wrapPrimitive(value, op1.getClass());
         }
-        return wrapPrimitive( value, op2.getClass());
+        return wrapPrimitive(value, op2.getClass());
     }
 
     /**
@@ -268,6 +268,31 @@ public abstract class MathUtils
     }
 
     /**
+     * Find the Number-type to be used for a single number
+     *
+     * @param op operand
+     * @return constant indicating type of Number to use in calculations
+     */
+    public static int findCalculationBase(Number op)
+    {
+        if (isInteger(op))
+        {
+            if (op instanceof BigInteger)
+            {
+                return BASE_BIGINTEGER;
+            }
+            return BASE_LONG;
+        } else if (op instanceof BigDecimal)
+        {
+            return BASE_BIGDECIMAL;
+        } else if (op instanceof Double)
+        {
+            return BASE_DOUBLE;
+        }
+        return BASE_FLOAT;
+    }
+
+    /**
      * Add two numbers and return the correct value / type.
      * Overflow detection is done for integer values (byte, short, int, long) 
only!
      * @param op1
@@ -480,4 +505,35 @@ public abstract class MathUtils
                 return toBigDecimal( op1 ).compareTo( toBigDecimal ( op2 ));
         }
     }
+
+    /**
+     * Negate a number
+     * @param op n
+     * @return -n (unary negation of n)
+     */
+    public static Number negate(Number op)
+    {
+        int calcBase = findCalculationBase( op);
+        switch (calcBase) {
+            case BASE_BIGINTEGER:
+                return toBigInteger(op).negate();
+            case BASE_LONG:
+                long l = op.longValue();
+                /* overflow check */
+                if (l == Long.MIN_VALUE)
+                {
+                    return toBigInteger(l).negate();
+                }
+                return wrapPrimitive(-l, op.getClass());
+            case BASE_FLOAT:
+                float f = op.floatValue();
+                return -f;
+            case BASE_DOUBLE:
+                double d = op.doubleValue();
+                return -d;
+            // Default is BigDecimal operation
+            default:
+                return toBigDecimal(op).negate();
+        }
+    }
 }

Modified: 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/MethodMap.java
 Sat Oct  8 15:59:05 2016
@@ -19,8 +19,6 @@ package org.apache.velocity.util.introsp
  * under the License.    
  */
 
-import org.apache.commons.lang3.Conversion;
-
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Iterator;

Modified: velocity/engine/trunk/velocity-engine-core/src/main/parser/Parser.jjt
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/parser/Parser.jjt?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/parser/Parser.jjt 
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/parser/Parser.jjt Sat 
Oct  8 15:59:05 2016
@@ -2129,6 +2129,7 @@ void UnaryExpression() #void : {}
     ( <WHITESPACE> | <NEWLINE> )*
     (
           <LOGICAL_NOT>  UnaryExpression() #NotNode(1)
+     |   <MINUS> PrimaryExpression() #NegateNode(1)
       |   PrimaryExpression()
     )
 }

Modified: 
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/ArithmeticTestCase.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/ArithmeticTestCase.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/ArithmeticTestCase.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/ArithmeticTestCase.java
 Sat Oct  8 15:59:05 2016
@@ -64,8 +64,8 @@ public class ArithmeticTestCase extends
     private void addHelper (Number n1, Number n2, double expectedResult, Class 
expectedResultType)
     {
         Number result = MathUtils.add( n1, n2);
-        assertEquals ("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
-        assertEquals ("ResultType does not match.", expectedResultType, 
result.getClass());
+        assertEquals("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
+        assertEquals("ResultType does not match.", expectedResultType, 
result.getClass());
     }
 
     public void testSubtract()
@@ -79,15 +79,15 @@ public class ArithmeticTestCase extends
 
         // Test overflow
         subtractHelper (new Integer(Integer.MIN_VALUE), new Short( (short)20), 
(double)Integer.MIN_VALUE-20, Long.class);
-        subtractHelper (new Integer (-20), new Long(Long.MAX_VALUE), 
-20d-(double)Long.MAX_VALUE, BigInteger.class);
-        subtractHelper (new Integer (Integer.MAX_VALUE), new 
Long(Long.MIN_VALUE), (double)Long.MAX_VALUE+(double)Integer.MAX_VALUE, 
BigInteger.class);
+        subtractHelper(new Integer(-20), new Long(Long.MAX_VALUE), -20d - 
(double) Long.MAX_VALUE, BigInteger.class);
+        subtractHelper(new Integer(Integer.MAX_VALUE), new 
Long(Long.MIN_VALUE), (double) Long.MAX_VALUE + (double) Integer.MAX_VALUE, 
BigInteger.class);
     }
 
     private void subtractHelper (Number n1, Number n2, double expectedResult, 
Class expectedResultType)
     {
         Number result = MathUtils.subtract( n1, n2);
-        assertEquals ("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
-        assertEquals ("ResultType does not match.", expectedResultType, 
result.getClass());
+        assertEquals("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
+        assertEquals("ResultType does not match.", expectedResultType, 
result.getClass());
     }
 
     public void testMultiply()
@@ -102,15 +102,15 @@ public class ArithmeticTestCase extends
 
         // Test overflow
         multiplyHelper (new Integer(Integer.MAX_VALUE), new Short( (short)10), 
(double)Integer.MAX_VALUE*10d, Long.class);
-        multiplyHelper (new Integer(Integer.MAX_VALUE), new Short( 
(short)-10), (double)Integer.MAX_VALUE*-10d, Long.class);
-        multiplyHelper (new Integer (20), new Long(Long.MAX_VALUE), 
20d*(double)Long.MAX_VALUE, BigInteger.class);
+        multiplyHelper(new Integer(Integer.MAX_VALUE), new Short((short) -10), 
(double) Integer.MAX_VALUE * -10d, Long.class);
+        multiplyHelper(new Integer(20), new Long(Long.MAX_VALUE), 20d * 
(double) Long.MAX_VALUE, BigInteger.class);
     }
 
     private void multiplyHelper (Number n1, Number n2, double expectedResult, 
Class expectedResultType)
     {
         Number result = MathUtils.multiply( n1, n2);
-        assertEquals ("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
-        assertEquals ("ResultType does not match.", expectedResultType, 
result.getClass());
+        assertEquals("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
+        assertEquals("ResultType does not match.", expectedResultType, 
result.getClass());
     }
 
     public void testDivide()
@@ -120,23 +120,23 @@ public class ArithmeticTestCase extends
         divideHelper (BigInteger.valueOf(10), new Short( (short)2), 5, 
BigInteger.class);
         divideHelper (new Integer(10), new Short( (short)4), 2, Integer.class);
         divideHelper (new Integer(10), new Float( 2.5f), 4, Float.class);
-        divideHelper (new Integer(10), new Double( 2.5), 4, Double.class);
-        divideHelper (new Integer(10), new BigDecimal( 2.5), 4, 
BigDecimal.class);
+        divideHelper(new Integer(10), new Double(2.5), 4, Double.class);
+        divideHelper(new Integer(10), new BigDecimal(2.5), 4, 
BigDecimal.class);
     }
 
     private void divideHelper (Number n1, Number n2, double expectedResult, 
Class expectedResultType)
     {
         Number result = MathUtils.divide( n1, n2);
-        assertEquals ("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
-        assertEquals ("ResultType does not match.", expectedResultType, 
result.getClass());
+        assertEquals("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
+        assertEquals("ResultType does not match.", expectedResultType, 
result.getClass());
     }
 
     public void testModulo()
     {
         moduloHelper (new Integer(10), new Short( (short)2), 0, Integer.class);
         moduloHelper (new Byte((byte)10), new Short( (short)3), 1, 
Short.class);
-        moduloHelper (BigInteger.valueOf(10), new Short( (short)4), 2, 
BigInteger.class);
-        moduloHelper (new Integer(10), new Float( 5.5f), 4.5, Float.class);
+        moduloHelper(BigInteger.valueOf(10), new Short((short) 4), 2, 
BigInteger.class);
+        moduloHelper(new Integer(10), new Float(5.5f), 4.5, Float.class);
 
         try
         {
@@ -152,8 +152,8 @@ public class ArithmeticTestCase extends
     private void moduloHelper (Number n1, Number n2, double expectedResult, 
Class expectedResultType)
     {
         Number result = MathUtils.modulo( n1, n2);
-        assertEquals ("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
-        assertEquals ("ResultType does not match.", expectedResultType, 
result.getClass());
+        assertEquals("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
+        assertEquals("ResultType does not match.", expectedResultType, 
result.getClass());
     }
 
     public void testCompare()
@@ -162,14 +162,32 @@ public class ArithmeticTestCase extends
         compareHelper (new Integer(10), new Short( (short)11), -1);
         compareHelper (BigInteger.valueOf(10), new Short( (short)11), -1);
         compareHelper (new Byte((byte)10), new Short( (short)3), 1);
-        compareHelper (new Float(10), new Short( (short)11), -1);
-        compareHelper (new Double(10), new Short( (short)11), -1);
+        compareHelper(new Float(10), new Short((short) 11), -1);
+        compareHelper(new Double(10), new Short((short) 11), -1);
     }
 
     private void compareHelper (Number n1, Number n2, int expectedResult)
     {
         int result = MathUtils.compare( n1, n2 );
-        assertEquals ("The arithmetic operation produced an unexpected 
result.", expectedResult, result);
+        assertEquals("The arithmetic operation produced an unexpected 
result.", expectedResult, result);
+    }
+
+    public void testNegate()
+    {
+        negateHelper(new Byte((byte) 1), -1, Byte.class);
+        negateHelper(new Short((short) 1), -1, Short.class);
+        negateHelper(new Integer(1), -1, Integer.class);
+        negateHelper(new Long(1), -1, Long.class);
+        negateHelper(BigInteger.valueOf(1), -1, BigInteger.class);
+        negateHelper(BigDecimal.valueOf(1), -1, BigDecimal.class);
+        negateHelper(new Long(Long.MIN_VALUE), 
BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.valueOf(1)).doubleValue(), 
BigInteger.class);
+    }
+
+    private void negateHelper(Number n, double expectedResult, Class 
expectedResultType)
+    {
+        Number result = MathUtils.negate(n);
+        assertEquals ("The arithmetic operation produced an unexpected 
result.", expectedResult, result.doubleValue(), 0.01);
+        assertEquals ("ResultType does not match.", expectedResultType, 
result.getClass());
     }
 
 /*

Modified: 
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/SetTestCase.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/SetTestCase.java?rev=1763913&r1=1763912&r2=1763913&view=diff
==============================================================================
--- 
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/SetTestCase.java
 (original)
+++ 
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/SetTestCase.java
 Sat Oct  8 15:59:05 2016
@@ -121,5 +121,24 @@ public class SetTestCase extends BaseTes
         }
     }
 
+    public void testInvalidSet() throws Exception
+    {
+        /* the purpose of this test is to check that in case of error, the 
calculation of the
+         literal representation of the expression, which is displayed in the 
logs, does not raise a null exception
+          */
+        assertEvalEquals("", "#set($c = $a - $b - $c)");
+        assertEvalEquals("", "#set($c = $a + $b + $c)");
+        assertEvalEquals("", "#set($c = $a * $b * $c)");
+        assertEvalEquals("", "#set($c = $a / $b / $c)");
+        assertEvalEquals("", "#set($c = $a % $b % $c)");
+        assertEvalEquals("", "#set($c = $a && $b && $c)");
+        assertEvalEquals("", "#set($c = $a || $b || $c)");
+        assertEvalEquals("", "#set($c = $a + $b + !$c)");
+        assertEvalEquals("", "#set($c = $a + $b + (-$c))");
+        assertEvalEquals("", "#set($c = $a && ($b < $c))");
+        assertEvalEquals("", "#set($c = !$a)");
+        assertEvalEquals("", "#set($c = ($a < $b) - ($c < $d))");
+        assertEvalEquals("","#set($b = !$a)");
+    }
 }
 



Reply via email to