Class Ruote::Exp::CursorExpression
In: lib/ruote/exp/fe_cursor.rb
Parent: CommandedExpression

This class implements the ‘cursor’ and the ‘repeat’ (loop) expressions.

The cursor expression is a kind of enhanced ‘sequence’. Like a sequence it will execute its child expression one by one, sequentially. Unlike a sequence though, it will obey ‘commands’.

  cursor do
    author
    reviewer
    rewind :if => '${f:not_ok}'
    publisher
  end

In this simplistic example, the process will flow from author to reviewer and back until the reviewer sets the workitem field ‘not_ok’ to something else than the value ‘true’.

There are two ways to pass commands to a cursor either directly from the process definition with a cursor command expression, either via the workitem ‘command’ [special] field.

cursor commands

The commands that a cursor understands are listed here. The most powerful ones are ‘rewind’ and ‘jump’.

rewind

Rewinds the cursor up to its first child expression.

  cursor do
    author
    reviewer
    rewind :if => '${f:not_ok}'
    publisher
  end

stop, over & break

Exits the cursor.

  cursor do
    author
    reviewer
    rewind :if => '${f:review} == fix'
    stop :if => '${f:review} == abort'
    publisher
  end

‘_break’ or ‘over’ can be used instead of ‘stop’.

skip & back

Those two commands jump forth and back respectively. By default, they skip 1 child, but they accept a numeric parameter holding the number of children to skip.

  cursor do
    author
    reviewer
    rewind :if => '${f:review} == fix'
    skip 2 :if => '${f:review} == publish'
    reviewer2
    rewind :if => '${f:review} == fix'
    publisher
  end

jump

Jump is probably the most powerful of the cursor commands. It allows to jump to a specified expression that is a direct child of the cursor.

  cursor do
    author
    reviewer
    jump :to => 'author', :if => '${f:review} == fix'
    jump :to => 'publisher', :if => '${f:review} == publish'
    reviewer2
    jump :to => 'author', :if => '${f:review} == fix'
    publisher
  end

Note that the :to accepts the name of an expression or the value of its :ref attribute or the value of its :tag attribute.

  cursor do
    participant :ref => 'author'
    participant :ref => 'reviewer'
    jump :to => 'author', :if => '${f:review} == fix'
    participant :ref => 'publisher'
  end

cursor command with :ref

It‘s OK to tag a cursor/repeat/loop with the :tag attribute and then point a command to it via :ref :

  concurrence do

    cursor :tag => 'main' do
      author
      editor
      publisher
    end

    # meanwhile ...

    sequence do
      sponsor
      rewind :ref => 'main', :if => '${f:stop}'
    end
  end

This :ref technique may also be used with nested cursor/loop/iterator constructs :

  cursor :tag => 'main' do
    cursor do
      author
      editor
      rewind :if => '${f:not_ok}'
      _break :ref => 'main', :if => '${f:abort_everything}'
    end
    head_of_edition
    rewind :if => '${f:not_ok}'
    publisher
  end

this example features two nested cursors. There is a "_break" in the inner cursor, but it will break the main ‘cursor’ (and thus break the whole review process).

:break_if / :rewind_if

As an attribute of the cursor/repeat expression, you can set a :break_if. It tells the cursor (loop) if it has to break.

  cursor :break_if => '${f:completed}' do
    participant 'alpha'
    participant 'bravo'
    participant 'charly'
  end

If alpha or bravo replies and the field ‘completed’ is set to true, this cursor will break.

:break_unless is accepted. :over_if and :over_unless are synonyms for :break_if and :break_unless respectively.

:rewind_if / :rewind_unless behave the same, but the cursor/loop, instead of breaking, is put back in its first step.

repeat (loop)

A ‘cursor’ expression exits implicitely as soon as its last child replies to it. a ‘repeat’ expression will apply (again) the first child after the last child replied. A ‘break’ cursor command might be necessary to exit the loop (or a cancel_process, but that exits the whole process instance).

  sequence do
    repeat do
      author
      reviewer
      _break :if => '${f:review} == ok'
    end
    publisher
  end

Methods

apply   is_loop?   jump_to   move_on  

Public Instance methods

Protected Instance methods

Jumps to an integer position, or the name of an expression or a tag name of a ref name.

[Validate]