OpenWFEru の expression(式表現)

OpenWFEru.にある各 expression についての説明と例です。

それぞれの expression について, その “rdoc” をリンクしておきますね(多くが空白かもしれませんが)。

使用例はXMLと(または)Ruby のプロセス定義で示します。

Ruby プロセス定義での expression 名は ’_’ (アンダースコア)で始まります。これは実際のRubyのキーワードおよび項目名と区別するためです。

そして、OpenWFEru で実装された ワークフロー制御パターン のそれぞれを見るととても勉強になりますよ。

cancel-process(プロセスのキャンセル)

アルファベット順の最初の expression がこれ…。ワークフローエンジンがこの expression に出会ったら、これが含まれているプロセスを完全にキャンセルします。

    <sequence>
        <participant ref="before" />
        <cancel-process />
        <participant ref="after" />
    </sequence>

この例では、”after”という participant には決して到着しません。

大体において、”cancel-process” は “if” expressionまたは自身の’if’ attribute(属性)の結果として使われます。例えば…。

    require 'openwfe/def'

    class TestDefinition1 < OpenWFE::ProcessDefinition
        def make
            process_definition :name => "25_cancel", :revision => "1" do
                sequence do
                    participant "customer"
                    _cancel_process :if => "${f:no_thanks} == true"
                    concurrence do
                        participant "accounting"
                        participant "logistics"
                    end
                end
            end
        end
    end

もし、participant “customer” がフィールド “no_thanks” に “true” をセットしたら、フローは決して concurrence(条件一致時の処理) を実行しないでしょう。

rdoc

case

rdoc

concurrence(条件一致)

プロセスフローで2つ以上の条件分岐をさせます。

    <process-definition name="exp_mydef" revision="0.1">
        <concurrence>
            <participant ref="alice" />
            <participant ref="bob" />
            <sequence>
                <participant ref="charlie" />
                <participant ref="doug" />
            </sequence>
        </concurrence>
    </process-definition>

OpenWFEru ならこう書くこともできます。

    require 'openwfe/def'

    class MyProcessDefinition01 < OpenWFE::ProcessDefinition
        _concurrence do
            _participant :ref => "alice"
            _participant "bob"
            _sequence do
                charlie
                doug
            end
        end
    end

例で注意してほしいのは、participant が表示した ‘invoking’ には3つの異なる方法があることです。単独で使用する場合、participant 名はアンダースコアで始めてはいけません。

rdoc

concurrent-iterator

これはconcurrence(条件分岐) と iteratorの合いの子です。

iterator が子プロセスの並列コピーを発生させるのと同様、同じような属性を持ち同じような行動をすると理解してください。.

rdoc

cron

    <cron tab="0 9-17 * * mon-fri" name="exp_//reminder">
        <send-reminder />
    </cron>

rdoc

cursor

‘cursor’ expression は拡張機能を持つ sequence(シーケンス)です。

以下のコマンドが使えます。

loop expression は cursor をループさせます(ループから出るために “break” か “cancel” を指定してください)。

cursor rdoc

‘cursor’ expression はワークフロー制御パターン 10(Arbitrary Cycles) の例で使われています。

pattern

defined

rdoc

equals

rdoc

f

これは “field” の短縮形です。

field

rdoc

filter

participant expression には workitem 本体の入り口出口でフィルタリングするための ‘filter’ attribute(属性) があります。

またプロセスのsegment(セグメント)の入出力のデータをフィルタリングする’filter’ expression もあります。

    class MyProcessDefinition001 < ProcessDefinition
        sequence do

            set :field => "readable", :value => "bible"
            set :field => "writable", :value => "sand"
            set :field => "randw", :value => "notebook"
            set :field => "hidden", :value => "playboy"

            alice

            filter :name => "filter0" do
                sequence
                    bob
                    charly
                end
            end
        end

        filter_definition :name => "filter0" do
            field :regex => "readable", :permissions => "r"
            field :regex => "writable", :permissions => "w"
            field :regex => "randw", :permissions => "rw"
            field :regex => "hidden", :permissions => ""
        end
    end

上記例では, participant ‘alice’ は workitem の全てのフィールドを参照・更新できます。そのため participant ‘bob’ ・’charly’ では’readable’ ・ ‘randw’ フィールドの参照や ‘sand’ ・ ‘randw’ フィールドの更新が制限されます。

rdoc

filter-definition(フィルター定義)

既に filter expression のところの記述にフィルター定義の例があります。

フィルター定義は ビルドされた後OpenWFE の変数にバインドされます。なのでフィルターはローカルにも(プレフィックスなし)、プロセスレベル(プレフィックスは ”/” )・エンジンレベル(プレフィックスは ”//” )にもバインドできます。

フィルター定義はプロセス定義内で行なわれます。プロセスの本体で直接設定しても、その外(そのプロセス定義内であれば)で設定してもかまいません。

    filter_definition :name => "filter0" do
        field :regex => "readable", :permissions => "r"
        field :regex => "writable", :permissions => "w"
        field :regex => "randw", :permissions => "rw"
        field :regex => "hidden", :permissions => ""
    end

rdoc

forget

rdoc

if

rdoc

iterator

rdoc

loop

see cursor.

rdoc

lose

rdoc

parameter

‘parameter’ は実質、フローの expression ではありません。これが使われるのは workitem/launchitem のフィールドを提示したり、ある時点やフロー起動時にそれをチェックしたり検証したりするときです。

<process-definition name="exp_x" revision="0">

    <!-- required workitem fields -->

    <parameter field="customer" />
    <parameter field="address" default="" />
    <parameter field="zip" type="integer" />
    <parameter field="town" />
    <parameter field="phone" match="^[0-9]{3}-[0-9]{7}$" />
    <parameter field="customer_type" default="2" type="int"/>

    <!-- the body of the process definition -->

    <sequence>
        <participant ref="service0" />
        <participant ref="service1" />
        <play-the-music/>
    </sequence>

    <!-- subprocesses -->

    <process-definition name="exp_play-the-music">
        <participant ref="musician" />
    </process-definition>

</process-definition>

パラメータ (‘param’ でも同意です) はプロセス定義本体の外側に置かれなくてはいけません (‘process-definition’ タグの直接の子のように)。.

この例では、もし launchitem に ‘customer’・ ‘zip’・ ‘town’ ・’phone’ フィールド(属性)がなかったら、プロセスの起動はすぐに失敗します (起動が非同期だとしても)。もし ‘zip’ フィールドに integer に変換できないものがセットされていたらプロセスの起動は失敗します。’phone’ フィールドの値が与えられた正規表現にマッチしなかったらプロセスの起動は失敗します。’address’ フィールドになにも設定されてなければ、空白文字列(フィールドのデフォルトの値)に置き換えられます。’customer_type’ フィールドに明白に設定されていなければ、その値は integer の ‘2’ になります。

Ruby プロセス定義ではこんな感じです…。

    require 'openwfe/def'

    class MyProcessDefinition_01 < OpenWFE::ProcessDefinition

        #
        # required fields in the launchitem

        param :field => "customer"
        param :field => "address", default => ""
        param :field => "zip", type => "integer"
        param :field => "town"
        param :field => "phone", match => "^[0-9]{3}-[0-9]{7}$"
        param :field => "customer_type", default => 2, type => :int

        #
        # process definition body

        sequence do
            service0
            service1
            play_the_music
        end

        #
        # subprocesses

        process_definition :name => "play_the_music"
            musician
        end
    end

participant

rdoc

process-definition

rdoc

print

rdoc

q

これは “quote” の短縮形です。

quote

rdoc

redo

全ての expression は暗黙に ‘tag’ attribute を受け入れます。これは評価前の expression のコピーの名前を定義するもので、 (タグで示された expression で受け取るように)適用する workitem 内に保持されます。

この名前 (タグ) はa ‘redo’ や ‘undo’ expression に使われます。

    sequence do
        sequence :tag => "core_job" do
            participant "alice"
            participant "bob"
        end
        participant "charly"
        _if :test => "${f:charly_not_happy} == true" do
            _redo :ref => "core_job"
        end
    end

たぶんこの例は以下のように実装されるでしょう。

rdoc

reserve

この expression でプロセスインスタンスのセグメントを同時に実行しないようにさせます。

これは mutex な変数として使います。この変数はエンジンレベル (プレフィックスが ”//”) でバインドされ、まったく違う複数プロセスのセグメントが同時に実行されるのを防ぐために使います。

rdoc

restore

これは workitem 本体の最上位の値同様、(サブ)フィールドの値をコピーしたり、前もってsave したworkitem の本体をリストアしたりするのに使います。

この expression にはたくさんのオプションがあります。詳細な説明は以下の rdoc を参照してください。

rdoc

reval

この expression はネストされた Ruby のコードを評価します。

    <sequence>
        <reval>$i = 0</reval>
        <loop>
            <participant ref="toto" />
            <reval>$i = $i + 1</reval>
            <break if="${r:$i == 10}" />
            <!-- a variant :
            <break rif="$i == 10" />
            -->
        </loop>
    </sequence>

‘reval’ されたコード中において、エンジン内部で hook される2つのprincipalは、RawExpression インスタンス自身とworkitem を指すself です。

    class Reval4 < OpenWFE::ProcessDefinition
        sequence do
            reval """
                engine = self.application_context['__tracer']

                workitem.currently_active_processes =
                    engine.list_processes.join('\n')

                'done' # will be placed in the workitem field '__result__'
            """
            participant :toto
        end
    end

‘reval’ の結果は

__result__
というフィールドに String でセットされます。

コードは SAFE level 3 ( http://www.rubycentral.com/book/taint.html にこの level に関する詳しい情報があります) で評価されます。

エンジンの application context で :ruby_eval_allowed パラメータに “true” を設定しなければなりません。さもないと ‘reval’ expression は例外を発生させます。

    engine.application_context[:ruby_eval_allowed] = true

rdoc

save

この expression は workitem に変数を保存したり、同一workitem の フィールドにある attribute を保存するのに使います。

restore と共同で使われます。

rdoc

sequence

単純に他のフローの expression と繋げるために使います。

    <process-definition name="exp_my_definition" revision="0">
        <sequence>
            <participant ref="alpha" />
            <participant ref="bravo" />
            <participant ref="charly" />
        </sequence>
    </process-definition>
    require 'openwfe/def'

    class MyDefinition0 < OpenWFE::ProcessDefinition
        sequence do
            participant "alpha"
            participant "bravo"
            participant "charly"
        end
    end

pattern rdoc

set

これは変数に値をセットしたり、 workitem のフィールド(attribute) に値をセットするのに使います。

これはプロセス定義本体の外側に置かれ、本体が適用(実行)される前に評価されます。

    require 'openwfe/def'

    class MyDefinition0 < OpenWFE::ProcessDefinition
        sequence do
            participant "alpha"
        end

        set :field => "city", :value => "Kyoto"
        set :field => "country", :value => "Japan"
    end

participant である ‘alpha’ は ‘city’ ・ ‘country’ フィールドにそれぞれ ‘Kyoto’ ・ ‘Japan’ とセットされた workitem を受け取ります。このテクニックはプロセスのロジック自体と関係ない長期の設定に便利です。

unset はプロセス本体の外側には置けません。Filter definitions は置けます。

rdoc

sleep

rdoc

subprocess

rdoc

undefined

rdoc

undo

全ての expression は暗黙に ‘tag’ attribute を受け入れます。これは評価前の expression のコピーの名前を定義するもので、 (タグで示された expression で受け取るように)適用する workitem 内に保持されます。

この名前 (タグ) はa ‘redo’ や ‘undo’ expression に使われます。

    concurrence do
        sequence :tag => "side_job" do
            participant "alice"
            participant "bob"
        end
        sequence do
            participant "charly"
            _undo :ref => "side_job"
        end
    end

この例で、participant の ‘charly’ が自分の仕事をした後で、最初の sequence (‘side_job’ というタグ) はキャンセルされます (そして親に当たる ‘concurrence’ にトリガーとなるよう返します)。

rdoc

unset

rdoc

v

“variable” の短縮形です。

variable

rdoc

when

rdoc

wait

rdoc