geirm 01/01/17 21:08:19
Modified: src/java/org/apache/velocity/runtime/parser/node
ASTReference.java
Log:
Added the contribution from Christoph Reck <[EMAIL PROTECTED]> to support Map
introspection on #set()
So #set($foo.bar = "blargh")
will attempt foo.put("bar", "blargh") if foo.setBar( "blargh" ) fails.
Revision Changes Path
1.19 +80 -27
jakarta-velocity/src/java/org/apache/velocity/runtime/parser/node/ASTReference.java
Index: ASTReference.java
===================================================================
RCS file:
/home/cvs/jakarta-velocity/src/java/org/apache/velocity/runtime/parser/node/ASTReference.java,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- ASTReference.java 2001/01/03 05:27:37 1.18
+++ ASTReference.java 2001/01/18 05:08:18 1.19
@@ -1,3 +1,5 @@
+package org.apache.velocity.runtime.parser.node;
+
/* Generated By:JJTree: Do not edit this line. ASTReference.java */
/*
@@ -54,21 +56,6 @@
* <http://www.apache.org/>.
*/
-
-/**
- * This class is responsible for handling the references in
- * VTL ($foo).
- *
- * Please look at the Parser.jjt file which is
- * what controls the generation of this class.
- *
- * @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a>
- * @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a>
- * @version $Id: ASTReference.java,v 1.18 2001/01/03 05:27:37 geirm Exp $
-*/
-
-package org.apache.velocity.runtime.parser.node;
-
import java.io.Writer;
import java.io.IOException;
import java.util.Map;
@@ -81,6 +68,20 @@
import org.apache.velocity.runtime.exception.ReferenceException;
import org.apache.velocity.runtime.parser.*;
+
+/**
+ * This class is responsible for handling the references in
+ * VTL ($foo).
+ *
+ * Please look at the Parser.jjt file which is
+ * what controls the generation of this class.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Christoph Reck</a>
+ * @version $Id: ASTReference.java,v 1.19 2001/01/18 05:08:18 geirm Exp $
+*/
+
public class ASTReference extends SimpleNode
{
/* Reference types */
@@ -240,6 +241,16 @@
return ( computableReference ? execute(null, context) : null );
}
+ /**
+ * Sets the value of a complex reference (something like $foo.bar)
+ * Currently used by ASTSetReference()
+ *
+ * @see ASTSetDirective
+ *
+ * @param context context object containing this reference
+ * @param value Object to set as value
+ * @return true if successful, false otherwise
+ */
public boolean setValue( InternalContextAdapter context, Object value)
{
/*
@@ -273,28 +284,70 @@
}
}
- Object[] args = { value };
- Class[] params = { value.getClass() };
-
/*
- * This catches the last phase of setting a property
- * if we catch an exception we know that something
- * like $provider.Monkey is not a valid reference.
- * $provider may be in the context, but Monkey is
- * not a method of $provider.
+ * We support two ways of setting the value in a #set($ref.foo = $value ) :
+ * 1) ref.setFoo( value )
+ * 2) ref,put("foo", value ) to parallel the get() map introspection
*/
+ String identifier = jjtGetChild(children - 1).getFirstToken().image;
+
try
{
+ /*
+ * first, we introspect for the set<identifier> setter method
+ */
+
+ Class[] params = { value.getClass() };
Class c = result.getClass();
- Method m = c.getMethod("set" + jjtGetChild(children -
1).getFirstToken().image, params);
+ Method m = c.getMethod("set" + identifier, params);
+
+ /*
+ * and if we get here, getMethod() didn't chuck an exception...
+ */
+
+ Object[] args = { value };
m.invoke(result, args);
}
- catch (Exception e)
+ catch (NoSuchMethodException nsme)
{
- Runtime.error(new ReferenceException("reference set : template = " +
context.getCurrentTemplateName(), this));
- return false;
+ /*
+ * right now, we only support the Map interface
+ */
+
+ if (result instanceof Map)
+ {
+ try
+ {
+ ((Map) result).put(identifier, value);
+ }
+ catch (Exception ex)
+ {
+ Runtime.error("ASTReference Map.put : exception : " + ex
+ + " template = " +
context.getCurrentTemplateName()
+ + " [" + this.getLine() + "," + this.getColumn()
+ "]");
+ return false;
+ }
+ }
+ else
+ {
+ Runtime.error("ASTReference : cannot find " + identifier + " as
settable property or key to Map in"
+ + " template = " + context.getCurrentTemplateName()
+ + " [" + this.getLine() + "," + this.getColumn() +
"]");
+ return false;
+
+ }
}
+ catch( Exception e )
+ {
+ /*
+ * maybe a security exception?
+ */
+ Runtime.error("ASTReference setValue() : exception : " + e
+ + " template = " +
context.getCurrentTemplateName()
+ + " [" + this.getLine() + "," + this.getColumn()
+ "]");
+ return false;
+ }
return true;
}