Data Models

Method Model

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 TemplateMethodModels 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 TemplateModels 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.

Methods are first-class objects

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.