The TemplateMethodModel
interface defines FM-Classic's way
of implementing methods within a TemplateModel
. The signature
of a TemplateMethodModel is below:
public TemplateModel exec(java.util.List<String> arguments) throws TemplateModelException;
The argument list that FM-Classic supplies is a list of String
objects, each one corresponding with an argument supplied to the method,
in the order that they were specified. If a method is called with no arguments,
the list will be empty, rather than null.
Note: Unlike other languages, such as Perl, FM-Classic does not flatten
complex variables. If a TemplateListModel
or
TemplateHashModel
is passed as a parameter to a
TemplateMethodModel
, FM-Classic will issue an error message.
For this reason, TemplateMethodModel2
was created. The signature
of a TemplateMethodModel2 is below:
public TemplateModel exec(java.util.List<TemplateModel> arguments) throws TemplateModelException;
It works the same way as TemplateMethodModel
, except all its
arguments are passed in as TemplateModel
objects, instead of
String
objects. This allows you to use the full flexibility
of all the TemplateModel
interfaces, including the
TemplateObjectModel
interface described later.
Note that TemplateMethodModel
implements a call to
only one method. To provide many methods, wrap up lots of
TemplateMethodModel
s inside a TemplateHashModel
,
one for each method you want to provide.
If the method model does not exist, or the isEmpty()
method of
a method model returns true, the method will not be called. Instead,
null
will be returned.
Like most other models, TemplateMethodModel
returns a
TemplateModel
. This allows method calls
to be very flexible, and allows methods to be chained together similarly to
the way other TemplateModel
s can be chained. To chain method
models, you can write:
${method(arg1, arg2, arg3)(arg6, arg7)}
Here, the first method model takes three arguments, and returns a second
TemplateMethodModel
. The second method model takes two arguments
and returns a TemplateScalarModel
.
If you have a hash named myBall
that has a method named
getColor
, you can quite intuitively write:
${myBall.getColor()}
This will invoke the method and retrieve the color of the ball. What is less obvious is that you can assign the method to a variable, and use it on its own, as in:
<assign getColorOfMyBall = myBall.getColor> ${getColorOfMyBall()}
By omitting the parentheses in the assign instruction, you didn't execute the method, rather you assigned the method itself to a variable, and then you have called it separately. This ability is found in several programming languages, such as Python and Lisp, and has several applications. Instead of writing:
<switch variable> <case cond1> ${obj1.method1(arg1, arg2, arg3, arg4, arg5, arg6)} <break> <case cond2> ${obj2.method2(arg1, arg2, arg3, arg4, arg5, arg6)} <break> <default> ${obj3.method3(arg1, arg2, arg3, arg4, arg5, arg6)} </switch>
you can write instead:
<switch variable> <case cond1> <assign method = obj1.method1> <break> <case cond2> <assign method = obj2.method2> <break> <default> <assign method = obj3.method3> </switch> ${method(arg1, arg2, arg3, arg4, arg5, arg6)}
Thus sparing yourself from duplicating the argument list three times.
First-class methods also allow templates to define lambdas, and allow for some forms of functional programming. See lambdas for more information.
Previous: Model Root | Next: Transform Model |