You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by bu...@apache.org on 2018/02/17 11:21:05 UTC

svn commit: r1025500 - in /websites/production/tapestry/content: cache/main.pageCache component-templates.html property-expressions.html

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;">&lt;html t:type="layout" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"&gt;
+<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;">&lt;html t:type="layout" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd"&gt;
     &lt;h1&gt;Bonjour from HelloWorld component.&lt;/h1&gt;
 &lt;/html&gt;
 </pre>
-</div></div><div class="sectionMacro"><div class="sectionMacroRow">&#160;</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;amp; &amp;lt; &amp;gt; &amp;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 &#8211; 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;amp; &amp;lt; &amp;gt; &amp;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 &#8211; 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;">&lt;!DOCTYPE html&gt;
 
 &lt;!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&#160; 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&#8211;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&#160; 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&#8211;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>&#160;</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>&#160;</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>&#160;</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>&#160;</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>&#160;</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>&#160;</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>&#160;</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>&#160;</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>