lib/openwfe/expressions/fe_cursor.rb in openwferu-0.9.8 vs lib/openwfe/expressions/fe_cursor.rb in openwferu-0.9.9

- old
+ new

@@ -58,17 +58,42 @@ C_SKIP = "skip" C_BREAK = "break" C_CANCEL = "cancel" C_REWIND = "rewind" C_CONTINUE = "continue" + C_JUMP = "jump" A_STEP = "step" # # The 'cursor' is much like a sequence, but you can go - # back and forth within it. + # back and forth within it, as it reads the field '\_\_cursor_command__' (or + # the field specified in the 'command-field' attribute) at each + # transition (each time it's supposed to move from one child expression to + # the next). # + # cursor do + # participant "alpha" + # skip :step => "2" + # participant "bravo" + # participant "charly" + # set :field => "__cursor_command__", value => "2" + # participant "delta" + # participant "echo" + # skip 2 + # participant "fox" + # # + # # in that cursor example, only the participants alpha, charly and + # # echo will be handed a workitem + # # (notice the last 'skip' with its light syntax) + # # + # end + # + # As you can see, you can directly set the value of the field + # '\_\_cursor_command__' or use a CursorCommandExpression like 'skip' or + # 'jump'. + # class CursorExpression < WithTemplateExpression names :cursor attr_accessor \ @@ -98,26 +123,40 @@ # reply_to_parent(workitem) return end - command_field = lookup_command_field(workitem) - command = lookup_command(command_field, workitem) - disallow_list = lookup_disallow(workitem) + command_field = lookup_command_field workitem + command, step = lookup_command command_field, workitem + + disallow_list = lookup_disallow workitem + command = nil \ - if disallow_list and disallow_list.include? command + if disallow_list and disallow_list.include?(command) + ldebug { "reply() command is '#{command} #{step}'" } + if command == C_BREAK or command == C_CANCEL - reply_to_parent(workitem) + reply_to_parent workitem return end if command == C_REWIND or command == C_CONTINUE + @current_child_id = 0 - else - step = lookup_step(command) + + elsif command and command.match "^#{C_JUMP}" + + @current_child_id = step + @current_child_id = 0 if @current_child_id < 0 + + @current_child_id = @children.length - 1 \ + if @current_child_id >= @children.length + + else # C_SKIP or C_BACK + @current_child_id = @current_child_id + step @current_child_id = 0 if @current_child_id < 0 if @current_child_id >= @children.length @@ -146,91 +185,155 @@ end # # takes care of cancelling the current child if necessary # - def cancel () + def cancel get_expression_pool.cancel(@current_child_fei) \ if @current_child_fei - super() + super end # - # returns false, the child class LoopExpression does return true. + # Returns false, the child class LoopExpression does return true. # def is_loop - return false + false end protected - def lookup_step (command) - - return 1 if not command - - step = 1 - - ss = command.split() - - if ss.length > 1 - step = Integer(ss[1]) - end - - step = -step if OpenWFE::starts_with(command, C_BACK) - - return step - end - + # + # Makes sure that only flow expression are left in the cursor + # children list (text and comment nodes get discarded). + # def clean_children_list c = @children @children = [] c.each do |child| @children << child \ - if child.kind_of? OpenWFE::FlowExpressionId + if child.kind_of?(OpenWFE::FlowExpressionId) end end + # + # Looks up the value in the command field. + # def lookup_command_field (workitem) - return lookup_attribute(A_COMMAND_FIELD, workitem, F_COMMAND) + lookup_attribute(A_COMMAND_FIELD, workitem, F_COMMAND) end + # + # Returns the command and the step + # def lookup_command (command_field, workitem) command = workitem.attributes[command_field] - command = command.strip() if command - return command + return [ nil, 1 ] unless command + # + # this corresponds to the "just one step forward" default + + command, step = command.strip.split + + step = if step + step.to_i + else + 1 + end + + step = -step if command == C_BACK + + [ command, step ] end + # + # Fetches the value of the 'disallow' cursor attribute. + # def lookup_disallow (workitem) - return lookup_comma_list_attribute(A_DISALLOW, workitem) + lookup_comma_list_attribute(A_DISALLOW, workitem) end end # # The 'loop' expression is like 'cursor' but it doesn't exit until - # it's broken. + # it's broken (with 'break' or 'cancel'). # class LoopExpression < CursorExpression names :loop def is_loop - return true + true end end # - # 'skip', 'continue', and the like + # This class implements the following expressions : back, break, + # cancel, continue, jump, rewind, skip. # + # They are generally used inside of a 'cursor' (CursorExpression) or + # a 'loop' (LoopExpression), they can be used outside, but their result + # (the value of the field '\_\_cursor_command__' will be used as soon as the + # flow enters a cursor or a loop). + # + # In fact, this expression is only a nice wrapper that sets the + # value of the field "\_\_cursor_command__" to its name ('back' for example) + # plus to the 'step' attribute value. + # + # For example <skip step="3"/> simply sets the value of the field + # '\_\_cursor_command__' to 'skip 3'. + # + # (The field \_\_cursor_command__ is, by default, read and + # obeyed by the 'cursor' expression). + # + # With Ruby process definitions, you can directly write : + # + # skip 2 + # jump "0" + # + # instead of + # + # skip :step => "2" + # jump :step => "0" + # + # Likewise, in an XML process definition, you can write + # + # <skip>2</skip> + # + # although that might still look lighter (it's longer though) : + # + # <skip step="2"/> + # + # + # About the command themselves : + # + # * back : will go back from the number of given steps, 1 by default + # * break : will exit the cursor (or the loop) + # * cancel : an alias for 'break' + # * continue : will exit the cursor, if in a loop, will get back at step 0 + # * jump : will move the cursor (or loop) to an absolute given position (count starts at 0) + # * rewind : an alias for continue + # * skip : skips the given number of steps + # + # + # All those command support an 'if' attribute to restrict their execution : + # + # cursor do + # go_to_shop + # check_prices + # _break :if => "${price} > ${f:current_cash}" + # buy_stuff + # end + # class CursorCommandExpression < FlowExpression include ConditionMixin - names :back, :skip, :continue, :break, :cancel, :rewind + names :back, :skip, :continue, :break, :cancel, :rewind, :jump def apply (workitem) conditional = eval_condition(:if, workitem) # @@ -238,18 +341,20 @@ if conditional == nil or conditional command = @fei.expression_name - step = lookup_attribute(A_STEP, workitem, "1") + step = lookup_attribute(A_STEP, workitem) + step = fetch_text_content(workitem) unless step + step = 1 unless step step = Integer(step) - command = "#{command} #{step}" if step != 1 + command = "#{command} #{step}" #if step != 1 workitem.attributes[F_COMMAND] = command end - reply_to_parent(workitem) + reply_to_parent workitem end end end