<?xml version="1.0"?>

<!--
 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.
-->

<document>

<properties>
    <title>Context Howto</title>
    <author email="a@a.com">Turbine Documentation Team</author>
    <author email="criley@ekmail.com">Cameron Riley</author>
</properties>

<body>

<section name="Using the Turbine Context">
<p>
The Turbine Templating Services attach references to default Objects in the
Turbine Context as part of their initialization. In the case of the
TurbineVelocityService these references point to RunData, TemplateLink and
HtmlPageAttributes. These three are put into the Context in the
TurbineVelocityService class. The Context stores the Objects in a Hashtable
with a key and the Object.
</p>
</section>

<section name="Using the RunData Object">
<p>
The RunData Object is referenced by the "data" keyword, which when using this
in the templating system is referenced by $data. As the Context contains a link
to the RunData object all the public methods in the RunData Object are made
available to the template. For example, typing $data.getMessage() will access
the message String being stored in the RunData Object and print that as part
of the templates output.
</p>

<p>
RunData exposes an extremely rich series of methods and fields, for a full list
of these methods refer to the Javadocs for RunData. Some of the useful methods
exposed in RunData include;
</p>

<p>
<ul>
    addMessage(String msg) <br />
    getMessage() <br />
    getParameters() <br />
    getServerName() <br />
    getTitle() <br />
    getUser() <br />
    removeUserFromSession() <br />
    setMessage(String message) <br />
    setRedirectUri(String ruri) <br />
    setTitle(String title) <br />
</ul>
</p>

<p>
The RunData also allows for access to the TemplateInfo Object via
getTemplateInfo() and several convenience methods. This allows for properties
of the Templates to be modified for a Request when using templating systems like
Velocity, WebMacro or Freemarker.
</p>

<p>
As an example assume we want a printable page that contains only the Templating
Screen and not all the navigational components. To achieve this we can strip
out all the non screen templating components by describing a new Layout Template
called PrintableLayout.vm in the templates/layouts directory. All the
PrintableLayout needs contain is;
</p>

<source test=""><![CDATA[
    $screen_placeholder
]]></source>

<p>
Without the references to the $navigation.setTemplate() methods in the template
no navigational screen will be called. In the Screen Template that wants to take
advantage of the PrintableLayout Template add to the Template;
</p>

<source test=""><![CDATA[
    $data.setLayoutTemplate("PrintableLayout.vm")
]]></source>

<p>
This will strip the Screen Template of its Navigational components. These
convenience methods can also be used to expose and to set the Layout when the
Template is processed. Through this a User can potentially choose how they would
like their webpage to appear by choosing one of many different Layouts or
choices you, the webdesigner provide.
</p>

</section>

<section name="Using the TemplateLink Object">
<p>
The TemplateLink is an extended version of DynamicURI customised to be used in
the templates. The TemplateLink is referenced in the templates via $link and
exposes convenience methods for building URI's on the fly. For example in a
template to build the URI to another template, TemplateLink would be referenced
via;
</p>

<source test=""><![CDATA[
    $link.setPage("newpage.vm")
]]></source>

<p>
which when added to a Velocity template in the TDK that is running as localhost,
would return;
</p>

<p>
<blockquote>
    http://127.0.0.1:8080/newapp/servlet/newapp/template/index.vm
</blockquote>
</p>

<p>
where "newapp" is the chosen webapp deployment name.
</p>

<p>
However the HTML page will load itself into a screen and not be embedded within
the Layouts and Navigations. If you still wish static content to be embedded
within the specified layouts and navigations it is easier to add the static
content as a velocity template and not take advantage of any of the dynamic
content addition the Velocity Context allows.
</p>


<p>
TemplateLink and DynamicURI again expose a rich set of methods and fields to
the link reference, for a full list of fields and methods please refer to
TemplateLink and DynamicURI in the javadocs. Some of the useful methods
exposed are;
</p>

<p>
<ul>
    setPage(String templatename) <br />
    addPathInfo(ParameterParser pp) <br />
    addPathInfo(String name, String value) <br />
    addQueryData(ParameterParser pp) <br />
    addQueryData(String name, String value) <br />
    getScriptName() <br />
    getServerData() <br />
    getServerPort() <br />
    setAction(String action) <br />
    setScreen(String screen) <br />
    setSecure() <br />
</ul>
</p>
</section>

<section name="Using the HtmlPageAttributes Object">
<p>
The HtmlPageAttributes is accessed from within the context by the keyword
"page" and provides methods to modify the various HTML attributes of the
templating system. The Template context can be used to dictate the style of
the HTML page in the navigation and layout templates as well as modify these
attributes from within a screen.
</p>

<p>
As an example in the default.vm the page can be set to a maroon background with;
</p>

<source test=""><![CDATA[
    $page.setBgColor("#800000")
]]></source>

<p>
the screen template may need to set a new title to the page being displayed in
the browser, this can be done in the screen template via;
</p>

<source test=""><![CDATA[
    $page.setTitle("New Title to Page")
]]></source>

<p>
Non standard attributes can be added to the Body tag, for instance the
leftmargin or topmargin attributes via;
</p>

<source test=""><![CDATA[
    $page.addBodyAttribute("topmargin", 0)
]]></source>

<p>
For a full list of methods exposed to the page reference view the Javadocs for
HtmlPageAttributes. Other methods exposed to the page reference are;
</p>

<p>
<ul>
    addAttribute(String name, String value) <br />
    getTitle() <br />
    setBackground(String url) <br />
    setBgColor(String color) <br />
    setDescription(String description) <br />
    setKeywords(String description) <br />
    setLinkColor(String color) <br />
    setStyleSheet(String url) <br />
    setTextColor(String color) <br />
    setTitle(String title) <br />
    setVLinkColor(String color) <br />
</ul>
</p>
</section>

<section name="Adding your own Objects to the Context">
<p>
As the Context is stored as a Hashtable any Object can be placed inside
it and be accessed from a template. For instance, in a Velocity Screen
in the doBuildTemplate() method, a String could be added to the Context.
Please refer to the <a href="../getting-started.html">Getting
Started</a> documentation for more examples of using the Velocity
Context with screens and events.
</p>

<source test=""><![CDATA[
    context.put("hello",new String("testing"));
]]></source>

<p>
This can be referenced from within the template via;
</p>

<source test=""><![CDATA[
    $hello the hello reference
]]></source>

<p>
which would be output as;
</p>

<source test=""><![CDATA[
    testing the hello reference
]]></source>
</section>

<section name="Using an Image Object in the Context">
<p>
Creating an HTML link to an image from a template could be done by;
</p>

<source test=""><![CDATA[
   $link.getServerScheme()
   ://
   $link.getServerName()
   :
   $link.getServerPort()
   /context/imagename.jpg
]]></source>

<p>
This has been split up into multiple lines for clarity. Doing this once is a
pain, doing it twice stinks, if the screen requires several images .... and
there are many screens .... it is a productivity killer. The Velocity Context
can be used to store this information and expose it to all the Screens
requiring it. To do this we can create an Image Object which extends the Turbine
DynamicURI Object. The following class is Apache Tomcat specific;
</p>


<source test=""><![CDATA[
//Turbine
import org.apache.turbine.util.DynamicURI;
import org.apache.turbine.util.RunData;


public class Image extends DynamicURI
{

    /** The images directory */
    public static final String DIR = "images";

    /** tomcat specific - tomcat context */
    private String contextpath;

    /** Constructor */
    public Image (RunData data)
    {
        super(data);

        //the Tomcat context
        contextpath = data.getRequest().getContextPath();
    }

    /** set the image and URI */
    public String setImage(String imagename)
    {
        return (
        getServerScheme() + //http
        "://" +
        getServerName()  + //www.foo.com
        ":" +
        getServerPort() + //port webserver running on (8080 for TDK)

        //the context for tomcat adds a / so no need to add another

        contextpath  +  //the tomcat context
        "/" +
        Images.DIR +
        "/" +
        imagename);
    }
}
]]></source>

<p>
This can be instantiated from within the doBuildTemplate method in a Velocity
Screen and added to the context from there;
</p>

<source test=""><![CDATA[
    public void doBuildTemplate(RunData data, Context context) throws Exception
    {
        Image image = new Image(data);
        context.put("image",image);
    }
]]></source>

<p>
from this the Image Object is accessible from within the corresponding screen
template and can be accessed by;
</p>

<source test=""><![CDATA[
    $image.setImage("imagename.jpg");
]]></source>

<p>
Which is much simpler than the original attempt at dynamically creating an image
URL. To make this Image object accessible across all Screens, subclass the
VelocityScreen Object with one that overrides the doBuildTemplate() method by
adding the Image object to the Velocity Context. Then use this class as the
parent class for the Screens that need access to the Image Object. For more
detail on taking advantage and extending the VelocityScreen Object, please view
the <a href="../getting-started.html">Getting Started</a> Document.
</p>

<p>
The above Image Object can also be modified to include any static data required
by the templates. For instance CSS files, JavaScript files etc. Instead of an
Image Object, it can be rewritten as a StaticLink Object;
</p>

<source test=""><![CDATA[
//Turbine
import org.apache.turbine.util.DynamicURI;
import org.apache.turbine.util.RunData;


public class StaticLink extends DynamicURI
{

    /** the images directory */
    public static final String IMAGES = "images";

    /** the css directory */
    public static final String CSS = "css";

    // etc

    /** tomcat specific - tomcat context */
    private String contextpath;

    /** Constructor */
    public Image (RunData data)
    {
        super(data);

        //the Tomcat context
        contextpath = data.getRequest().getContextPath();
    }

    /** set the image and URI */
    public String setImage(String imagename)
    {
        //URI Logic
    }

    /** set the CSS style and URI*/
    public String setCss(String stylesheet)
    {
        //URI Logic
    }

    /** general set method, input as string
     *  ie can be set as $staticlink.setStaticLink("images/imagename")
     */
    public String setStaticLink(String staticlink)
    {
        //URI Logic
    }

}

]]></source>
</section>

<section name="Using the Context Object with the Base/Peer OM">
<p>
As a more complex example, assume we are building a book archive system,
where users can search for books by author and title. If we search on author
"Greg Egan" and title "Permutation City", we can query the database through the
base\peer system and return a Book Object that contains the information on the
book "Permutation City". The Book Object would be placed in the context via;
</p>

<source test=""><![CDATA[
    Book book = new Book();

    //add the data to the Book Object
    //from the Base/Peer Objects for Book

    context.put("book", book);

]]></source>

<p>
and then accessed in the velocity template by;
</p>

<source test=""><![CDATA[
    $book.getAuthor()
    $book.getTitle()
]]></source>

<p>
where the two methods are public methods in the Book Object, in this case built
by the <a href="http://db.apache.org/torque/">Torque</a>. These methods would return;
</p>

<source test=""><![CDATA[
    Greg Egan
    Permutation City
]]></source>

<p>
It is important not to try and put Objects with value null into the Context.
A NullPointerException will be returned. This above example is intended to get
across how the Velocity Context can be used to store data from the Base/Peer
system that can be accessed from the Templates.
</p>
</section>

</body>
</document>
