You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by co...@apache.org on 2003/05/24 20:51:26 UTC
cvs commit: cocoon-2.1/src/documentation/xdocs/userdocs/flow api.xml jpath.xml jxtemplate.xml sitemap.xml using.xml velocity.xml views.xml book.xml continuations.xml how-does-it-work.xml
coliver 2003/05/24 11:51:26
Modified: src/documentation/xdocs/userdocs/flow book.xml
continuations.xml how-does-it-work.xml
Added: src/documentation/xdocs/userdocs/flow api.xml jpath.xml
jxtemplate.xml sitemap.xml using.xml velocity.xml
views.xml
Log:
improve flowscript docs (still sucks though, unfortunately)
Revision Changes Path
1.3 +7 -0 cocoon-2.1/src/documentation/xdocs/userdocs/flow/book.xml
Index: book.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/flow/book.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- book.xml 25 Mar 2003 13:53:56 -0000 1.2
+++ book.xml 24 May 2003 18:51:26 -0000 1.3
@@ -14,5 +14,12 @@
<menu-item label="Introduction" href="index.html"/>
<menu-item label="Continuations" href="continuations.html"/>
<menu-item label="How does it work?" href="how-does-it-work.html"/>
+ <menu-item label="Usage" href="using.html"/>
+ <menu-item label="Sitemap" href="sitemap.html"/>
+ <menu-item label="JavaScript API" href="api.html"/>
+ <menu-item label="Generators" href="views.html"/>
+ <menu-item label="JXTemplate" href="jxtemplate.html"/>
+ <menu-item label="JPath" href="jpath.html"/>
+ <menu-item label="Velocity" href="velocity.html"/>
</menu>
</book>
1.2 +3 -3 cocoon-2.1/src/documentation/xdocs/userdocs/flow/continuations.xml
Index: continuations.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/flow/continuations.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- continuations.xml 25 Mar 2003 13:43:33 -0000 1.1
+++ continuations.xml 24 May 2003 18:51:26 -0000 1.2
@@ -35,13 +35,13 @@
var a, b, operator;
sendPageAndWait("getA.html");
- a = request.getParameter("a");
+ a = cocoon.request.get("a");
sendPageAndWait("getB.html");
- b = request.getParameter("b");
+ b = cocoon.request.get("b");
sendPageAndWait("getOperator.html");
- operator = request.getParameter("op");
+ operator = cocoon.request.get("op");
try {
if (operator == "plus")
1.2 +1 -1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/how-does-it-work.xml
Index: how-does-it-work.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/flow/how-does-it-work.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- how-does-it-work.xml 25 Mar 2003 13:43:33 -0000 1.1
+++ how-does-it-work.xml 24 May 2003 18:51:26 -0000 1.2
@@ -35,7 +35,7 @@
<p>Since continuations are objects, you can also store them in
a database, for really long-lived session, just like you do
with session beans.</p>
- </s1>
+ </s1>
</body>
</document>
1.1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/api.xml
Index: api.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "../../../WEB-INF/entities/document-v10.dtd">
<document>
<header>
<title>Advanced Control Flow</title>
<authors>
<person name="Ovidiu Predescu" email="ovidiu@apache.org"/>
<person name="Christopher Oliver" email="coliver@apache.org"/>
</authors>
</header>
<body>
<s1 title="JavaScript API">
<p>Cocoon provides a JavaScript API to manage control flow based on an <link href="http://cvs.cocoondev.org/cgi-bin/viewcvs.cgi/?cvsroot=rhino">extended</link> version of <link href="http://www.mozilla.org/rhino">Mozilla Rhino</link> that supports continuations.</p>
</s1>
<s1 title="Functions">
<s2 title = "sendPage">
<p>
<code>void sendPage([String] uri, [Object] bean)</code>
</p>
<p>
Passes control to the Cocoon sitemap to generate the output page.
</p>
<p>
<code>uri</code> is the relative URL of the page to be sent back to the client.
</p>
<p>
<code>bean</code> is a context object which can be accessed inside this page toextract various values and place them in the generated page.
</p>
</s2>
<s2 title = "sendPageAndWait">
<p>
<code>WebContinuation sendPageAndWait([String] uri, [Object] bean, [Number] timeToLive)</code>
</p>
<p>
Passes control to the Cocoon sitemap to generate the output page.
</p>
<p>The flow script is suspended after the page is generated and the whole execution stack saved in a the WebContinuation object returned from this function. </p>
<p> <code>uri</code> is the relative URL of the page to be sent back to the client. <code>bean</code> is a context object which can be accessed inside this page to extract various values and place them in the generated page.</p>
<p><code>timeToLive</code> is the time to live for the continuation created.</p>
<p>The return value is the continuation object.</p>
</s2>
</s1>
<s1 title="Objects">
<s2 title = "cocoon">
</s2>
<p>The <code>cocoon</code> object represents the current Cocoon sitemap and provides the following readonly properties:</p>
<p>The current Cocoon request:</p>
<p>
<code>[org.apache.cocoon.environment.Request] request</code>
</p>
<p>The current Cocoon response:</p>
<p>
<code>[org.apache.cocoon.environment.Response] response</code>
</p>
<p>The current Cocoon session:</p>
<p>
<code>[org.apache.cocoon.environment.Session] session</code>
</p>
<p>The current Cocoon application context:</p>
<p>
<code>[org.apache.cocoon.environment.Context] context</code>
</p>
<p>The current Cocoon environment:</p>
<p>
<code>[org.apache.cocoon.environment.Environment] environment</code>
</p>
<p>The current Sitemap's component manager:</p>
<p>
<code>[org.apache.avalon.framework.component.ComponentManager] componentManager</code>
</p>
<p>Any parameters passed to the script by the Sitemap:</p>
<p>
<code>[Array] parameters</code>
</p>
<p>The <code>cocoon</code> object also provides the following functions:</p>
<p>
<code>[Boolean] process([String] uri, [Object] bizData, [java.io.OutputStream] stream)</code></p>
<p>
Call the Cocoon sitemap for the given URI, sending the output of the
eventually matched pipeline to the specified outputstream.</p>
<p><code>uri</code> is the URI for which the request should be generated.</p>
<p><code>bizData</code> is the business data object
to be made available to the forwarded pipeline</p>
<p><code>stream</code> is an <code>OutputStream</code> where the output should be written to.</p>
<p>Returns the result from the Cocoon processor.
</p>
<p><code>void createSession()</code></p>
<p>
Associate the current set of JavaScript global variables with the user's session. This means that all invocations from the
sitemap of a JavaScript function (using the <map:call
function="...">), will share global JavaScript variables.
</p>
<p>
<code>void removeSession()</code>
</p>
<p>
Dissociate global JavaScript variables from the user's session.
</p>
<p><code>void load([String] uri)</code></p>
<p>
Load the JavaScript script specified by <code>uri</code>. The Cocoon
source resolver is used to resolve <code>uri</code>.
</p>
</s1>
</body>
</document>
1.1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/jpath.xml
Index: jpath.xml
===================================================================
<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN"
"../dtd/document-v10.dtd">
<document>
<header>
<title>Advanced Control Flow</title>
<authors>
<person name="Christopher Oliver" email="coliver@apache.org" />
<person name="Ovidiu Predescu" email="ovidiu@apache.org" />
</authors>
</header>
<body>
<s1 title="JPath Logic Sheet">
<p>
The JPath Logic Sheet is an XSP logic sheet that allows you to access data from a Cocoon Flowscript in an XSP page and inject it into a Cocoon pipeline. It provides a set of tags (similar to the those defined by <link href="http://www.w3.org/TR/xslt">XSLT</link>) that allow you to iterate over Java collections (and Java or JavaScript arrays) and to test for the presence of optional or alternate bean properties. It is based on <link href="http://jakarta.apache.org/commons/jxpath">Apache JXPath</link>.
</p>
</s1>
<s1 title ="Tags">
<p>The JPath tags are defined in the namespace</p>
<source>
http://apache.org/xsp/jpath/1.0
</source>
<s2 title ="if">
<p>The <code>if</code> tag allows the conditional execution of its body
according to value of a <code>test</code> attribute:</p>
<source>
<if test="XPathExpression">
body
</if>
</source>
<p>Example:
<source>
<jpath:if test="cart/numberOfItems = 0">
Your cart is empty
</jpath:if>
</source>
</p>
</s2>
<s2 title ="choose">
<p>The <code>choose</code> tag performs conditional block execution by the
embedded <code>when</code> sub tags. It renders the body of the first
<code>when</code> tag whose <code>test</code> condition evaluates to true.
If none of the <code>test</code> conditions of nested <code>when</code> tags
evaluate to <code>true</code>, then the body of an <code>otherwise</code>
tag is evaluated, if present:</p>
<source>
<choose>
<when test="XPathExpression">
body
</when>
<otherwise>
body
</otherwise>
</choose>
</source>
<p>Example:
<source>
<choose>
<when test="not(user/loggedIn)">
You're not logged in
</when>
<otherwise>
You're already logged in
</otherwise>
</choose>
</source>
</p>
</s2>
<s2 title="value-of">
<p>The <code>value-of</code> tag evaluates an expression and outputs
the result of the evaluation:</p>
<source>
<value-of select="XPathExpression"/>
</source>
<p>Example:
<source>
<value-of select="cart/numberOfItems">
</source>
</p>
</s2>
<s2 title="for-each">
<p>The <code>forEach</code> tag allows you to iterate over a collection
of objects:</p><p>
<source>
<forEach select="XPathExpression">
body
</forEach>
</source>
<p>When using XPath expressions within <code>for-each</code> the current element is the context node and can be referenced with:</p>
<source>.</source></p>
<p>Example:
<source>
<for-each select="cart/cartItems[position() <= $count]">
<td><value-of select="./productId"></td>
</forEach>
</source>
</p>
</s2>
<s2 title="continuation">
<p>The <code>continuation</code> tag returns the id of the current web continuation of your Flowscript. You can refer to previous continuations by supplying the <code>level</code> attribute. Zero is the current level, <code>-1</code> refers to the previous continuation, and so on.</p>
<source>
<continuation [level="Number"]/>
</source>
<p>Example:
<source>
<xsp:attribute name="action">"kont/"+<jpath:continuation><xsp:attribute>
</source>
</p>
</s2>
</s1>
</body>
</document>
1.1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/jxtemplate.xml
Index: jxtemplate.xml
===================================================================
<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN"
"../dtd/document-v10.dtd">
<document>
<header>
<title>Advanced Control Flow</title>
<authors>
<person name="Christopher Oliver" email="coliver@apache.org" />
</authors>
</header>
<body>
<s1 title="JXTemplate Generator">
<p>
The JXTemplate Generator is a page template processor that allows you to inject data from Java and JavaScript objects passed by a Cocoon Flowscript into a Cocoon pipeline. It provides a set of tags (similar to the <link href="http://java.sun.com/products/jsp/jstl/">JSTL</link> core tags) that allow you to iterate over Java collections (and Java or JavaScript arrays) and to test for the presence of optional or alternate bean properties, as well as embedded expressions to specify conditions and to access the properties of objects. The <em>JX</em>Template Generator gets its name from the embedded expression languages it supports, namely <link href="http://jakarta.apache.org/commons/jxpath">Apache <em>JX</em>Path</link> and <link href="http://jakarta.apache.org/commons/jxpath">Apache <em>J</em>e<em>X</em>l</link>.
</p>
</s1>
<s1 title="Expression Languages">
<p>
The JXTemplateGenerator supports two embedded expression languages: <link href="http://jakarta.apache.org/commons/jxpath">Jexl</link> and <link href="http://jakarta.apache.org/commons/jxpath">JXPath</link>. Apache <link href="http://jakarta.apache.org/commons/jxpath">Jexl</link> provides an extended version of the expression language of the <link href="http://java.sun.com/webservices/docs/1.0/tutorial/doc/JSTL.html">JSTL</link>. Apache <link href="http://jakarta.apache.org/commons/jxpath">JXPath</link> provides an interpreter of the <link href="http://www.w3.org/TR/xpath">XPath</link> expression language that can apply XPath expressions to graphs of Java objects of all kinds: JavaBeans, Maps, Servlet contexts, DOM etc, including mixtures thereof.
</p>
<p>
Having an embedded expression language allows a page author to access an object using a simple syntax such as
</p>
<source>
<site signOn="${accountForm.signOn}">
</source>
<p>Embedded Jexl expressions are contained in <source>${}</source></p>
<p>Embedded JXPath expressions are contained in <source>#{}</source></p>
<p>The referenced objects may be Java Beans, DOM, JDOM, or JavaScript objects
from a Flowscript. In addition the following implicit objects are available as
both JXPath and Jexl variables in a template:</p>
<p>
<dl>
<dt><code>request</code></dt>
<dd>The Cocoon current request</dd>
<dt><code>response</code></dt>
<dd>The Cocoon response associated with the current request</dd>
<dt><code>session</code> </dt>
<dd>The Cocoon session associated with the current request</dd>
<dt><code>context</code> </dt>
<dd>The Cocoon context associated with the current request</dd>
<dt><code>parameters</code></dt>
<dd>Any parameters passed to the generator in the pipeline</dd>
</dl>
</p>
<p>
Jexl Example:
<source>
The content type of the current request is ${request.contentType}
</source>
</p>
<p>
JXPath Example:
<source>
The content type of the current request is #{request/contentType}
</source>
</p>
<p>
The current Web Continuation from the Flowscript
is also available as a variable named <code>continuation</code>. You would
typically access its <code>id</code>:
<source>
<form action="${continuation.id}">
</source>
</p>
<p>You can also reach previous continuations by using the <code>getContinuation()</code> function:</p>
<source>
<form action="${continuation.getContinuation(1).id}" >
</source>
<p>or using an XPath expression:</p><p>
<source>
<form action="#{getContinuation($continuation)/id}" >
</source></p>
</s1>
<s1 title ="Tags">
<p>The JXTemplateGenerator tags are defined in the namespace</p>
<source>
http://apache.org/cocoon/templates/jx/1.0
</source>
<s2 title ="template">
<p>The <code>template</code> tag defines a new template:</p><source>
<t:template xmlns:t="http://apache.org/cocoon/templates/jx/1.0">
body
</t:template>
</source>
</s2>
<s2 title ="import"/>
<p>The <code>import</code> tag allows you to include another template within the current template. The content of the imported template is compiled and will be executed in place of the <code>import</code> tag:</p><source>
<import uri="URI" [context="Expression"]/>
</source><p>The Cocoon source resolver is used to resolve <code>uri</code>. If <code>context</code> is present, then its value is used as the context for evaluating the imported template, otherwise the current context is used.</p>
<s2 title ="set">
<p>The <code>set</code> tag creates a local alias of an object. The <code>var</code> attribute specifies the name of a variable to assign the object to. The <code>value</code> attribute specifies the object (defaults to <code>body</code> if not present):</p><source>
<set var="Name" [value="Value"]>
[body]
</set>
</source><p>If used within a <code>macro</code> definition (see below) variables created by <code>set</code> are only visible within the body of the <code>macro</code>.</p>
<p>Jexl Example:
<source>
<set var="greeting" value="Hello ${user}"/>
${greeting}
</source>
</p>
<p>JXPath Example:
<source>
<set var="greeting" value="Hello #{user}"/>
#{$greeting}
</source>
</p>
</s2>
<s2 title ="if">
<p>The <code>if</code> tag allows the conditional execution of its body
according to value of a <code>test</code> attribute:</p>
<source>
<if test="Expression">
body
</if>
</source>
<p>Jexl Example:
<source>
<if test="${cart.numberOfItems == 0}">
Your cart is empty
</if>
</source>
</p>
<p>JXPath Example:
<source>
<if test="#{cart/numberOfItems = 0}">
Your cart is empty
</if>
</source>
</p>
</s2>
<s2 title ="choose">
<p>The <code>choose</code> tag performs conditional block execution by the
embedded <code>when</code> sub tags. It renders the body of the first
<code>when</code> tag whose <code>test</code> condition evaluates to true.
If none of the <code>test</code> conditions of nested <code>when</code> tags
evaluate to <code>true</code>, then the body of an <code>otherwise</code>
tag is evaluated, if present:</p>
<source>
<choose>
<when test="Expression">
body
</when>
<otherwise>
body
</otherwise>
</choose>
</source>
<p>Jexl Example:
<source>
<choose>
<when test="${!user.loggedIn}">
<set var="label" value="Log in">
</when>
<otherwise>
<set var="label" value="Log out">
</otherwise>
</choose>
</source>
</p>
<p>JXPath Example:
<source>
<choose>
<when test="#{not(user/loggedIn)}">
<set var="label" value="Log in">
</when>
<otherwise>
<set var="label" value="Log out">
</otherwise>
</choose>
</source>
</p>
</s2>
<s2 title="out">
<p>The <code>out</code> tag evaluates an expression and outputs
the result of the evaluation:</p>
<source>
<out value="Expression"/>
</source>
<p>Jexl Example:
<source>
<out value="${cart.numberOfItems}">
</source>
</p>
<p>JXPath Example:
<source>
<out value="#{cart/numberOfItems}">
</source>
</p>
</s2>
<s2 title="forEach">
<p>The <code>forEach</code> tag allows you to iterate over a collection
of objects:</p><p>
<source>
<forEach [var="Name"] [items="Expression"] [begin="NumExpr"] [end="NumExpr"] [step="NumExpr"]>
body
</forEach>
</source></p>
<p>The <code>items</code> attribute specifies the list of items to iterate over. The <code>var</code> attribute specifies the name of a variable to hold the current item. The <code>begin</code> attribute specifies the element to start with
(<code>0</code> = first item, <code>1</code> = second item, ...).
If unspecified it defaults to <code>0</code>. The <code>end</code>
attribute specifies the item to end with (<code>0</code> = first item,
<code>1</code> = second item, ...). If unspecified it defaults to the last item in the list. Every <code>step</code> items are
processed (defaults to <code>1</code> if <code>step</code> is absent). Either <code>items</code> or both <code>begin</code> and <code>end</code> must be present.</p>
<p>An alternate form of <code>forEach</code> is supported for convenience when using XPath (since you can specify the selection criteria for the collection using XPath itself):</p>
<source>
<forEach select="XPathExpression">
body
</forEach>
</source>
<p>When using XPath expressions within <code>forEach</code> the current element is the context node and can be referenced with:</p>
<source>#{.}</source>
<p>Jexl Example:
<source>
<forEach var="item" items="${cart.cartItems} begin="${start}" end="${count-start}" step="1"">
<td>${item.productId}</td>
</forEach>
</source>
</p>
<p>JXPath Example:
<source>
<forEach items="#{cart/cartItems[position() <=$count]}}>
<td>#{./productId}</td>
</forEach>
</source>
</p>
</s2>
<s2 title="macro">
<p>The <code>macro</code> tag allows you define a new custom tag.</p><source>
<macro name="Name" [targetNamespace="Namespace"]>
<parameter name="Name" [optional="Boolean"] [default="Value"]/>
body
</macro>
</source>
<p> For example:</p><source>
<c:macro name="d">
<tr><td></td></tr>
</c:macro>
</source>
<p>The tag being defined in this example is <code><d></code> and it
can be used like any other tag:</p><source>
<d/>
</source>
<p>However, when this tag is used it will be replaced with a row containing a single empty data cell.</p>
<p> When such a tag is used, the attributes and content of the tag become available as variables in the body of the <code>macro</code>'s definition, for example:</p><source>
<c:macro name="tablerows">
<c:parameter name="list"/>
<c:parameter name="color"/>
<c:forEach var="item" items="${list}">
<tr><td bgcolor="${color}">${item}</td></tr>
</c:forEach>
</c:macro>
</source>
<p>The <code>parameter</code> tags in the macro definition define formal parameters, which are replaced with the actual attribute values of the tag when it is used. The content of the tag is also available as a special variable <code>${content}</code>.</p><p>Assuming you had this code in your flowscript:</p><p>
<code>var greatlakes = ["Superior", "Michigan", "Huron", "Erie", "Ontario"];</code></p><p><code> sendPage(uri, {greatlakes: greatlakes});</code>
</p><p>and a template like this:</p><source>
<table>
<tablerows list="${greatlakes}" color="blue"/>
</table>
</source>
<p>When the <code>tablerows</code> tag is used in this situation the following output would be generated:
</p>
<source>
<table>
<tr><td bgcolor="blue">Superior</td></tr>
<tr><td bgcolor="blue">Michigan</td></tr>
<tr><td bgcolor="blue">Huron</td></tr>
<tr><td bgcolor="blue">Erie</td></tr>
<tr><td bgcolor="blue">Ontario</td></tr>
</table>
</source>
</s2>
</s1>
</body>
</document>
1.1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/sitemap.xml
Index: sitemap.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "../../../WEB-INF/entities/document-v10.dtd">
<document>
<header>
<title>Advanced Control Flow</title>
<authors>
<person name="Ovidiu Predescu" email="ovidiu@apache.org"/>
<person name="Christopher Oliver" email="coliver@apache.org"/>
</authors>
</header>
<body>
<s1 title="Sitemap">
<p>The Cocoon sitemap includes several elements to specify interactions with your Flowscripts</p>
<s2 title="flow">
<p>The <code>flow</code> element defines a Flowscript interpreter for a sitemap. The <code>language</code> attribute specifies the target programming language. Currently the only supported language is <code>"JavaScript"</code>. Its embedded <code>script</code> elements allow you to specify the files that make up the flow for this sitemap. Each <code>script</code> element specifies the URI of a script that will be compiled and executed when this Sitemap is created. The <code>src</code> attribute specifies the URI of the script.</p><p>
<source><![CDATA[
<map:flow language="Language">
<map:script src="URI"/>+
</map:flow>
]]></source>
</p>
</s2>
<s2 title="call">
<p>The <code>call</code> element allows you to call a top-level function in your Flowscript or to invoke an existing continuation.</p>
<p>If the <code>function</code> attribute is present, then the Sitemap will invoke a top-level function defined in your Flowscript. The <code>function</code> attribute specifies the name of the function. Zero or more nested <code>parameter</code> elements may be provided to pass arguments to the function.</p>
<p>
<source><![CDATA[
<map:call function="FunctionName">
<map:parameter name="Name" value="Value"/>*
</map:call>
]]></source>
</p>
<p>If the <code>continuation</code> attribute is present, then the Sitemap will invoke an existing continuation of your Flowscript. The <code>continuation</code> attribute specifies the unique id of the continuation.</p>
<p>
<source><![CDATA[
<map:call continuation="Id"/>
]]></source>
</p>
</s2>
</s1>
</body>
</document>
1.1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/using.xml
Index: using.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "../../../WEB-INF/entities/document-v10.dtd">
<document>
<header>
<title>Advanced Control Flow</title>
<authors>
<person name="Ovidiu Predescu" email="ovidiu@apache.org"/>
</authors>
</header>
<body>
<s1 title="Using Cocoon's Control Flow">
<p>
The general flow of actions in an application which uses the control flow
is as described below.
</p>
<p>
The request is received by Cocoon and passed to the sitemap for
processing. In the sitemap, you can do two things to pass the control to
the Control Flow layer:
<ul>
<li>
You can invoke a JavaScript top-level function to start processing a
logically grouped sequences of pages. Each time a response page is
being sent back to the client browser from this function, the
processing of the JavaScript code stops at the point the page is
sent back, and the HTTP request finishes. Through the magic of
continuations, the execution state is saved in a continuation object.
Each continuation is given a unique string id, which could be embedded
in generated page, so that you can restart the saved computation later
on.
</li>
<li>
To invoke a top level JavaScript function in the Control Flow, you use
the <code><map:call function="function-name"/></code>
construction.
</li>
<li>
To restart the computation of a previously stopped function, you use
the <code><map:continue with="..."/></code> construction.
This restarts the computation saved in a continuation object
identified by the string value of the <code>with</code> attribute.
This value could be extracted in the sitemap from the requested URL,
from a POST or GET parameter etc. When the computation stored in the
continuation object is restarted, it appears as if nothing happened,
all the local and global variables have exactly the same values as
they had when the computation was stopped.
</li>
</ul>
</p>
<p>
Once the JavaScript function in the control layer is restarted, you're
effectively inside the Control Flow. Here you have access to the request
parameters, and to the business logic objects. The controller script
takes the appropriate actions to invoke the business logic, usually
written in Java, creating objects, setting various values on them etc...
</p>
<p>
When the business logic is invoked, you're inside the Model. The business
logic takes whatever actions are needed, accessing a database, making a
SOAP request to a Web service etc. When this logic finishes, the program
control goes back to the Control Flow.
</p>
<p>
Once here, the Control Flow has to decide which page needs to be sent back
to the client browser. To do this, the script can invoke either the
<code>sendPage</code> or the <code>sendPageAndContinue</code> functions.
These functions take two parameters, the relative URL of the page to be
sent back to the client, and a context object which can be accessed
inside this page to extract various values and place them in the
generated page.
</p>
<p>
The second argument to <code>sendPage</code> and
<code>sendPageAndContinue</code> is a context object, which can be a
simple dictionary with values that need to be displayed by the View. More
generally any Java or JavaScript object can be passed here, as long as
the necessary get methods for the important values are provided.
</p>
<p>
The page specified by the URL is processed by the sitemap, using the
normal sitemap rules. The simplest case is an XSP generator followed by
an XSLT transformation and a serializer. This page generation is part of
the View layer. If an XSP page is processed, you can make use of several
Cocoon generators to retrieve values from the context objects passed by the
Control Flow.
</p>
<p>
Going back to the <code>sendPage</code> and
<code>sendPageAndContinue</code> functions, there is a big difference
between them. The first function will send the response back to the
client browser, and will stop the processing of the JavaScript script by
saving it into a continuation object. The other function,
<code>sendPageAndContinue</code> will send the response, but it will not
stop the computation. This is useful for example when you need to exit a
top-level JavaScript function invoked with
<code><map:call function="..."/></code>.
</p>
<p>
The above explains how MVC could be really achieved in Cocoon with the
control flow layer. Note that there is no direct communication between
Model and View, everything is directed by the Control Flow by passing to
View a context object constructed from Model data. In a perfect world,
XSP should have only one logicsheet, the JXPath logicsheet. There should
be no other things in an XSP page that put logic in the page (read View),
instead of the Model. If you don't like XSP, and prefer to use JSP or
Velocity, the JXPath logicsheet equivalents should be implemented.
</p>
<h4>Basic usage</h4>
<p>
As hinted in the previous section, an application using Cocoon's MVC
approach is composed of three layers:
<ul>
<li>
A JavaScript controller which implements the interaction with the
client
</li>
<li>
The business logic model which implements your application
</li>
<li>
The XSP pages, which describe the content of the pages, and XSLT
stylesheets which describe the look of the content.
</li>
</ul>
</p>
<p>
In more complex applications, the flow of pages can be thought of smaller
sequences of pages which are composed together. The natural analogy is to
describe these sequences in separate JavaScript functions, which can then
be called either from the sitemap, can call each other freely.
</p>
<p>
An example of such an application is the user login and preferences
sample
</p>
<p>
This application is composed of four top-level JavaScript functions:
<ul>
<li><code>login</code>,</li>
<li><code>registerUser</code>,</li>
<li><code>edit</code> and</li>
<li><code>logout</code>.</li>
</ul>
</p>
<p>
The entry level point in the application can be any of these functions,
but in order for a user to use the application, (s)he must login first.
Once the user logs in, we want to maintain the Java User object which
represents the user between top-level function invocations.
</p>
<p>
If the script does nothing, each invocation of a top-level function
starts with fresh values for the global variables, no global state is
preserved between top-level function invocations from the sitemap. In
this sample for example, the <code>login</code> function assigns to the
global variable <em>user</em> the Java User object representing the
logged in user. The <code>edit</code> function trying to operate on this
object would get a null value instead, because the value is not shared by
default between these top-level function invocations.
</p>
<p>
To solve the problem, the <code>login</code> and
<code>registerUser</code> functions have to call the
<code>cocoon.createSession()</code> method, which creates a servlet
session and saves the global scope containing the global variables' value
in it. Next time the user invokes one of the four top-level functions,
the values of the global variables is restored, making sharing very easy.
</p>
<p>
Even if you don't need complex control flow in your application, you may
still choose to use the MVC pattern described above. You can have top-
level JavaScript functions which obtain the request parameters, invoke
the business logic and then call <code>sendPageAndContinue</code> to
generate a response page and return from the computation. Since there's
no continuation object being created by this function, and no global
scope being saved, there's no memory resource being eaten. The approach
provides a clean way of separating logic and content, and makes things
easy to follow, since you have to look at a single script to understand
what's going on.
</p>
</s1>
</body>
</document>
1.1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/velocity.xml
Index: velocity.xml
===================================================================
<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN"
"../dtd/document-v10.dtd">
<document>
<header>
<title>Advanced Control Flow</title>
<authors>
<person name="Christopher Oliver" email="coliver@apache.org" />
<person name="Ovidiu Predescu" email="ovidiu@apache.org" />
</authors>
</header>
<body>
<s1 title="Velocity Generator">
<p>
If called from a Flowscript, the Cocoon <link href="http://jakarta.apache.org/velocity">Velocity</link> Generator provides access to the immediate properties of the context object passed to <code>sendPage</code> and <code>sendPageAndWait</code>. In that case, the current <code>WebContinuation</code> is also available as a variable named <code>$continuation</code>
You would
typically access its <code>id</code>:
<source>
<p><pre>
<form action="$continuation.id">
</pre></p>
</source>
<p>You can also reach previous continuations by using the <code>getContinuation()</code> function:</p>
<source>
<p><pre>
<form action="$continuation.getContinuation(1).id" >
</pre></p>
</source>
In addition the following implicit objects are always available in
the Velocity context:
<p>
<dl>
<dt><code>request</code> (<code>org.apache.cocoon.environment.Request</code>)</dt>
<dd>The current Cocoon request</dd>
<dt><code>response</code> (<code>org.apache.cocoon.environment.Response</code>)</dt>
<dd>The Cocoon response associated with the current request</dd>
<dt><code>session</code> (<code>org.apache.cocoon.environment.Session</code>)</dt>
<dd>The Cocoon session associated with the current request</dd>
<dt><code>context</code> (<code>org.apache.cocoon.environment.Context</code>)</dt>
<dd>The Cocoon context associated with the current request</dd>
<dt><code>parameters</code> (<code>org.apache.avalon.framework.parameters.Parameters</code>)</dt>
<dd>Any parameters passed to the generator in the pipeline</dd>
</dl>
</p>
</p>
</s1>
</body>
</document>
1.1 cocoon-2.1/src/documentation/xdocs/userdocs/flow/views.xml
Index: views.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "../../../WEB-INF/entities/document-v10.dtd">
<document>
<header>
<title>Advanced Control Flow</title>
<authors>
<person name="Ovidiu Predescu" email="ovidiu@apache.org"/>
<person name="Christopher Oliver" email="coliver@apache.org"/>
</authors>
</header>
<body>
<s1 title="Flowscript-aware Generators">
<p>
The second argument to <code>sendPage</code> and <code>sendPageAndWait</code> is a context object, which can be a simple dictionary with values that need to be displayed by the View. More generally any Java or JavaScript object can be passed here, as long as the necessary get methods for the important values are provided.
</p>
<p>
The page specified by the URL is processed by the sitemap, using the normal sitemap rules.
</p>
<p>
Several generators are provided that allow you to access the context object and inject its values into a pipeline.
</p>
</s1>
</body>
</document>