Flow Script

Flow Script という JavaScript 形式の言語でページ遷移の流れを記述することができます.

HTTP は本質的にステートレスなプロトコルであるため,Webアプリケーションの"状態"を表現するには一般にセッションを使います.
Flow Script では HTTP において HTML とともに継続と呼ばれる"計算の続きへのポインタ"をクライアントに渡し,クライアントはこの継続をサーバへ返すことでHTTPを介しても流れを損なわないようにしています.


たとえば "Login してメッセージを投稿" するというアプリを書いてみましょう.


こんな感じです.

login


Flow Script

このフローは以下のような JavaScript で記述できます.
 /* sample.js */
function login() {

var name = "";
var password = "";

/* passwordが一致するまでループ */
while (true) {

/* パラメータ name, password を付加して,ページ login.jx を送信し一時停止 */
cocoon.sendPageAndWait("login.jx", { "name" : name , "password" : password } );

/* クライアントから受信したパラメータを取得 */
name = cocoon.request.get("name");
password = cocoon.request.get("password");

if (password == "test") {
break;
}
}

cocoon.sendPageAndWait("success.jx", {} );

var greeting = cocoon.request.get("greeting");

/* 一時停止しない */
cocoon.sendPage("greeting.jx", { "name" : name, "greeting" : greeting});

}

ひとつづつ説明します.

1.

 function login() { 
Flow Script は JavaScript の関数で記述します.
Cocoon は login という名前でフローを呼び出すことができるようになります.

2.

cocoon.sendPageAndWait("login.jx", { "name" : name , "password" : password } );
オブジェクト cocoonCocoon が提供するオブジェクトです. 宣言する必要はありません.
cocoon オブジェクトのメソッド sendPageAndWait() でページを送信し,Script はここで一時停止します.

引数の意味は以下のようになります.
第1引数: ページ
第2引数: key: value 形式のパラメータマップ.

しがたってこの例では,name,password というパラメータを付けて login.jx というページをクライアントに送信することになります.

3.

name = cocoon.request.get("name");
password = cocoon.request.get("password");

cocoon.request はリクエスト(ブラウザからのアクセス) を表すオブジェクトです.
メソッド get によりリクエストパラメータを取得できます.
この例ではパラメータ name, password を取得します.

4.

if (password == "test") {
break;
}

パスワードチェックです.簡単のため固定値"test"と比較します.
passwordが "test" ならwhileループを抜けます.

5.

cocoon.sendPageAndWait("success.jx", {} );

var greeting = cocoon.request.get("greeting");

/* 一時停止しない */
cocoon.sendPage("greeting.jx", { "name" : name, "greeting" : greeting});

sendPage() は sendPageAndWait() と違って一時停止しません.
ページを送信するとここでフローは終了です.

sitemap.xmapへの登録

以下のように FlowScript を登録します.
   <map:flow language="javascript">
<map:script src="sample.js"/>
</map:flow>

ページ

ページは継続を持ってクライアントに送信され,その継続をサーバに送信できるようになってなければなりません.
一番最初のページ login.jx で説明します.

例えば以下のように記述します.

<?xml version="1.0" encoding="Shift_JIS"?>
<html xmlns:jx="http://apache.org/cocoon/templates/jx/1.0">
<head>
<title>Login Page</title>
</head>
<body>
<h1>Login Page</h1>
<p>name = ${name}</p>
<p>password = ${password}</p>
<form method="post" action="${cocoon.continuation.id}.kont">
<table>
<tr><td>Name:</td><td><input type="text" name="name"/></td></tr>
<tr><td>Password:</td><td><input type="password" name="password"/></td></tr>
<tr><td></td><td><input type="submit"/></td></tr>
</table>
</form>
</body>
</html>
これはJXテンプレートというテンプレートエンジンを使ったページ生成プログラムです.

1.
${name}, ${password}のように記述することで Flow Script の sendPageAndWait(), sendPage() から渡された変数 name, password の値で置き換えます.

2.
${cocoon.continuation.id} で継続へのポインタで置き換えます.これは実際にはランダムな文字列で置き換えます.
<form method="post" action="${cocoon.continuation.id}.kont">
のようにしているので,submit すると *.kont というアドレスへアクセスされるため,sitemap.xmap ではこれに対応するパイプラインを記述する必要があります.
これは次項で.

再び sitemap.xmap

<map:match pattern="login">
<map:call function="login"/>
</map:match>

<map:match pattern="*.jx">
<map:generate type="jx" src="{1}.jx"/>
<map:serialize type="xhtml"/>
</map:match>


<map:match pattern="*.kont">
<map:call continuation="{1}"/>
</map:match>

<map:call function="login"/> で継続のエントリポイントを決めます.
<map:call continuation="{1}"/> で継続を Flow Script に渡し,フローを再開します.

以上が Flow Script の基本です.
さらなる情報はCocoon User Documentationを参照.