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,
- <val>)</code> which works with arrays, otherwise it calls
- <code>.put(<val>, <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>