blob: 9367e365aa616ef19e554c1a57246a650af329e3 [file] [log] [blame]
~~ $Id$
~~
~~ Licensed to the Apache Software Foundation (ASF) under one
~~ or more contributor license agreements. See the NOTICE file
~~ distributed with this work for additional information
~~ regarding copyright ownership. The ASF licenses this file
~~ to you under the Apache License, Version 2.0 (the
~~ "License"); you may not use this file except in compliance
~~ with the License. You may obtain a copy of the License at
~~
~~ http://www.apache.org/licenses/LICENSE-2.0
~~
~~ Unless required by applicable law or agreed to in writing,
~~ software distributed under the License is distributed on an
~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~~ KIND, either express or implied. See the License for the
~~ specific language governing permissions and limitations
~~ under the License.
~~
-----------
Supporting a template language
-----------
Supporting a template language
Tiles currently uses JSP, FreeMarker and Velocity as a template language.
All these view technologies are supported through the
{{{../../framework/tiles-template}tiles-template}} module.
This module contains all the common code for directive-based template languages,
JSP and FreeMarker have this characteristic, because they use "tags" as directives.
Velocity support uses both a "directive-based" style and a Java-like style.
* Creating directives
To create a directive in your favourite template language, simply use all of
the classes in <<<org.apache.tiles.template>>> package. These classes (called "models)
have three methods:
* <<<start>>>: to be called at the start of the directive;
* <<<end>>>: to be called at the end of the directive;
* <<<execute>>>: when you need to use directives with and without body.
[]
Typically, you need only to use <<<start>>> and <<<end>>> methods (this is the
case of JSP and FreeMarker), but sometimes you need <<<execute>>> to: Velocity
support uses <<<execute>>> methods to have a clearer syntax when no body is
provided.
For example, the {{{../../apidocs/org/apache/tiles/template/InsertAttributeModel.html}InsertAttributeModel}}
model can be implemented in FreeMarker this way:
------------------------
@SuppressWarnings("unchecked")
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body) throws TemplateException, IOException {
Map<String, TemplateModel> parms = (Map<String, TemplateModel>) params;
TilesContainer container = FreeMarkerUtil.getCurrentContainer(env);
model.start(
FreeMarkerUtil.getComposeStack(env),
container,
FreeMarkerUtil.getAsBoolean(parms.get("ignore"), false),
FreeMarkerUtil.getAsString(parms.get("preparer")),
FreeMarkerUtil.getAsString(parms.get("role")),
FreeMarkerUtil.getAsObject(parms.get("defaultValue")),
FreeMarkerUtil.getAsString(parms
.get("defaultValueRole")), FreeMarkerUtil
.getAsString(parms.get("defaultValueType")),
FreeMarkerUtil.getAsString(parms.get("name")),
(Attribute) FreeMarkerUtil.getAsObject(parms
.get("value")), env);
FreeMarkerUtil.evaluateBody(body);
model.end(FreeMarkerUtil.getComposeStack(env), container,
FreeMarkerUtil.getAsBoolean(parms.get("ignore"), false), env);
}
------------------------
As you can see, the map of parameters at the call of the tag are converted into
parameters of the template model. In JSP, private fields would have become such
parameters.
The <<<FreeMarkerUtil.evaluateBody(body)>>> is used to evaluate the body, and all
of its tags, so the model can start and end correctly.
** The role of the compose stack
In the previous code you may have noticed the "compose stack" parameter.
This stack is simply a Stack of objects that is used to store objects that
need to be composed between the start and the end of the model.
For example, if you use {{{../../apidocs/org/apache/tiles/template/DefinitionModel.html}DefinitionModel}},
the Definition object is created in <<<start>>> and pushed into the stack and it is retrieved
in <<<end>>>. Between these methods, other models, like PutAttributeModel, can
get it from the stack and modify it.
* Developing attribute renderers
Template language files (for example ".ftl" files for FreeMarker, ".vm" for Velocity
can be rendered using specific servlets (respectively FreemarkerServlet
and VelocityViewServlet).
However, Tiles attributes can be rendered through the use of
{{{../advanced/attribute-rendering.html}attribute renderers}}.
Currently, the implementations for Velocity and FreeMarker use their servlets
as delegate for the real rendering. This means that these renderes use the
servlet <<directly>> through calling some specific method, and not forwarding to an URL.
This is particularly useful if the attribute to render points to a file
not accessible as an URL, but allowing the correct initialization of these
attributes and their integration with the rest of the layout.