# #-- # Copyright (c) 2006-2007, John Mettraux, OpenWFE.org # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # . Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # . Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # . Neither the name of the "OpenWFE" nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #++ # # # "made in Japan" # # John Mettraux at openwfe.org # require 'openwfe/workitem' require 'openwfe/flowexpressionid' require 'openwfe/expressions/condition' require 'openwfe/expressions/flowexpression' # # expressions like 'set' and 'unset' and their utility methods # module OpenWFE # # The 'if' expression. # # # # # # # It accepts an 'else' clause : # # # # # # # # The 'test' attribute can be used instead of a condition child : # # # # # # The 'rtest' attribute can be used to embed a condition expressed directly # in Ruby : # # # # # # (Note that 'rtest' may only be used if the :ruby_eval_allowed # parameter has been set in the engine's application_context : # # engine.application_context[:ruby_eval_allowed] = true # # but this is dangerous if the origin of the process defintions to run # are not trusted) # # Used alone with 'test' or 'rtest', the 'if' expression simply sets the # the __result__ field of its workitem to the result of its attribute # evaluation : # # # # will set the __result__ field of the workitem to 'false'. # class IfExpression < FlowExpression include ConditionMixin names :if attr_accessor \ :condition_replied def apply (workitem) workitem.unset_result test = eval_condition(:test, workitem, :not) if @children.length < 1 workitem.set_result test if test reply_to_parent(workitem) return end @condition_replied = (test != nil) # # if the "test" attribute is not used, test will be null store_itself() if test != nil apply_consequence(test, workitem, 0) else get_expression_pool.apply(@children[0], workitem) end end def reply (workitem) if @condition_replied reply_to_parent(workitem) return end result = workitem.attributes[FIELD_RESULT] @condition_replied = true store_itself() apply_consequence result, workitem end def reply_to_parent(workitem) clean_children() super workitem end protected def apply_consequence (index, workitem, offset=1) if index == true index = 0 elsif index == false index = 1 elsif index == nil index = 1 elsif not index.integer? index = 0 end index = index + offset if index >= @children.length reply_to_parent workitem else get_expression_pool.apply @children[index], workitem end end end # # The 'case' expression. # # # # # # # # # # # # # # A generalized 'if'. Will evaluate its children, expecting the order : # # - condition # - consequence # - condition # - consequence # ... # - else consequence (optional) # # The 'switch' nickname can be used for 'case'. # class CaseExpression < FlowExpression names :case, :switch attr_accessor \ :offset, :evaluating_condition def apply (workitem) workitem.unset_result @offset = nil trigger_child workitem, true end def reply (workitem) if @evaluating_condition result = workitem.get_boolean_result #ldebug { "reply() result : '#{result.to_s}' (#{result.class})" } trigger_child workitem, !result else reply_to_parent workitem end end protected def trigger_child (workitem, is_condition) @offset = if !@offset 0 elsif is_condition @offset + 2 else @offset + 1 end #ldebug { "trigger_child() is_condition ? #{is_condition}" } #ldebug { "trigger_child() next offset is #{@offset}" } unless @children[@offset] reply_to_parent workitem return end @evaluating_condition = is_condition store_itself get_expression_pool.apply(@children[@offset], workitem) end end end