You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Chris Miller <ch...@swebtec.com> on 2002/10/07 16:40:08 UTC

Re: Variable method name in a macro?

Does anyone have any comments on this? I must be missing something simple.

"Chris Miller" <ch...@swebtec.com> wrote in message
news:amtefe$52c$1@main.gmane.org...
> First off, I had a look around the CVS contrib dirs and the Tools
> subproject, but still couldn't see your tool code.
>
> I've been trying to implement this myself. However I'm still missing
either
> a vital piece of information, or, more likely, a vital piece of my brain.
>
> I am trying to achieve something like the following:
>
> #set($method = 'propertyName')
> #foreach($option in $list)
>     $tool.eval("\$option.$method")
> #end
>
> So far I have the following code in my tool:
>
>    public String eval(String str) throws Exception
>    {
>        StringWriter writer = new StringWriter(100);
>        Velocity.evaluate(context, writer, "postEval", str);
>        return writer.toString();
>    }
>
> Note that I pass the context into the tool's constructor, and then put the
> tool into the context before merging my original template :-)
>
> This however still does not work - the eval() method does not get called.
> I've also tried using $tool.eval("\option.get$method()"), which doesn't
even
> parse properly. Any tips on what I'm still missing?
>
> Thanks,
> Chris
>
>
> > 2) Velocity doesn't do evaluation interpolation for introspection (that
> > phrase may not make sense?)
> >
> >    $formBean.$method
> >
> > does *not* work.
> >
> > However, you can easily make a tool (I have said this same thing 3-4
times
> > this week - I am going to just write it and put in contrib at this point
> to
> > prove my learning curve isn't flat) where you *can* do
> >
> >   $tool.eval("\$formBean.get$which()")
> >
> > such that the eval(String) method gets, with $which -> "FirstName",
> >
> >    $formBean.getFirstName()
> >
> > and then your tool can just evaluate that against the context.
> >
> > Does that make sense?
> >
> > --
> > Geir Magnusson Jr.
> > Research & Development, Adeptra Inc.
> > geirm@adeptra.com
> > +1-203-247-1713





--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Variable method name in a macro?

Posted by Chris Miller <ch...@swebtec.com>.
> Does this do what you want...
>
> #set ($pre = '$book.')
> #set ($bookeval = "$pre$propertyName")
> $took.eval($bookeval)
>
> -- Denis.

YES!! :-)))) I knew I was close but I couldn't nail down the exact syntax.
Thank you very much Denis! Looks like it's time for me to read the manual a
bit more carefully wrt the single vs double quote behaviour.





--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: Variable method name in a macro?

Posted by Aapo Laakkonen <aa...@giro.fi>.
>> So, similar to what Aapo is after
>>
> Does this do what you want...
> 
> #set ($pre = '$book.')
> #set ($bookeval = "$pre$propertyName")
> $took.eval($bookeval)

Ok. I got it to work!

I have attached my solution in this posting.

And here is how to use it:

#macro(list $data $columns)
<table border="1">
<tr>
    #foreach($column in $columns)
    <th>$column</th>
    #end
</tr>
#foreach($row in $data)
<tr>
    #set ($table = '$row.')
    #foreach($column in $columns)
        <td>$Global.evaluate("$table$column")</td>
    #end
</tr>
#end
</table>
#end

#set($columns = ["name.first", "name.last"])
#list($employees $columns)

And this renders to something like this:

|----------------|----------------|
|   name.first   |    name.last   |
|----------------|----------------|
| Aapo           | Laakkonen      |
|----------------|----------------|

Next I can i18n name.first and name.last headings and continue to add
mopre functionality.

Thanks for your help!

Re: Variable method name in a macro?

Posted by Denis <ji...@respublica.fr>.
Hi Chris,

On Tuesday, October 8, 2002, at 08:44  am, Chris Miller wrote:

> That's not what I'm after though. What I really want is a way to 
> pass this
> exact string (excluding the quotes) through to my tool:
>
> "$book.title"
>
> The catch of course is that the String "title" needs to be evaluated by
> Velocity first, since I am retrieving the value from elsewhere in the
> context. So, similar to what Aapo is after, I only want to evaluate the
> second half of the expression (ie the method name), and then pass 
> the whole
> string through to my eval() method which will then effectively 
> evaluate the
> expression a second time.
>
> ie:
>
> $book.$propertyName  ## Only evaluate the $propertyName
> $book.title          ## Result of the first evaluation
> The Lord of the Rings    ## Result of the second evaluation (ie, 
> the result
> of the call to $tool.eval("$book.title"))

Does this do what you want...

#set ($pre = '$book.')
#set ($bookeval = "$pre$propertyName")
$took.eval($bookeval)

-- Denis.

>
> Thanks for your patience so far :-)
> Chris
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Variable method name in a macro?

Posted by Chris Miller <ch...@swebtec.com>.
Hi Terry,

Responses inline...

> Just to be very clear: Velocity does *not* retrieve properties, public or
> not.  It will *only* invoke public methods.  And, using Reflection, if
> 'propertyName' refers to a method, the 'getter' method would have to be
> 'getpropertyName()'.

you mean getPropertyName()?

Yep, sorry I guess my description was confusing, however I am aware of the
way this works. I have something like the following:

class Book {
  private String title;
  public String getTitle() {
    return title;
  }
  public void setTitle(String title) {
    this.title = title;
  }
  // etc ....
}

> Maybe you could just confirm that, and then let's see about additional
> questions. ( I make extensive use of all kinds of tools, with all kinds of
> parameters passed to them.  So I know it works.)
>
> Regards,
>
> Terry
>
> PS: And regardless of the above, if you want something like this:
#set($xxx=
> $yyy$zzz),
> I believe you should restate it as this: #set($xxx= "$yyy$zzz").
> Furthermore, I find that occasionally when I string varbs together, the
> parser gets confused.  If that were to have happened in the above example,
> what I'd try would be this: #set($xxx= "${yyy}${zzz}").

That's not what I'm after though. What I really want is a way to pass this
exact string (excluding the quotes) through to my tool:

"$book.title"

The catch of course is that the String "title" needs to be evaluated by
Velocity first, since I am retrieving the value from elsewhere in the
context. So, similar to what Aapo is after, I only want to evaluate the
second half of the expression (ie the method name), and then pass the whole
string through to my eval() method which will then effectively evaluate the
expression a second time.

ie:

$book.$propertyName  ## Only evaluate the $propertyName
$book.title          ## Result of the first evaluation
The Lord of the Rings    ## Result of the second evaluation (ie, the result
of the call to $tool.eval("$book.title"))

Thanks for your patience so far :-)
Chris





--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Variable method name in a macro?

Posted by Terry Steichen <te...@net-frame.com>.
Chris,

Just to be very clear: Velocity does *not* retrieve properties, public or
not.  It will *only* invoke public methods.  And, using Reflection, if
'propertyName' refers to a method, the 'getter' method would have to be
'getpropertyName()'.

Maybe you could just confirm that, and then let's see about additional
questions. ( I make extensive use of all kinds of tools, with all kinds of
parameters passed to them.  So I know it works.)

Regards,

Terry

PS: And regardless of the above, if you want something like this: #set($xxx=
$yyy$zzz),
I believe you should restate it as this: #set($xxx= "$yyy$zzz").
Furthermore, I find that occasionally when I string varbs together, the
parser gets confused.  If that were to have happened in the above example,
what I'd try would be this: #set($xxx= "${yyy}${zzz}").

----- Original Message -----
From: "Chris Miller" <ch...@swebtec.com>
To: <ve...@jakarta.apache.org>
Sent: Monday, October 07, 2002 6:41 PM
Subject: Re: Variable method name in a macro?


> Hi Terry,
>
> > Is 'propertyName' the name of a public method, or is it a property?
>
> It's a property, declared with public getters and setters.
>
> > Is this VTL code in a macro or in the main template body?
>
> I've tried both without success. Ideally though for real world use I'll
want
> it to be in a macro.
>
> > Curiosity: (1) why the single quotes around 'propertyName', and (2) why
> the
> > '\' in "\$option..$method"?
>
> 1) No reason, bad psuedocode :-)
> 2) This is where I'm really having problems I suspect. I was trying to
> escape the $ sign to prevent evaluation. Let's look at an example. Suppose
I
> have a book bean, with properties title, author, etc. I'd like to be able
to
> perform the equivalent of this java code (assume the book object is
already
> in the context):
>
> String propertyName = "title";        // In reality this is retrieved
> dynamically
> String evalString = "$book." + propertyName;
> String title = tool.eval(evalString);
>
> The big problem I seem to be having is how to pass the string
"$book.title"
> into the eval method - the eval method itself seems to work fine. How do I
> escape the $ character? Everything I have tried has failed either with a
> lexical error, or it does not evaluate as I would like.
>
> eg, I would have thought this would work, but it doesn't:
>
> #set($propertyName = "title")
> #set($objName = '$book.')
> #set($evalString = $objName$propertyName)
> $tool.eval($evalString)
>
> So, what's the trick? Any help greatly appreciated!! :-)
>
>
>
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Variable method name in a macro?

Posted by Chris Miller <ch...@swebtec.com>.
Hi Aapo,

Yes, you've got it, you're trying to do exactly the same thing as me (in
reality I want to use this in several places, including to dynamically
populate tables and select boxes).

However it's actually trivial to write a basic #eval macro. The hard part
seems to be passing in the parameters to it! I can't for the life of me
figure out how to get the '$' character passed in to my eval method
successfully.

I have this macro:

#macro(eval $query)
  $tool.eval($query)
#end

which calls this method:

public Object eval(Object str) throws Exception {
  StringWriter writer = new StringWriter(100);
  Velocity.evaluate(context, writer, "postEval", str.toString());
  return writer.toString();
}

The only trick is to make sure the $tool object has access to the current
context - I just pass it in as a constructor parameter which seems a bit
clunky, but it works. The only limitation (I think?) is that it won't
evaluate something that was #set during the processing of the template
(although I haven't actually tested that yet).





--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: Variable method name in a macro?

Posted by Aapo Laakkonen <aa...@giro.fi>.
> Aapo,
>
> Here is a small script, using a context tool called 'ff':

Yeah, I have done something similar, but this does not work as I want it
to.

> #set($test = "getSig()")
> 1-$ff.$test<br>
> 1-npg1.business.ff@7afa94.getSig()
> ##note that this is merely a reference

Ok. This is what I want. How can I use that? For me output like
"npg1.business.ff@7afa94.getSig()" is completely useless.

> 2-$ff.getSig()<br>
> 3-$ff.Sig<br>

These are not dynamic, cause method names are hard-coded.

> Here's the output:
> 2-This is FF, your friendly formatter
> 3-This is FF, your friendly formatter

Yeah I know. How does these relate to the first line:

    #set($test = "getSig()") ?

Is it impossible to have #eval directive built-in Velocity? There is
already quite useless #stop directive, so why not to add #eval? It's not
bloat! It's useful directive, trust me, :-)! Or maybe we should modify
#parse directive to also parse strings, not only files. What do you
think? Are these insane ideas?

Kind Regards
Aapo Laakkonen


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Variable method name in a macro?

Posted by Terry Steichen <te...@net-frame.com>.
Aapo,

Here is a small script, using a context tool called 'ff':

#set($test = "getSig()")
1-$ff.$test<br>
2-$ff.getSig()<br>
3-$ff.Sig<br>

Here's the output:
1-npg1.business.ff@7afa94.getSig()        ##note that this is merely a
reference
2-This is FF, your friendly formatter
3-This is FF, your friendly formatter

HTH,

Terry



----- Original Message -----
From: "Aapo Laakkonen" <aa...@giro.fi>
To: "'Velocity Users List'" <ve...@jakarta.apache.org>
Sent: Monday, October 07, 2002 7:27 PM
Subject: RE: Variable method name in a macro?


> > String propertyName = "title";
> > String evalString = "$book." + propertyName;
> > String title = tool.eval(evalString);
> >
> > The big problem I seem to be having is how
> > to pass the string "$book.title" into the
> > eval method - the eval method itself seems
> > to work fine.
>
> This is exactly what I'm after also. Here is my (more complex) example:
>
> // $data is a list (java.util.List) of beans with proper getters (and
> setters).
>
> #macro(list $data $columns)
> <table>
>   #foreach ($column in $columns)
>     <th>$tool.getText($column)</th>
>   #end
>   #foreach ($row in $data)
>   <tr>
>     #foreach ($column in $columns)
>       <td>
>         In this place I want Velocity to call following methods:
>         $data.getName().getFirst() or $data.getName().getLast().
>         eg. $tool.evaluate("$row.$column").
>       </td>
>     #end
>   </tr>
>   #end
> </table>
> #end
>
> #set($columns = ["name.first", "name.last"]
> #list($employees $columns)
>
> This way I could write html-tables with only 2-lines of code. And I
> could develop it furher to build very handy web ui-tools (with search,
> actions (update, insert, delete), sorting, paging, etc.).
>
> > So, what's the trick? Any help greatly appreciated!! :-)
>
> If you get it to work, could you send me your solution? I will look this
> thing again tomorrow and will post my solution (if I found one) here.
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: Variable method name in a macro?

Posted by Aapo Laakkonen <aa...@giro.fi>.
> String propertyName = "title";
> String evalString = "$book." + propertyName;
> String title = tool.eval(evalString);
>
> The big problem I seem to be having is how
> to pass the string "$book.title" into the
> eval method - the eval method itself seems
> to work fine.

This is exactly what I'm after also. Here is my (more complex) example:

// $data is a list (java.util.List) of beans with proper getters (and
setters).

#macro(list $data $columns)
<table>
  #foreach ($column in $columns)
    <th>$tool.getText($column)</th>
  #end
  #foreach ($row in $data)
  <tr>
    #foreach ($column in $columns)
      <td>
        In this place I want Velocity to call following methods:
        $data.getName().getFirst() or $data.getName().getLast().
        eg. $tool.evaluate("$row.$column").
      </td>
    #end
  </tr>
  #end
</table>
#end

#set($columns = ["name.first", "name.last"]
#list($employees $columns)

This way I could write html-tables with only 2-lines of code. And I
could develop it furher to build very handy web ui-tools (with search,
actions (update, insert, delete), sorting, paging, etc.).

> So, what's the trick? Any help greatly appreciated!! :-)

If you get it to work, could you send me your solution? I will look this
thing again tomorrow and will post my solution (if I found one) here.


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Variable method name in a macro?

Posted by Chris Miller <ch...@swebtec.com>.
Hi Terry,

> Is 'propertyName' the name of a public method, or is it a property?

It's a property, declared with public getters and setters.

> Is this VTL code in a macro or in the main template body?

I've tried both without success. Ideally though for real world use I'll want
it to be in a macro.

> Curiosity: (1) why the single quotes around 'propertyName', and (2) why
the
> '\' in "\$option..$method"?

1) No reason, bad psuedocode :-)
2) This is where I'm really having problems I suspect. I was trying to
escape the $ sign to prevent evaluation. Let's look at an example. Suppose I
have a book bean, with properties title, author, etc. I'd like to be able to
perform the equivalent of this java code (assume the book object is already
in the context):

String propertyName = "title";        // In reality this is retrieved
dynamically
String evalString = "$book." + propertyName;
String title = tool.eval(evalString);

The big problem I seem to be having is how to pass the string "$book.title"
into the eval method - the eval method itself seems to work fine. How do I
escape the $ character? Everything I have tried has failed either with a
lexical error, or it does not evaluate as I would like.

eg, I would have thought this would work, but it doesn't:

#set($propertyName = "title")
#set($objName = '$book.')
#set($evalString = $objName$propertyName)
$tool.eval($evalString)

So, what's the trick? Any help greatly appreciated!! :-)





--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Variable method name in a macro?

Posted by Terry Steichen <te...@net-frame.com>.
Chris,

Is 'propertyName' the name of a public method, or is it a property?

Is this VTL code in a macro or in the main template body?

Curiosity: (1) why the single quotes around 'propertyName', and (2) why the
'\' in "\$option..$method"?

Regards,

Terry

----- Original Message -----
From: "Chris Miller" <ch...@swebtec.com>
To: <ve...@jakarta.apache.org>
Sent: Monday, October 07, 2002 10:40 AM
Subject: Re: Variable method name in a macro?


> Does anyone have any comments on this? I must be missing something simple.
>
> "Chris Miller" <ch...@swebtec.com> wrote in message
> news:amtefe$52c$1@main.gmane.org...
> > First off, I had a look around the CVS contrib dirs and the Tools
> > subproject, but still couldn't see your tool code.
> >
> > I've been trying to implement this myself. However I'm still missing
> either
> > a vital piece of information, or, more likely, a vital piece of my
brain.
> >
> > I am trying to achieve something like the following:
> >
> > #set($method = 'propertyName')
> > #foreach($option in $list)
> >     $tool.eval("\$option.$method")
> > #end
> >
> > So far I have the following code in my tool:
> >
> >    public String eval(String str) throws Exception
> >    {
> >        StringWriter writer = new StringWriter(100);
> >        Velocity.evaluate(context, writer, "postEval", str);
> >        return writer.toString();
> >    }
> >
> > Note that I pass the context into the tool's constructor, and then put
the
> > tool into the context before merging my original template :-)
> >
> > This however still does not work - the eval() method does not get
called.
> > I've also tried using $tool.eval("\option.get$method()"), which doesn't
> even
> > parse properly. Any tips on what I'm still missing?
> >
> > Thanks,
> > Chris
> >
> >
> > > 2) Velocity doesn't do evaluation interpolation for introspection
(that
> > > phrase may not make sense?)
> > >
> > >    $formBean.$method
> > >
> > > does *not* work.
> > >
> > > However, you can easily make a tool (I have said this same thing 3-4
> times
> > > this week - I am going to just write it and put in contrib at this
point
> > to
> > > prove my learning curve isn't flat) where you *can* do
> > >
> > >   $tool.eval("\$formBean.get$which()")
> > >
> > > such that the eval(String) method gets, with $which -> "FirstName",
> > >
> > >    $formBean.getFirstName()
> > >
> > > and then your tool can just evaluate that against the context.
> > >
> > > Does that make sense?
> > >
> > > --
> > > Geir Magnusson Jr.
> > > Research & Development, Adeptra Inc.
> > > geirm@adeptra.com
> > > +1-203-247-1713
>
>
>
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>