Example Velocimacro that sets arbitrary fields, #eval directive

Skip to first unread message

Mark Pitely

May 10, 2021, 11:52:09 AMMay 10
to dot...@googlegroups.com
For our majors (we use the term 'program') - we have a tiered set of information. Suppose we have testimonial videos made. If the program (smallest unit) has a testimonial, show it on the program page, if not, show the department testimonial, and, if not, show the college testimonial.

You could do this with code like this:
#set ($videourl=$college.testimonial)
#if ($UtilMethods.isSet($department.testimonial))
#set ($viderourl=$department.testimonial)
#iif ($UtilMethods.isSet($program.testimonial))
#set ($videorul=$program.testimonial)
My Video is at $videourl

This is fine, but as a programmer, I want a 'smarter' solution sometimes, to avoid repetitive code. Here is a sneaky solution that takes advantage of Velocity's powerful #eval function and flexible parsing.

## A Tool to set defaults for one of three things.
#macro( defaulter $varname )
#set ($aprog="\$program.${varname}")
#set ($myprog="#evaluate($aprog)")
#set ($adept="\$department.${varname}")
#set ($mydept="#evaluate($adept)")
#set ($adef="\$defaults.${varname}")
#set ($mydef="#evaluate($adef)")
#set ($aval=$mydef)
#if ($UtilMethods.isSet($mydept))
#set ($aval=$mydept)
#if ($UtilMethods.isSet($myprog))
#set ($aval=$myprog)
#set ($avar="${esc.h}set (${esc.d}${varname}=\"${aval}\")")
#evaluate ($avar)

Now, I just use this:
#defaulter ("videourl")
My video is $videourl. 

Let's look at what this does.
#set ($adept="\$department.${varname}")
This makes a string that equals '$department.videourl' (if 'videourl' is the text sent).
The slash makes sure to escape the (first) $, I could have used ${esc.d} as well.
So, I am escaping $department but parsing $varname.
#set ($mydept="#evaluate($adept)")
Now, $mydept is now set to the evaluation of that string, as if I had typed:
#set ($mydept=$department.videourl)
So, we are able to perform the same logic as we did before, and bring it all home with:
#set ($avar="${esc.h}set (${esc.d}${varname}=\"${aval}\")")
$avar is now the string  '#set ($videourl=$aval)', and once we evaluate it we are done.
So $videourl is now set in velocity despite never making an explicit call to #set ($videourl)!

I would normally advise avoiding tricky bits of code like this and just write it all out, it is easier to debug, I think, and most importantly, no less fast. But, if you ever need to work with arbitrary (here, one step removed, fake variables) to do something, code like this might really help- you should know it is at least possible: You can use velocity to write velocity.
The pieces above also work outside of the context of macros.

Mark Pitely
Marywood University

Reply all
Reply to author
0 new messages