Author: henning
Date: Sat Aug 26 03:25:44 2006
New Revision: 437138
URL: http://svn.apache.org/viewvc?rev=437138&view=rev
Log:
Lots of work on the directives chapter during AC Asia.
Modified:
jakarta/velocity/docbook/trunk/src/docbook/userguide/VelocityUsersGuide.xml
Modified:
jakarta/velocity/docbook/trunk/src/docbook/userguide/VelocityUsersGuide.xml
URL:
http://svn.apache.org/viewvc/jakarta/velocity/docbook/trunk/src/docbook/userguide/VelocityUsersGuide.xml?rev=437138&r1=437137&r2=437138&view=diff
==============================================================================
--- jakarta/velocity/docbook/trunk/src/docbook/userguide/VelocityUsersGuide.xml
(original)
+++ jakarta/velocity/docbook/trunk/src/docbook/userguide/VelocityUsersGuide.xml
Sat Aug 26 03:25:44 2006
@@ -352,7 +352,11 @@
<para>A multi-line statement starts like a single-line statement, but
also has a statement body. This body ends with
- <literal>#end</literal>.</para>
+ <literal>#end</literal>.<footnote>
+ <para>Technically spoken, the opening statement and
+ <literal>#end</literal> can be on the same line. We will still call
+ it a multi-line statement.</para>
+ </footnote></para>
<example id="example-velocity-multi-line-statements">
<title>Velocity multi-line statements</title>
@@ -391,6 +395,12 @@
<para>All available Velocity directives are listed in the <link
linkend="chapter-directives">Directives chapter</link>.</para>
+
+ <note>
+ <para>While the hash sign is technically not part of the directive, we
+ will still speak about the <literal>#if</literal> or
+ <literal>#set</literal> directive in the latter chapters.</para>
+ </note>
</section>
<section id="section-reference">
@@ -891,7 +901,7 @@
notation. Even if a method is called
<literal>set<property>()</literal> or
<literal>get<property>()</literal>, it must still adhere to bean
- getter and setter method signatures. </para>
+ getter and setter method signatures.</para>
<example>
<title>Methods that can not be used with shorthand notation</title>
@@ -997,13 +1007,16 @@
of the template.</para>
<para>As described in Chapter 3.1, Velocity Directives are part of either
- single or multi-line statements.</para>
+ single or multi-line statements and are preceded by a hash sign
+ (<literal>#</literal>). While the hash sign is technically not part of the
+ directive, we will still speak about the <literal>#if</literal> or
+ <literal>#set</literal> directive.</para>
<section id="section-the-set-directive">
- <title>The <firstterm>set</firstterm> directive</title>
+ <title>The <literal>#set</literal> directive</title>
- <para>The <literal>set</literal> directive is used for setting the value
- of a reference. It is used in a single-line statement.</para>
+ <para>The <literal>#set</literal> directive is used for setting the
+ value of a reference. It is used in a single-line statement.</para>
<para>A value can be assigned to either a variable reference or a
property reference.</para>
@@ -1120,7 +1133,7 @@
not possible to assign a null value through a <literal>set</literal>
directive to a reference. Starting with Velocity 1.5, a runtime
property (<literal>directive.set.null.allowed</literal>) exists that
- removes this restriction. If you don't want <literal>null</literal>
+ removes this restriction. If you do not want <literal>null</literal>
values to be treated special, tell your application developers that
they should look up this property in the <emphasis>Velocity Developers
Guide</emphasis> and set it to true.</para>
@@ -1147,8 +1160,8 @@
is very different from the behaviour in e.g. the Java programming
language and needs some discussion.</para>
- <para>In the following example, two queries are executed using the
- same set of template references:</para>
+ <para>In the following piece of code, two queries are executed using
+ the same set of template references:</para>
<programlisting>#set( $result = $query.criteria("fruit") )
The result of the first query is $result
@@ -1158,7 +1171,7 @@
<para>If <literal>$query.criteria("name")</literal> returns the string
"apple", and <literal>$query.criteria("customer")</literal> returns
- null, the above VTL will render as the following:</para>
+ null, the above VTL will render as the follows:</para>
<programlisting>The result of the first query is apple
@@ -1166,12 +1179,13 @@
<para>In the second <literal>set</literal> directive, the RHS is null,
because <literal>$query.criteria("customer")</literal> returned null.
- So the RHS will not be modified (and the old value retained). </para>
+ So the RHS will not be modified (and the old value retained).</para>
<para>Unfortunately, this can lead to hard-to-detect errors, for
example with <literal>#foreach</literal> loops that attempt to change
- a reference using a <literal>set</literal> directive, then immediately
- test that reference with an <literal>if</literal> directive:</para>
+ a reference using a <literal>#set</literal> directive, then
+ immediately test that reference with an <literal>#if</literal>
+ directive:</para>
<programlisting>#set( $criteria = ["fruit", "customer"] )
@@ -1270,7 +1284,9 @@
<para>The <literal>#literal</literal> directive allows you to easily use
large chunks of uninterpreted content in VTL code. This can be
- especially useful in place of escaping multiple directives.</para>
+ especially useful in place of escaping multiple directives. #literal is
+ a multi-line statement and needs a #end directive to close the statement
+ body.</para>
<programlisting>#literal()
#foreach ($fruit in $basket)
@@ -1280,8 +1296,21 @@
<para>Renders as:</para>
- <programlisting>#foreach ($fruit in $basket) nothing will happen
- to $fruit #end</programlisting>
+ <programlisting>#foreach ($fruit in $basket)
+ nothing will happen to $fruit
+#end</programlisting>
+
+ <para>Even if the <literal>$fruit</literal> or
+ <literal>$basket</literal> references have a value assigned, the text
+ will still be output uninterpreted.</para>
+
+ <caution>
+ <para>While <literal>#literal()</literal> suppresses the evaluation of
+ Velocity directives and references at run-time, the body is still
+ parsed. <literal>#literal()</literal> is not a comment block, if you
+ have a syntax error (e.g. a missing <literal>#end</literal>) inside
+ the block, Velocity will still report a parse error.</para>
+ </caution>
</section>
<section id="section-conditionals">
@@ -1289,7 +1318,8 @@
<para>The <literal>#if</literal> directive in Velocity allows for text
to be included when the web page is generated, on the conditional that
- the <emphasis>if-statement</emphasis> is true. For example:</para>
+ the <emphasis>if-statement</emphasis> is true. Consider the following
+ piece of code:</para>
<programlisting>#if( $display )
<strong>Velocity!</strong>
@@ -1323,11 +1353,16 @@
<para>An <literal>#elseif</literal> or <literal>#else</literal> element
can be used with an <literal>#if</literal> element. Note that the
Velocity Templating Engine will stop at the first expression that is
- found to be true. In the following example, suppose that
- <literal>$direction</literal> has a value of 15 and
- <literal>$wind</literal> has a value of 6.</para>
+ found to be true:</para>
+
+ <example>
+ <title>Using #if/#elseif/#else to select multiple template
+ pieces</title>
- <programlisting>#if( $direction < 10 )
+ <programlisting>#set ($direction = 15)
+#set ($wind = 6)
+
+#if( $direction < 10 )
<strong>Go North</strong>
#elseif( $direction == 10 )
<strong>Go East</strong>
@@ -1336,6 +1371,7 @@
#else
<strong>Go West</strong>
#end</programlisting>
+ </example>
<para>In this example, <literal>$direction</literal> is greater than 10,
so the first two comparisons fail. Next <literal>$wind</literal> is
@@ -1348,231 +1384,76 @@
following text:</para>
<programlisting>#if( $foo == $bar)it's true!#{else}it's
not!#end</li></programlisting>
-
- <section id="section-relational-and-logical-operators">
- <title>Relational and Logical Operators</title>
-
- <para>Velocity uses operators to determine the relationships between
- variables.</para>
-
- <table id="table-velocity-relational-and-logical-operators">
- <title>Velocity Relational and logical operators</title>
-
- <tgroup cols="3">
- <thead>
- <row>
- <entry align="center">Type of operator</entry>
-
- <entry align="center">short version</entry>
-
- <entry>text version</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>equal<footnote>
- <para>Note that the semantics of the equal operator are
- slightly different than Java where<literal>==</literal>
- can only be used to test object equality. In Velocity the
- equivalent operator can be used to directly compare
- numbers, strings, or objects. When the objects are of
- different classes, the string representations are obtained
- by calling <literal>toString()</literal> for each object
- and then compared.</para>
- </footnote></entry>
-
- <entry>==</entry>
-
- <entry>eq</entry>
- </row>
-
- <row>
- <entry>not equal</entry>
-
- <entry>!=</entry>
-
- <entry>ne</entry>
- </row>
-
- <row>
- <entry>greater than</entry>
-
- <entry>></entry>
-
- <entry>gt</entry>
- </row>
-
- <row>
- <entry>greater or equal than</entry>
-
- <entry>>=</entry>
-
- <entry>ge</entry>
- </row>
-
- <row>
- <entry>less than</entry>
-
- <entry><</entry>
-
- <entry>lt</entry>
- </row>
-
- <row>
- <entry>less or equal than</entry>
-
- <entry><=</entry>
-
- <entry>le</entry>
- </row>
-
- <row>
- <entry>logical and</entry>
-
- <entry>&&</entry>
-
- <entry>and</entry>
- </row>
-
- <row>
- <entry>logical or</entry>
-
- <entry>||</entry>
-
- <entry>or</entry>
- </row>
-
- <row>
- <entry>logical not</entry>
-
- <entry>!</entry>
-
- <entry>not</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Here is a simple example to illustrate how the equivalent
- operator is used.</para>
-
- <programlisting>#set ($foo = "deoxyribonucleic acid")
-#set ($bar = "ribonucleic acid")
-
-#if ($foo == $bar)
- In this case it's clear they aren't equivalent. So...
-#else
- They are not equivalent and this will be the output.
-#end</programlisting>
-
- <para>The text versions of all logical operators can be used to avoid
- problems with < and > in XML templates.</para>
- </section>
-
- <section id="section-the-and-operator">
- <title>The AND Operator</title>
-
- <programlisting>## logical AND
-
-#if( $foo && $bar )
- <strong>This AND that</strong>
-#end</programlisting>
-
- <para>The <literal>#if()</literal> directive will only evaluate to
- true if both <literal>$foo</literal> and <literal>$bar</literal> are
- true. If <literal>$foo</literal> is false, the expression will
- evaluate to false; <literal>$bar</literal> will not be evaluated. If
- <literal>$foo</literal> is true, the Velocity Templating Engine will
- then check the value of <literal>$bar</literal>; if
- <literal>$bar</literal> is true, then the entire expression is true
- and This AND that becomes the output. If <literal>$bar</literal> is
- false, then there will be no output as the entire expression is
- false.</para>
- </section>
-
- <section id="the-or-operator">
- <title>The OR Operator</title>
-
- <para>Logical OR operators work the same way as AND operators, except
- only one of the references need evaluate to true in order for the
- entire expression to be considered true. Consider the following
- example:</para>
-
- <programlisting>## logical OR
-
-#if( $foo || $bar )
- <strong>This OR That</strong>
-#end</programlisting>
-
- <para>If <literal>$foo</literal> is true, the Velocity Templating
- Engine has no need to look at <literal>$bar</literal>; whether
- <literal>$bar</literal> is true or false, the expression will be true,
- and This OR That will be output. If <literal>$foo</literal> is false,
- however, <literal>$bar</literal> must be checked. In this case, if
- <literal>$bar</literal> is also false, the expression evaluates to
- false and there is no output. On the other hand, if
- <literal>$bar</literal> is true, then the entire expression is true,
- and the output is This OR That</para>
- </section>
-
- <section id="the-not-operator">
- <title>The NOT Operator</title>
-
- <para>With logical NOT operators, there is only one argument:</para>
-
- <programlisting>##logical NOT
-
-#if( !$foo )
- <strong>NOT that</strong>
-#end</programlisting>
-
- <para>Here, the if <literal>$foo</literal> is true, then
- <literal>!$foo</literal> evaluates to false, and there is no output.
- If <literal>$foo</literal> is false, then <literal>!$foo</literal>
- evaluates to true and <computeroutput>NOT that</computeroutput> will
- be output. Be careful not to confuse this with the <emphasis>quiet
- reference </emphasis><literal>$!foo</literal>.</para>
- </section>
</section>
<section id="loops">
<title>Loops - #foreach</title>
- <para>The <literal>#foreach</literal> element allows for looping:</para>
+ <para><literal>#foreach</literal> iterates over the elements given in a
+ List or Array element.</para>
- <programlisting><ul>
+ <example>
+ <title>foreach loop example</title>
+
+ <programlisting><ul>
#foreach( $product in $allProducts )
<li>$product</li>
#end
</ul></programlisting>
+ </example>
- <para>This <literal>#foreach</literal> loop causes the
- <literal>$allProducts</literal> list (the object) to be looped over for
- all of the products (targets) in the list. Each time through the loop,
- the value from <literal>$allProducts</literal> is placed into the
- <literal>$product</literal> variable.</para>
-
- <para>The contents of the <literal>$allProducts</literal> variable is a
- Vector, a Hashtable or an Array. The value assigned to the
- <literal>$product</literal> variable is a Java Object and can be
- referenced from a variable as such. For example, if
- <literal>$product</literal> was really a Product class in Java, its name
- could be retrieved by referencing the <literal>$product.Name</literal>
- method (ie: <literal>$Product.getName()</literal>).</para>
-
- <para>Lets say that <literal>$allProducts</literal> is a Hashtable. If
- you wanted to retrieve the key values for the Hashtable as well as the
- objects within the Hashtable, you can use code like this:</para>
-
- <programlisting><ul>
- #foreach( $key in $allProducts.keySet() )
- <li>Key: $key -> Value: $allProducts.get($key)</li>
- #end
-</ul></programlisting>
+ <para>Unlike other languages, the Velocity templating language allows
+ only loops where the number of iterations is predetermined. There is no
+ <literal>do..while</literal> or <literal>repeat..until</literal> loop in
+ Velocity. This has been a conscious decision to make sure that the
+ rendering process of Velocity does always terminate.<footnote>
+ <para>It is stil possible to write a template that contains endless
+ loops. It is just harder.</para>
+ </footnote></para>
- <para>Velocity provides an easy way to get the loop counter so that you
- can do something like the following:</para>
+ <para>A VTL foreach loop takes two arguments, the first one is the
+ <firstterm>loop variable</firstterm> and the second is an object that
+ can be iterated over. Velocity supports a number of object types in its
+ default configuration:<footnote>
+ <para>The list of objects can be changed and extended, please see
+ the Developers guide on how to do this.</para>
+ </footnote><itemizedlist>
+ <listitem>
+ <para>Any array type</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>java.lang.Collection</literal> The loop iterates
+ over the Iterator returned by obj.iterator()</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>java.lang.Map</literal> The loop will iterate over
+ the values of the Map using the iterator returned by
+ values().iterator()</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>java.lang.Iterator</literal> Velocity uses this
+ iterator directly</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>java.lang.Enumeration</literal> Velocity wrapping
+ the Enumeration into an Iterator</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <warning>
+ <para>Using an Iterator or Enumeration object directly in a template
+ has the side effect that the loop cannot be evaluated multiple times
+ because the loop consumes the object that gets iterated. Be especially
+ careful if you use such an object inside a Macro or an included
+ template.</para>
+ </warning>
+
+ <para>Velocity provides you with a loop counter reference which contains
+ the number of the current iteration of the loop:</para>
<programlisting><table>
#foreach( $customer in $customerList )
@@ -1580,11 +1461,9 @@
#end
</table></programlisting>
- <para>The default name for the loop counter variable reference, which is
- specified in the velocity.properties file, is
- <literal>$velocityCount</literal>. By default the counter starts at 1.
- Both, the start value and the variable name can be changed through
- properties in the Velocity configuration:</para>
+ <para>The default name for the loop counter and its starting value is
+ specified through runtime properties. By default it starts at 1 and is
+ called <literal>$velocityCount</literal>.</para>
<programlisting># Default name of the loop counter
# variable reference.
@@ -1594,8 +1473,33 @@
# counter variable reference.
directive.foreach.counter.initial.value = 1</programlisting>
- <para>To avoid deadlocks and denial of service attacks, it's possible to
- set a maximum allowed number of times that a loop may be executed. By
+ <para>The Velocity loop counter variable does support nested loops, so
+ the following example would work as expected:</para>
+
+ <example>
+ <title>Nested Loops and the loop counter</title>
+
+ <programlisting>#foreach ($category in $allCategories)
+ Category # $velocityCount is $category
+
+ #foreach ($item in $allItems)
+ Item # $velocitycount is $item
+ #end
+
+#end</programlisting>
+ </example>
+
+ <para>The loop counter is local to its surrounding loop and any inner
+ loops hides but not resets it. Please note that it is not possible to
+ access the count variable of the outer loop directly inside the inner
+ loop.<footnote>
+ <para>You can assign its value to another variable before entering
+ the inner loop using <literal>#set</literal> and access it through
+ this variable inside the inner loop.</para>
+ </footnote></para>
+
+ <para>To avoid deadlocks and denial of service attacks, it is possible
+ to set a maximum allowed number of times that a loop may be executed. By
default there is no limit, but it can be set to an arbitrary number in
the Velocity configuration.</para>
@@ -1606,6 +1510,16 @@
<section id="section-loading-resources">
<title>Loading resources</title>
+ <para>In Velocity just as in other rendering techniques like JSP it is
+ important to build output from multiple input files. For this, you need
+ to be able to pull external resources into the rendering process.</para>
+
+ <para>Velocity supports the loading of external files by the #include
+ and #parse directive, which both load external resources into the
+ rendering process of a template.</para>
+
+ <para>Velocity does not allow you to </para>
+
<section id="section-file-inclusion">
<title>File inclusion - #include</title>
@@ -1711,6 +1625,190 @@
<para>Unlike most other directives, <literal>#stop</literal> has no
matching <literal>#end</literal> directive.</para>
+ </section>
+ </chapter>
+
+ <chapter id="section-relational-and-logical-operators">
+ <title>Relational and Logical Operators</title>
+
+ <para>Velocity uses operators to determine the relationships between
+ variables.</para>
+
+ <table id="table-velocity-relational-and-logical-operators">
+ <title>Velocity Relational and logical operators</title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry align="center">Type of operator</entry>
+
+ <entry align="center">short version</entry>
+
+ <entry>text version</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>equal<footnote>
+ <para>Note that the semantics of the equal operator are
+ slightly different than Java where<literal>==</literal> can
+ only be used to test object equality. In Velocity the
+ equivalent operator can be used to directly compare numbers,
+ strings, or objects. When the objects are of different
+ classes, the string representations are obtained by calling
+ <literal>toString()</literal> for each object and then
+ compared.</para>
+ </footnote></entry>
+
+ <entry>==</entry>
+
+ <entry>eq</entry>
+ </row>
+
+ <row>
+ <entry>not equal</entry>
+
+ <entry>!=</entry>
+
+ <entry>ne</entry>
+ </row>
+
+ <row>
+ <entry>greater than</entry>
+
+ <entry>></entry>
+
+ <entry>gt</entry>
+ </row>
+
+ <row>
+ <entry>greater or equal than</entry>
+
+ <entry>>=</entry>
+
+ <entry>ge</entry>
+ </row>
+
+ <row>
+ <entry>less than</entry>
+
+ <entry><</entry>
+
+ <entry>lt</entry>
+ </row>
+
+ <row>
+ <entry>less or equal than</entry>
+
+ <entry><=</entry>
+
+ <entry>le</entry>
+ </row>
+
+ <row>
+ <entry>logical and</entry>
+
+ <entry>&&</entry>
+
+ <entry>and</entry>
+ </row>
+
+ <row>
+ <entry>logical or</entry>
+
+ <entry>||</entry>
+
+ <entry>or</entry>
+ </row>
+
+ <row>
+ <entry>logical not</entry>
+
+ <entry>!</entry>
+
+ <entry>not</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>Here is a simple example to illustrate how the equivalent operator
+ is used.</para>
+
+ <programlisting>#set ($foo = "deoxyribonucleic acid")
+#set ($bar = "ribonucleic acid")
+
+#if ($foo == $bar)
+ In this case it's clear they aren't equivalent. So...
+#else
+ They are not equivalent and this will be the output.
+#end</programlisting>
+
+ <para>The text versions of all logical operators can be used to avoid
+ problems with < and > in XML templates.</para>
+
+ <section id="section-the-and-operator">
+ <title>The AND Operator</title>
+
+ <programlisting>## logical AND
+
+#if( $foo && $bar )
+ <strong>This AND that</strong>
+#end</programlisting>
+
+ <para>The <literal>#if()</literal> directive will only evaluate to true
+ if both <literal>$foo</literal> and <literal>$bar</literal> are true. If
+ <literal>$foo</literal> is false, the expression will evaluate to false;
+ <literal>$bar</literal> will not be evaluated. If
+ <literal>$foo</literal> is true, the Velocity Templating Engine will
+ then check the value of <literal>$bar</literal>; if
+ <literal>$bar</literal> is true, then the entire expression is true and
+ This AND that becomes the output. If <literal>$bar</literal> is false,
+ then there will be no output as the entire expression is false.</para>
+ </section>
+
+ <section id="the-or-operator">
+ <title>The OR Operator</title>
+
+ <para>Logical OR operators work the same way as AND operators, except
+ only one of the references need evaluate to true in order for the entire
+ expression to be considered true. Consider the following example:</para>
+
+ <programlisting>## logical OR
+
+#if( $foo || $bar )
+ <strong>This OR That</strong>
+#end</programlisting>
+
+ <para>If <literal>$foo</literal> is true, the Velocity Templating Engine
+ has no need to look at <literal>$bar</literal>; whether
+ <literal>$bar</literal> is true or false, the expression will be true,
+ and This OR That will be output. If <literal>$foo</literal> is false,
+ however, <literal>$bar</literal> must be checked. In this case, if
+ <literal>$bar</literal> is also false, the expression evaluates to false
+ and there is no output. On the other hand, if <literal>$bar</literal> is
+ true, then the entire expression is true, and the output is This OR
+ That</para>
+ </section>
+
+ <section id="the-not-operator">
+ <title>The NOT Operator</title>
+
+ <para>With logical NOT operators, there is only one argument:</para>
+
+ <programlisting>##logical NOT
+
+#if( !$foo )
+ <strong>NOT that</strong>
+#end</programlisting>
+
+ <para>Here, the if <literal>$foo</literal> is true, then
+ <literal>!$foo</literal> evaluates to false, and there is no output. If
+ <literal>$foo</literal> is false, then <literal>!$foo</literal>
+ evaluates to true and <computeroutput>NOT that</computeroutput> will be
+ output. Be careful not to confuse this with the <emphasis>quiet
+ reference </emphasis><literal>$!foo</literal>.</para>
</section>
</chapter>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]