Author: byron
Date: Fri Jan  2 08:02:30 2009
New Revision: 730763

URL: http://svn.apache.org/viewvc?rev=730763&view=rev
Log:
VELOCITY-406 for setting $foo[$i] =, changed so Velocity first tries 'set' 
method then 'put' instead of always calling 'set' if  is an Integer, and 
failing if not.

Modified:
    
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTReference.java
    
velocity/engine/trunk/src/test/org/apache/velocity/test/BaseEvalTestCase.java
    velocity/engine/trunk/src/test/org/apache/velocity/test/IndexTestCase.java
    velocity/engine/trunk/xdocs/docs/user-guide.xml

Modified: 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTReference.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTReference.java?rev=730763&r1=730762&r2=730763&view=diff
==============================================================================
--- 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTReference.java
 (original)
+++ 
velocity/engine/trunk/src/java/org/apache/velocity/runtime/parser/node/ASTReference.java
 Fri Jan  2 08:02:30 2009
@@ -499,6 +499,16 @@
         return (computableReference ? execute(null, context) : null);
     }
 
+    
+    /**
+     * Utility class to handle nulls when printing a class type
+     */
+    public static String printClass(Class clazz)
+    {
+      return clazz == null ? "null" : clazz.getName();
+    }
+    
+    
     /**
      *  Sets the value of a complex reference (something like $foo.bar)
      *  Currently used by ASTSetReference()
@@ -569,25 +579,43 @@
             // of the form set(Integer, <something>), or put(Object, 
<something), where
             // the first parameter is the index value and the second is the 
LHS of the set.
           
-            String methodName = "put";
             Object argument = astIndex.jjtGetChild(0).value(context);
             // If negative, turn -1 into (size - 1)
             argument = ASTIndex.adjMinusIndexArg(argument, result, context, 
astIndex);            
             Object [] params = {argument, value};
             Class[] paramClasses = {params[0] == null ? null : 
params[0].getClass(), 
                                     params[1] == null ? null : 
params[1].getClass()};
-            if (params[0] instanceof Integer)
+
+            String methodName = "set";
+            VelMethod method = ClassUtils.getMethod(methodName, params, 
paramClasses, 
+                result, context, astIndex, false);
+            
+            if (method == null)
+            {
+                // If we can't find a 'set' method, lets try 'put',  This 
warrents a little
+                // investigation performance wise... if the user is using the 
hash 
+                // form $foo["blaa"], then it may be expensive to first try 
and fail on 'set'
+                // then go to 'put'?  The problem is that getMethod will try 
the cache, then
+                // perform introspection on 'result' for 'set'
+                methodName = "put";
+                method = ClassUtils.getMethod(methodName, params, 
paramClasses, 
+                      result, context, astIndex, false);
+            }   
+            
+            if (method == null)
             {
-                // If the index parameter is of type Integer, then it is more 
approiate
-                // to call set(Integer, <whatever>) since the user is 
probabbly attempting
-                // to set an array.
-                methodName = "set";
+                // couldn't find set or put method, so bail
+                if (strictRef)
+                {
+                    throw new VelocityException(
+                        "Found neither a 'set' or 'put' method with param 
types '("
+                        + printClass(paramClasses[0]) + "," + 
printClass(paramClasses[1])
+                        + ")' on class '" + result.getClass().getName() 
+                        + "' at " + Log.formatFileString(astIndex));
+                }
+                return false;
             }
-                   
-            VelMethod method = ClassUtils.getMethod(methodName, params, 
paramClasses, 
-                result, context, astIndex, strictRef);
           
-            if (method == null) return false;
             try
             { 
                 method.invoke(result, params);
@@ -599,18 +627,11 @@
             }
             catch(Exception e)
             {
-                // Create a parameter list for the exception error message
-                StringBuffer plist = new StringBuffer();
-                for (int i = 0; i < params.length; i++)
-                {
-                    Class param = paramClasses[i];
-                    plist.append(param == null ? "null" : param.getName());
-                    if (i < params.length - 1)
-                        plist.append(", ");
-                }
                 throw new MethodInvocationException(
-                  "Exception calling of method '"
-                  + methodName + "(" + plist + ")' in  " + result.getClass(),
+                  "Exception calling method '"
+                  + methodName + "(" 
+                  + printClass(paramClasses[0]) + "," + 
printClass(paramClasses[1])
+                  + ")' in  " + result.getClass(),
                   e.getCause(), identifier, astIndex.getTemplateName(), 
astIndex.getLine(), 
                     astIndex.getColumn());
             }

Modified: 
velocity/engine/trunk/src/test/org/apache/velocity/test/BaseEvalTestCase.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/test/org/apache/velocity/test/BaseEvalTestCase.java?rev=730763&r1=730762&r2=730763&view=diff
==============================================================================
--- 
velocity/engine/trunk/src/test/org/apache/velocity/test/BaseEvalTestCase.java 
(original)
+++ 
velocity/engine/trunk/src/test/org/apache/velocity/test/BaseEvalTestCase.java 
Fri Jan  2 08:02:30 2009
@@ -37,7 +37,7 @@
 {
     protected VelocityEngine engine;
     protected VelocityContext context;
-    protected boolean DEBUG = false;
+    protected boolean DEBUG = true;
     protected TestLogChute log;
 
     public BaseEvalTestCase(String name)

Modified: 
velocity/engine/trunk/src/test/org/apache/velocity/test/IndexTestCase.java
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/src/test/org/apache/velocity/test/IndexTestCase.java?rev=730763&r1=730762&r2=730763&view=diff
==============================================================================
--- velocity/engine/trunk/src/test/org/apache/velocity/test/IndexTestCase.java 
(original)
+++ velocity/engine/trunk/src/test/org/apache/velocity/test/IndexTestCase.java 
Fri Jan  2 08:02:30 2009
@@ -88,7 +88,8 @@
         assertEvalEquals("junk foobar ", "$foo[\"junk\"]");
         assertEvalEquals("GOT NULL", "#set($i=$NULL)$boo[$i]");
         
-        assertEvalEquals("3", "$a[-1]");
+        assertEvalEquals("321", "$a[-1]$a[ -2]$a[-3 ]");
+        assertEvalEquals("67xx", "#set($hash={1:11, 5:67, 
23:2})$hash[5]$!hash[6]#if(!$hash[1000])xx#end");
     }
 
     public void testIndexSetting()
@@ -100,6 +101,7 @@
         assertEvalEquals("null","#set($str[0] = $NULL)#if($str[0] == 
$NULL)null#end");
         assertEvalEquals("null","#set($blaa = 
{\"apple\":\"grape\"})#set($blaa[\"apple\"] = $NULL)#if($blaa[\"apple\"] == 
$NULL)null#end");
         assertEvalEquals("2112", "#set($a[-1] = 2112)$a[2]");
+        assertEvalEquals("3344","#set($hash = {1:11, 2:22, 
5:66})#set($hash[2]=33)#set($hash[3]=44)$hash[2]$hash[3]");
     }
     
     

Modified: velocity/engine/trunk/xdocs/docs/user-guide.xml
URL: 
http://svn.apache.org/viewvc/velocity/engine/trunk/xdocs/docs/user-guide.xml?rev=730763&r1=730762&r2=730763&view=diff
==============================================================================
--- velocity/engine/trunk/xdocs/docs/user-guide.xml (original)
+++ velocity/engine/trunk/xdocs/docs/user-guide.xml Fri Jan  2 08:02:30 2009
@@ -642,10 +642,8 @@
 #set($foo.bar[1] = 3)
 #set($map["apple"] = "orange")</source>
  <p>
-   The specified element is set with the given value.  If the index
-   value is of type Integer then Velocity calls <code>.set(Integer,
-   &lt;val>)</code> which works with arrays, otherwise it calls
-   <code>.put(&lt;val>, &lt;val>)</code> which works with Maps.
+   The specified element is set with the given value.  Velocity tries
+   first the 'set' method on the element, then 'put' to make the assignment.
  </p>
 
  <p>


Reply via email to