You need to reuse portions of a template to standardize the display of common elements such as an address or a name.
Use Velocity Macro definitions to reuse logic to print out
both names and addresses. Velocity macros
are like subroutines that take a set of parameters and perform common
tasks. In the following Velocity template, two macros,
#name
and #address
, handle the
printing of names and addresses:
#set( $volunteer = $appointment.volunteer ) #set( $location = $appointment.location ) #set( $org = $appointment.organization ) ## Define the "name" macro #macro( name $object )$!object.firstName $!object.lastName#end ## Define the "address" macro #macro( address $object ) $!object.address.street1 $!object.address.street2 $!object.address.city, $!object.address.state $!object.address.zipcode #end #name( $volunteer ), Thank you for volunteering to help serve food at the $location.name next week. This email is a reminder that you are scheduled to help out from $appointment.startTime to $appointment.endTime on $appointment.date. The address of the shelter is: #address( $location ) If you need directions to the shelter click the following URL: ${org.baseUrl}directions?location=${location.id} Also, if you are unable to help out on $appointment.date, please let us know by sending an email to ${org.email} or by filling out the form at this URL: ${org.baseUrl}planschange?appointment=${appointment.id} Thanks again, #name( $org.president ) #address( $org )
In the following code, the template shown previously is loaded from a
classpath resource organize.vm
, and an
Appointment
object is placed in a
VelocityContext
:
import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; // Create and initialize a VelocityEngine setting a configuration property VelocityEngine vEngine = new VelocityEngine( ); vEnging.setProperty( RuntimeConstants.VM_CONTEXT_LOCALSCOPE, Boolean.TRUE ); vEngine.init( ); // Create a test Appointment Appointment appointment = testAppointment( ); // Create a Velocity Context and give it the appointment VelocityContext context = new VelocityContext( ); context.put("appointment", appointment); // Prepare a StringWriter that will hold the contents of // our template merge StringWriter writer = new StringWriter( ); // Get a stream to read in our velocity template. The // organize.vm file is loaded from the classpath and is stored // in the same package as the current class. InputStream templateStream = getClass( ).getResourceAsStream("organize.vm"); Reader reader = new InputStreamReader( templateStream ); // Evaluate the template vEngine.evaluate(context, writer, "test", reader); // Print out the results of the template evaluation System.out.println( "organize: " + writer.toString( ) );
The template is merged with a VelocityContext
, and
the following output is produced:
John S.
,
Thank you for volunteering to help serve food at the Boston Homeless
Veterans Shelter next week. This email is a reminder that you are
scheduled to help out from 9:00 AM to 2:00 PM on Monday, September
12, 2003. The address of the shelter is:
17 Court Street
Boston, MA 01260
If you need directions to the shelter click the following URL:
http://www.organize.com/directions?location=2342
Also, if you are unable to help out on September 12th, please let us
know by sending an email to [email protected]
or by filling out the form at this URL:
http://www.organize.com/planschange?appointment=29932422
Thanks again,
Brishen R.
201 N. 2nd Street
Jersey City, NJ 20213
A macro definition is started with the #macro
directive and ended with #end
; the same macro is
invoked by calling #<macro_name>( <parameters> )
. Velocity macros must be defined before they are
referenced, using the following syntax:
#macro(<name> <arguments>) <Macro Body> #end
Macro parameters are
not
typed as are method parameters in Java; there is no mechanism to
check that an Address
object is passed to the
#address
macro, throwing an exception if an
inappropriate object is encountered. To successfully render this
Velocity template, verify that an Address
is sent
to the #address
macro and a
Person
is sent to the #name
macro.
In the previous example, an instance of
VelocityEngine
is created and the
RuntimeConstants.VM_CONTEXT_LOCALSCOPE
property is
set to true
. This property corresponds to the
velocimacro.context.localscope
, which controls the
scope of references created by #set
directives
within macros. When this configuration property is set to
true
, references created in the body of a macro
are local to that macro.
The Velocity template in the Solution expects a single reference
$appointment
to an Appointment
bean. Each Appointment
has a
volunteer
property of type
Person
, and every Organization
has a president
property of type
Person
. These Person
objects,
${appointment.volunteer}
and
${appointment.organization.president}
, are passed
to the #name macro that prints out the first and last name. Two
Address
objects,
${appointment.location.address}
and
${appointment.organization.address}
, are passed to
the #address
macro that prints a standard U.S.
mailing address.
A macro can contain any directive used in Velocity; the following
macro uses nested directives to print out a list of numbers in HTML.
#numberList
allows you to specify a range with
$low
and $high
; values in
$numbers
within this range will be printed bold:
#macro( numberList $numbers $low $high ) <ul> #foreach( $number in $numbers ) #if( ($number > $low) && ($number < $high) ) <li><b>$number</b> - In Range!</li> #else <li>$number</li> - Out of Range!</li> #end #end </ul> #end
The macro defined above would be called by the following Velocity
template. Note the presence of comments, which are preceded by two
hashes (##
):
#set( $squares = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] )
## Print out a list of numbers highlighting numbers
## between 25 and 75
#numberList( $squares, 25, 75 )
If your system has a large number of Velocity templates, you can
create a set of files to hold common macros, which will be made
available to every Velocity template using the
velocimacro.library
property. For more
information, see the Velocity User Guide (http://jakarta.apache.org/velocity/user-guide.html#Velocimacros).
18.119.136.84