Author: buildbot
Date: Sat Feb 17 11:21:05 2018
New Revision: 1025500
Log:
Production update by buildbot for tapestry
Modified:
websites/production/tapestry/content/cache/main.pageCache
websites/production/tapestry/content/component-templates.html
websites/production/tapestry/content/property-expressions.html
Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.
Modified: websites/production/tapestry/content/component-templates.html
==============================================================================
--- websites/production/tapestry/content/component-templates.html (original)
+++ websites/production/tapestry/content/component-templates.html Sat Feb 17
11:21:05 2018
@@ -171,12 +171,12 @@
</div>
-<p>Under Tapestry, a <strong>component template</strong> is a file that
contains the markup for a component.</p><p>Component templates are <em>well
formed XML documents</em>. That means that every open tag must have a matching
close tag, every attribute must be quoted, and so forth.</p><p><em>Note: At
runtime, Tapestry parses the documents and only checks for wellformedness. Even
when the document has a DTD or schema, there are no validity
checks.</em></p><p>For the most part, these templates are standard HTML/XHTML;
Tapestry extensions to ordinary markup are provided in the form of a Tapestry
namespace:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>A
template for a page</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html t:type="layout"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
+<p>Under Tapestry, a <strong>component template</strong> is a file that
contains the markup for a component.</p><p>Component templates are <em>well
formed XML documents</em>. That means that every open tag must have a matching
close tag, every attribute must be quoted, and so forth.</p><p><em>Note: At
runtime, Tapestry parses the documents and only checks for wellformedness. Even
when the document has a DTD or schema, there are no validity
checks.</em></p><p>For the most part, these templates are standard HTML/XHTML;
Tapestry extensions to ordinary markup are provided in the form of a Tapestry
XML namespace (xmlns):</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>A template for a page</b></div><div class="codeContent panelContent
pdl">
+<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html t:type="layout"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<h1>Bonjour from HelloWorld component.</h1>
</html>
</pre>
-</div></div><div class="sectionMacro"><div
class="sectionMacroRow"> </div></div><p>We'll cover the specific content
of templates shortly, but first a few details about connecting a component to
its template.</p><h2 id="ComponentTemplates-TemplateLocation">Template
Location</h2><p>A component template shares the same name as its corresponding
class file, but with a ".tml" ending (i.e., <strong>T</strong>apestry
<strong>M</strong>arkup <strong>L</strong>anguage), and is stored in the same
package as the corresponding component class.</p><p>Under a typical Maven
directory structure, the Java class and template files for a <em>component</em>
might be:</p><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p><strong>Java class:</strong></p></td><td colspan="1"
rowspan="1"
class="confluenceTd"><p><code>src/main/java/org/example/myapp/components/MyComponent.java</code></p></td></tr><tr><td
colspan="1" rowspan="1" class="c
onfluenceTd"><p><strong>Template:</strong></p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p><code>src/main/resources/org/example/myapp/components/MyComponent.tml</code></p></td></tr></tbody></table></div><p>Likewise,
the Java class and template files for a <em>page</em> might be:</p><div
class="table-wrap"><table class="confluenceTable"><tbody><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p><strong>Java class:</strong></p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><code>src/main/java/org/example/myapp/pages/MyPage.java</code></p></td></tr><tr><td
colspan="1" rowspan="1"
class="confluenceTd"><p><strong>Template:</strong></p></td><td colspan="1"
rowspan="1"
class="confluenceTd"><p><code>src/main/resources/org/example/myapp/pages/MyPage.tml</code></p></td></tr></tbody></table></div><p>The
template and the compiled class will be packaged together in the
WEB-INF/classes folder of the application WAR.</p><p>For <em>pages</em> (but
not other components), a
second location will be searched: in the web application context. The location
is based on the logical name of the page, in the previous example, the template
would be <code>MyPage.tml</code> in the root folder of the web
application.</p><p>A template on the classpath takes precedence over a file in
the web application context.</p><div class="confluence-information-macro
confluence-information-macro-warning"><span class="aui-icon aui-icon-small
aui-iconfont-error confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>Allowing pages to store their
template in the web context is a feature that may go away at some point. It was
included as a way for HTML designers to edit template directly and live preview
the template directly, without executing the Tapestry application. This comes
with a large number of limitations and leads to a false sense of security that
a template that previews correctly will render properly (this is not always the
case).</p>
</div></div><h2 id="ComponentTemplates-TemplateLocalization">Template
Localization</h2><p>Main Article: <a
href="localization.html">Localization</a></p><p>Templates are handled in much
the same way as individual files of a component's message catalog: the
effective locale is inserted into the name of the file. Thus a German users
will see the content generated from <code>MyPage_de.tml</code> and French users
will see content generated from <code>MyPage_fr.tml</code>. When no specific
localization is available, the default location (<code>MyPage.tml</code>) is
used.</p><div class="confluence-information-macro
confluence-information-macro-information"><span class="aui-icon aui-icon-small
aui-iconfont-info confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>It is necessary to <a
href="configuration.html">enable support for a locale</a></p><p>before Tapestry
will attempt to localize to that locale. This requires configuration in your
application
module (usually AppModule.java); if you are using the Tapestry Quickstart
archetype, only locale "en" will be enabled by default.</p></div></div><p><span
class="confluence-anchor-link" id="ComponentTemplates-doctypes"></span></p><h2
id="ComponentTemplates-TemplateDoctypes">Template Doctypes</h2><p>As mentioned
above, component templates are well-formed XML documents. This means that if
you want to use any <a class="external-link"
href="http://www.w3.org/TR/html401/sgml/entities.html" rel="nofollow">Named
HTML entities</a> (such as &amp; &lt; &gt; &copy;), you must
use an <a class="external-link"
href="http://www.w3.org/QA/2002/04/valid-dtd-list.html" rel="nofollow">HTML or
XHTML doctype</a> in your template <em>(starting in 5.3, this is more-or-less
automatic, see notes below)</em>. If you choose to use (X)HTML doctypes in your
templates, they will be passed on to the client in the resultant (X)HTML. Note
that if your pages are composed of multiple components, eac
h with a template, and each template contains a doctype declaration, only the
first doctype encountered by the template parser will be passed on to the
client.</p><p>It should also be noted that even though <strong>X</strong>HTML
DTDs are valid XML DTDs, HTML DTDs aren't. This means that HTML doctypes cannot
be used by XML parsers. Tapestry works around this limitation internally by
using XHTML DTDs to parse templates that use HTML DTDs. This internal mapping
is possible because XHTML 1.0 is nothing more than "a reformulation of the
three HTML 4 document types as applications of XML 1.0," <a
class="external-link" href="http://www.w3.org/TR/xhtml1/#xhtml"
rel="nofollow">as per the W3C</a>. Don't worry though – the original HTML
4 doctype will still be emitted to the client!</p><p>The following are the most
common (X)HTML doctypes:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
+</div></div><p>We'll cover the specific content of templates shortly, but
first a few details about connecting a component to its template.</p><h2
id="ComponentTemplates-TemplateLocation">Template Location</h2><p>A component
template shares the same name as its corresponding class file, but with a
".tml" ending (i.e., <strong>T</strong>apestry <strong>M</strong>arkup
<strong>L</strong>anguage), and is stored in the same package as the
corresponding component class.</p><p>Under a typical Maven directory structure,
the Java class and template files for a <em>component</em> might be:</p><div
class="table-wrap"><table class="confluenceTable"><tbody><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p><strong>Java class:</strong></p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><code>src/main/java/org/example/myapp/components/MyComponent.java</code></p></td></tr><tr><td
colspan="1" rowspan="1"
class="confluenceTd"><p><strong>Template:</strong></p></td><td colspan="1"
rowspa
n="1"
class="confluenceTd"><p><code>src/main/resources/org/example/myapp/components/MyComponent.tml</code></p></td></tr></tbody></table></div><p>Likewise,
the Java class and template files for a <em>page</em> might be:</p><div
class="table-wrap"><table class="confluenceTable"><tbody><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p><strong>Java class:</strong></p></td><td
colspan="1" rowspan="1"
class="confluenceTd"><p><code>src/main/java/org/example/myapp/pages/MyPage.java</code></p></td></tr><tr><td
colspan="1" rowspan="1"
class="confluenceTd"><p><strong>Template:</strong></p></td><td colspan="1"
rowspan="1"
class="confluenceTd"><p><code>src/main/resources/org/example/myapp/pages/MyPage.tml</code></p></td></tr></tbody></table></div><p>The
template and the compiled class will be packaged together in the
WEB-INF/classes folder of the application WAR.</p><p>For <em>pages</em> (but
not other components), a second location will be searched: in the web
application context. The loc
ation is based on the logical name of the page, in the previous example, the
template would be <code>MyPage.tml</code> in the root folder of the web
application.</p><p>A template on the classpath takes precedence over a file in
the web application context.</p><div class="confluence-information-macro
confluence-information-macro-warning"><span class="aui-icon aui-icon-small
aui-iconfont-error confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>Allowing pages to store their
template in the web context is a feature that may go away at some point. It was
included as a way for HTML designers to edit template directly and live preview
the template directly, without executing the Tapestry application. This comes
with a large number of limitations and leads to a false sense of security that
a template that previews correctly will render properly (this is not always the
case).</p></div></div><h2 id="ComponentTemplates-TemplateLocalization">Template
Loc
alization</h2><p>Main Article: <a
href="localization.html">Localization</a></p><p>Templates are handled in much
the same way as individual files of a component's message catalog: the
effective locale is inserted into the name of the file. Thus a German users
will see the content generated from <code>MyPage_de.tml</code> and French users
will see content generated from <code>MyPage_fr.tml</code>. When no specific
localization is available, the default location (<code>MyPage.tml</code>) is
used.</p><div class="confluence-information-macro
confluence-information-macro-information"><span class="aui-icon aui-icon-small
aui-iconfont-info confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>It is necessary to <a
href="configuration.html">enable support for a locale</a></p><p>before Tapestry
will attempt to localize to that locale. This requires configuration in your
application module (usually AppModule.java); if you are using the Tapestry
Quickstar
t archetype, only locale "en" will be enabled by
default.</p></div></div><p><span class="confluence-anchor-link"
id="ComponentTemplates-doctypes"></span></p><h2
id="ComponentTemplates-TemplateDoctypes">Template Doctypes</h2><p>As mentioned
above, component templates are well-formed XML documents. This means that if
you want to use any <a class="external-link"
href="http://www.w3.org/TR/html401/sgml/entities.html" rel="nofollow">Named
HTML entities</a> (such as &amp; &lt; &gt; &copy;), you must
use an <a class="external-link"
href="http://www.w3.org/QA/2002/04/valid-dtd-list.html" rel="nofollow">HTML or
XHTML doctype</a> in your template <em>(starting in 5.3, this is more-or-less
automatic, see notes below)</em>. If you choose to use (X)HTML doctypes in your
templates, they will be passed on to the client in the resultant (X)HTML. Note
that if your pages are composed of multiple components, each with a template,
and each template contains a doctype declaration, only
the first doctype encountered by the template parser will be passed on to the
client.</p><p>It should also be noted that even though <strong>X</strong>HTML
DTDs are valid XML DTDs, HTML DTDs aren't. This means that HTML doctypes cannot
be used by XML parsers. Tapestry works around this limitation internally by
using XHTML DTDs to parse templates that use HTML DTDs. This internal mapping
is possible because XHTML 1.0 is nothing more than "a reformulation of the
three HTML 4 document types as applications of XML 1.0," <a
class="external-link" href="http://www.w3.org/TR/xhtml1/#xhtml"
rel="nofollow">as per the W3C</a>. Don't worry though – the original HTML
4 doctype will still be emitted to the client!</p><p>The following are the most
common (X)HTML doctypes:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"><!DOCTYPE html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
Modified: websites/production/tapestry/content/property-expressions.html
==============================================================================
--- websites/production/tapestry/content/property-expressions.html (original)
+++ websites/production/tapestry/content/property-expressions.html Sat Feb 17
11:21:05 2018
@@ -67,7 +67,7 @@
</div>
<div id="content">
- <div id="ConfluenceContent"><p>Tapestry uses <strong>property
expressions</strong> to move data between components. Property expressions are
the basis of the <a href="property-expressions.html">component parameters</a>
and <a href="component-templates.html">template expansions</a>.</p><div
class="aui-label" style="float:right" title="Related Articles">
+ <div id="ConfluenceContent"><p>Tapestry uses <strong>property
expressions</strong> to move data between components. Property expressions are
the basis of the <a href="component-parameters.html">component parameters</a>
and <a href="component-templates.html">template expansions</a>.</p><div
class="aui-label" style="float:right" title="Related Articles">
@@ -100,7 +100,7 @@
</div>
-<p>A property expression is a string that explains to Tapestry how to navigate
from a root object (the containing component) through some number of
properties, to a final property that can be read or updated. In fact, that's a
simplification, as the properties may actually be public fields, or even method
invocations.</p><p>As elsewhere in Tapestry, the names of fields, properties,
and methods are recognized in a case-insensitive manner.</p><p>The most basic
form of a property expression is a simple property name, such as
"userName".</p><p>A series of property names may be specified, separated by
periods: "user.name", which is equivalent to either
<code>getUser().getName()</code> or <code>getUser().setName()</code>, depending
on context (whether the expression is being read or updated).</p><p>The "<span
style="color: rgb(255,0,0);"><strong>.</strong></span>" is called the
"dereference operator". In addition, there is a a "safe dereference operator",
"<span style="color: rgb(255,0,0)
;">?.</span>", which  works the same as "<span style="color:
rgb(255,0,0);">.</span>" except that it allows any of the properties to be
null. When reading, a null short-circuits the expression (which returns null).
When writing to a property, an intermediate null value will cause the value to
be discarded without error.</p><p>In other words, "user<span style="color:
rgb(255,0,0);">?.</span>name" works, even when the <code>user</code> property
may be null.</p><p>Property expressions can also reference public methods.
Methods may take parameters (or not), but must not return void. When the final
term in a property expression is a method, then the property expression is
read-only.</p><p>Being able to invoke methods was originally added so that it
was possible to access methods such as <code>java.util.Map.size()</code> (which
is not named like a property getter method). In Tapestry 5.1, property
expressions were extended so that parameters could be passed into
methods.</p><p>Parame
ters to methods are, themselves, property expressions. This means that you can
write a property expression that reads a property and passes it as a parameter
to a method, and then access a property of the object returned from the
method.</p><h2 id="PropertyExpressions-Compilation">Compilation</h2><p>Property
expressions are compiled to Java classes at runtime; there is no runtime
reflection (unlike the OGNL expression language used in prior releases of
Tapestry).</p><h2 id="PropertyExpressions-Grammar">Grammar</h2><p>Expressed in
simplified <a class="external-link"
href="http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form"
rel="nofollow">Backus–Naur Form</a>, the grammar of property expressions
is as follows:</p><div class="preformatted panel" style="border-width:
1px;"><div class="preformattedContent panelContent">
+<p>A property expression is a string that explains to Tapestry how to navigate
from a root object (the containing component) through some number of
properties, to a final property that can be read or updated. In fact, that's a
simplification, as the properties may actually be public fields, or even method
invocations.</p><p>As elsewhere in Tapestry, the names of fields, properties,
and methods are recognized in a case-insensitive manner.</p><p>The most basic
form of a property expression is a simple property name, such as
"userName".</p><p>A series of property names may be specified, separated by
periods: "<code>user.name</code>", which is equivalent to either
<code>getUser().getName()</code> or <code>getUser().setName()</code>, depending
on context (whether the expression is being read or updated).</p><p>The
"<strong><span style="color: rgb(255,0,0);">.</span></strong>" is called the
"dereference operator". In addition, there is a a "safe dereference operator",
"<strong><span style
="color: rgb(255,0,0);">?.</span></strong>", which  works the same as
"<strong><span style="color: rgb(255,0,0);">.</span></strong>" except that it
allows any of the properties to be null. When reading, a null short-circuits
the expression (which returns null). When writing to a property, an
intermediate null value will cause the value to be discarded without
error.</p><p>In other words, "user<strong><span style="color:
rgb(255,0,0);">?.</span></strong>name" works, even when the <code>user</code>
property may be null.</p><p>Property expressions can also reference public
methods. Methods may take parameters (or not), but must not return void. When
the final term in a property expression is a method, then the property
expression is read-only.</p><p>Being able to invoke methods was originally
added so that it was possible to access methods such as
<code>java.util.Map.size()</code> (which is not named like a property getter
method). In Tapestry 5.1, property expressions were extend
ed so that parameters could be passed into methods.</p><p>Parameters to
methods are, themselves, property expressions. This means that you can write a
property expression that reads a property and passes it as a parameter to a
method, and then access a property of the object returned from the
method.</p><h2 id="PropertyExpressions-Compilation">Compilation</h2><p>Property
expressions are compiled to Java classes at runtime; there is no runtime
reflection (unlike the OGNL expression language used in Tapestry 4 and
earlier).</p><h2 id="PropertyExpressions-Grammar">Grammar</h2><p>Expressed in
simplified <a class="external-link"
href="http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form"
rel="nofollow">Backus–Naur Form</a>, the grammar of property expressions
is as follows:</p><div class="preformatted panel" style="border-width:
1px;"><div class="preformattedContent panelContent">
<pre>expression : keyword | rangeOp | constant | propertyChain | list | notOp
| map;
keyword : 'null' | 'this';
@@ -140,7 +140,7 @@ mapKey : keyword | constant | propertyCh
</p><div class="aui-message aui-message-info">
Added in 5.3
Support for map literals was added in Tapestry 5.3.
-</div>Notes:<ul><li>Whitespace is ignored.</li><li>Integers and decimals may
have a leading sign ('+' or '-').</li><li>Constants are in base 10 (octal and
hex notation is not yet supported). Decimals may contain a decimal point
(exponent notation not yet supported).</li><li>Literal strings are enclosed in
single quotes.</li><li>The <code>rangeOp</code> creates a range object that
will iterate between the two values. The upper and lower bounds may be literal
integers, or property expressions.</li><li>An identifier by itself is a
property name. An identifier with parenthesis is a method
invocation.</li><li>Property names, method names, and keywords are
case-insensitive.</li><li>'this' is the root object (i.e., the containing
component).</li><li>The <code>not</code> operator coerces the expression to a
<code>boolean</code> (so it can be used on strings, numbers,
etc.).</li><li>Method matching is based on method name and number of
parameters, but not parameter types. The <a href="prope
rty-expressions.html">TypeCoercer</a> service is used to convert parameters to
the correct type to be passed into the method.</li></ul><h2
id="PropertyExpressions-Examples">Examples</h2><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p> </p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Example</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Notes</p></th></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Keyword</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>this</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p> </p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Keyword</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>null</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p> </p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Property Name</p></th><td colspan="1" rowspan="1"
class="confluen
ceTd"><p>userName</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>Calls getUserName() or setUserName, depending on
context</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Property Chain</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>user.address.city</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>Calls getUser().getAddress().getCity() or
getUser().getAddress().setCity(), depending on context</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Property Chain</p></th><td
colspan="1" rowspan="1" class="confluenceTd"><p>user?.name</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p>Calls getUser() and, if the
result is not null, calls getName() on the result</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Method Invocation</p></th><td
colspan="1" rowspan="1" class="confluenceTd"><p>groupList.size()</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p>calls getGroupList().size(
)</p></td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Method
Invocation</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>members.findById(<a class="external-link"
href="http://user.id" rel="nofollow">user.id</a>)?.name</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>Calls
getMembers().findById(getUser().getId())?.getName() (unless findById returns
null)</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Range</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>1..10</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>Iterates between integers 1 and 10</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Range</p></th><td colspan="1"
rowspan="1" class="confluenceTd"><p>1..groupList.size()</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>Iterates between 1 and the result of
getGroupList().size()</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Literal String</p></t
h><td colspan="1" rowspan="1" class="confluenceTd"><p>'Beer is proof that God
loves us and wants us to be happy.'</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>Use single quotes</p></td></tr><tr><th colspan="1"
rowspan="1" class="confluenceTh"><p>List</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>[<a class="external-link" href="http://user.name"
rel="nofollow">user.name</a>, user.email, user.phone]</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p> </p></td></tr><tr><th colspan="1"
rowspan="1" class="confluenceTh"><p>Not Operator</p></th><td colspan="1"
rowspan="1" class="confluenceTd"><p>! user.deleted</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>the boolean negation of
getUser().getDeleted()</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Not, Coerced</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>! user.middleName</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>true only if ge
tUser.getMiddleName() returns null or an empty string</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Map</p></th><td colspan="1"
rowspan="1" class="confluenceTd"><p>{ 'framework' : 'Tapestry', 'version' :
version }</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Keys are
string literals (in single quotes), but could be properties as
well</p></td></tr></tbody></table></div></div>
+</div>Notes:<ul><li>Whitespace is ignored.</li><li>Integers and decimals may
have a leading sign ('+' or '-').</li><li>Constants are in base 10 (octal and
hex notation is not yet supported). Decimals may contain a decimal point
(exponent notation not yet supported).</li><li>Literal strings are enclosed in
single quotes.</li><li>The <code>rangeOp</code> creates a range object that
will iterate between the two values. The upper and lower bounds may be literal
integers, or property expressions.</li><li>An identifier by itself is a
property name. An identifier with parenthesis is a method
invocation.</li><li>Property names, method names, and keywords are
case-insensitive.</li><li>'this' is the root object (i.e., the containing
component).</li><li>The <code>not</code> operator coerces the expression to a
<code>boolean</code> (so it can be used on strings, numbers,
etc.).</li><li>Method matching is based on method name and number of
parameters, but not parameter types. The <a href="type-
coercion.html">TypeCoercer</a> service is used to convert parameters to the
correct type to be passed into the method.</li></ul><h2
id="PropertyExpressions-Examples">Examples</h2><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p> </p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Example</p></th><th colspan="1" rowspan="1"
class="confluenceTh"><p>Notes</p></th></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Keyword</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>this</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p> </p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Keyword</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>null</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p> </p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Property Name</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><
p>userName</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Calls
getUserName() or setUserName, depending on context</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Property Chain</p></th><td
colspan="1" rowspan="1" class="confluenceTd"><p>user.address.city</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p>Calls
getUser().getAddress().getCity() or getUser().getAddress().setCity(), depending
on context</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Property Chain</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>user?.name</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>Calls getUser() and, if the result is not null, calls
getName() on the result</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Method Invocation</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>groupList.size()</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>calls getGroupList().size()</p></
td></tr><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Method
Invocation</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>members.findById(user.id)?.name</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>Calls
getMembers().findById(getUser().getId()).getName() (unless findById returns
null)</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Range</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>1..10</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>Iterates between integers 1 and 10</p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Range</p></th><td colspan="1"
rowspan="1" class="confluenceTd"><p>1..myList.size()</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>Iterates between 1 and the result of
getMyList().size()</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Literal String</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>'Beer is proof that God lov
es us and wants us to be happy.'</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>Use single quotes</p></td></tr><tr><th colspan="1"
rowspan="1" class="confluenceTh"><p>List</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>[user.name, user.email, user.phone]</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p> </p></td></tr><tr><th
colspan="1" rowspan="1" class="confluenceTh"><p>Not Operator</p></th><td
colspan="1" rowspan="1" class="confluenceTd"><p>! user.deleted</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p>the boolean negation of
getUser().getDeleted()</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Not, Coerced</p></th><td colspan="1" rowspan="1"
class="confluenceTd"><p>! user.middleName</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>true only if getUser.getMiddleName() returns null or an
empty string</p></td></tr><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p>Map</p></th><td colspan="1"
rowspan="1" class="confluenceTd"><p>{ 'framework' : 'Tapestry', 'version' :
version }</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Keys are
string literals (in single quotes), but could be properties as
well</p></td></tr></tbody></table></div></div>
</div>
<div class="clearer"></div>