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;
       }
  
  
  

Reply via email to