| ~~ $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. |