lib/openwfe/expressions/fe_if.rb in ruote-0.9.18 vs lib/openwfe/expressions/fe_if.rb in ruote-0.9.19

- old
+ new

@@ -1,34 +1,34 @@ # #-- # Copyright (c) 2006-2008, John Mettraux, OpenWFE.org # All rights reserved. -# -# Redistribution and use in source and binary forms, with or without +# +# 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 +# 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 +# +# 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. #++ # # @@ -47,257 +47,257 @@ # expressions like 'set' and 'unset' and their utility methods # module OpenWFE + # + # The 'if' expression. + # + # <if> + # <equals field-value="f0" other-value="true" /> + # <participant ref="alpha" /> + # </if> + # + # It accepts an 'else' clause : + # + # <if> + # <equals field-value="f0" other-value="true" /> + # <participant ref="alpha" /> + # <participant ref="bravo" /> + # </if> + # + # The 'test' attribute can be used instead of a condition child : + # + # <if test="${f:f0}"> + # <participant ref="alpha" /> + # </if> + # + # The 'rtest' attribute can be used to embed a condition expressed directly + # in Ruby : + # + # <if rtest="5 * 12 == 61"> + # <participant ref="alpha" /> + # </if> + # + # (Note that 'rtest' may only be used if the <tt>:ruby_eval_allowed</tt> + # 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 : + # + # <if test="5 == 6"/> + # + # will set the __result__ field of the workitem to 'false'. + # + class IfExpression < FlowExpression + include ConditionMixin + + names :if + # - # The 'if' expression. + # This boolean is set to true when the conditional claused has + # been evaluated and the 'if' is waiting for the consequence's + # reply. # - # <if> - # <equals field-value="f0" other-value="true" /> - # <participant ref="alpha" /> - # </if> - # - # It accepts an 'else' clause : - # - # <if> - # <equals field-value="f0" other-value="true" /> - # <participant ref="alpha" /> - # <participant ref="bravo" /> - # </if> - # - # The 'test' attribute can be used instead of a condition child : - # - # <if test="${f:f0}"> - # <participant ref="alpha" /> - # </if> - # - # The 'rtest' attribute can be used to embed a condition expressed directly - # in Ruby : - # - # <if rtest="5 * 12 == 61"> - # <participant ref="alpha" /> - # </if> - # - # (Note that 'rtest' may only be used if the <tt>:ruby_eval_allowed</tt> - # 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 : - # - # <if test="5 == 6"/> - # - # will set the __result__ field of the workitem to 'false'. - # - class IfExpression < FlowExpression - include ConditionMixin + attr_accessor :condition_replied - names :if + def apply (workitem) + + #workitem.unset_result # - # This boolean is set to true when the conditional claused has - # been evaluated and the 'if' is waiting for the consequence's - # reply. - # - attr_accessor :condition_replied + # since OpenWFEru 0.9.16 previous __result__ values + # are not erased before an 'if'. + test = eval_condition :test, workitem, :not - def apply (workitem) + if @children.length < 1 + #workitem.set_result test if test + workitem.set_result((test != nil and test != false)) + reply_to_parent workitem + return + end - #workitem.unset_result - # - # since OpenWFEru 0.9.16 previous __result__ values - # are not erased before an 'if'. + @condition_replied = (test != nil) + # + # if the "test" attribute is not used, test will be null - test = eval_condition :test, workitem, :not + store_itself - if @children.length < 1 - #workitem.set_result test if test - workitem.set_result((test != nil and test != false)) - reply_to_parent workitem - return - end + # a warning - @condition_replied = (test != nil) - # - # if the "test" attribute is not used, test will be null + maxchildren = (test == nil) ? 3 : 2 - store_itself + lwarn { + "apply() 'if' with more than #{maxchildren} children" + } if @children.size > maxchildren - # a warning + # apply next step - maxchildren = (test == nil) ? 3 : 2 + if test != nil + # + # apply then or else (condition result known) + # + apply_consequence test, workitem, 0 + else + # + # apply condition + # + get_expression_pool.apply @children.first, workitem + end + end - lwarn { - "apply() 'if' with more than #{maxchildren} children" - } if @children.size > maxchildren + def reply (workitem) - # apply next step + return reply_to_parent(workitem) \ + if @condition_replied - if test != nil - # - # apply then or else (condition result known) - # - apply_consequence test, workitem, 0 - else - # - # apply condition - # - get_expression_pool.apply @children.first, workitem - end - end + result = workitem.attributes[FIELD_RESULT] - def reply (workitem) + @condition_replied = true - return reply_to_parent(workitem) \ - if @condition_replied + store_itself - result = workitem.attributes[FIELD_RESULT] + apply_consequence result, workitem + end - @condition_replied = true + # + # This reply_to_parent takes care of cleaning all the children + # before replying to the parent expression, this is important + # because only the 'then' or the 'else' child got evaluated, the + # remaining one has to be cleaned out here. + # + def reply_to_parent (workitem) - store_itself + clean_children + super workitem + end - apply_consequence result, workitem - end + protected - # - # This reply_to_parent takes care of cleaning all the children - # before replying to the parent expression, this is important - # because only the 'then' or the 'else' child got evaluated, the - # remaining one has to be cleaned out here. - # - def reply_to_parent (workitem) + def apply_consequence (index, workitem, offset=1) - clean_children - super workitem + if index == true + index = 0 + elsif index == false + index = 1 + elsif index == nil + index = 1 + elsif not index.integer? + index = 0 end - protected + index = index + offset - def apply_consequence (index, workitem, offset=1) + if index >= @children.length + reply_to_parent workitem + else + get_expression_pool.apply @children[index], workitem + end + end + end - if index == true - index = 0 - elsif index == false - index = 1 - elsif index == nil - index = 1 - elsif not index.integer? - index = 0 - end + # + # The 'case' expression. + # + # <case> + # + # <equals field="f0" other-value="ready" /> + # <participant ref="alpha" /> + # + # <if test="${supply_level} == ${field:supply_request}" /> + # <participant ref="bravo" /> + # + # <participant ref="charly" /> + # + # </case> + # + # 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 - index = index + offset + names :case, :switch - if index >= @children.length - reply_to_parent workitem - else - get_expression_pool.apply @children[index], workitem - end - end - end - # - # The 'case' expression. + # keeping track of where we are in the case iteration # - # <case> + attr_accessor :offset + # - # <equals field="f0" other-value="ready" /> - # <participant ref="alpha" /> + # set to 'true' when the case expression is actually evaluating + # a condition (ie not triggering a consequence). # - # <if test="${supply_level} == ${field:supply_request}" /> - # <participant ref="bravo" /> - # - # <participant ref="charly" /> - # - # </case> - # - # 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 + attr_accessor :evaluating_condition - names :case, :switch - # - # keeping track of where we are in the case iteration - # - attr_accessor :offset + def apply (workitem) + #workitem.unset_result # - # set to 'true' when the case expression is actually evaluating - # a condition (ie not triggering a consequence). - # - attr_accessor :evaluating_condition + # since OpenWFEru 0.9.16 previous __result__ values + # are not erased before a 'case'. + @offset = nil - def apply (workitem) + trigger_child workitem, true + end - #workitem.unset_result - # - # since OpenWFEru 0.9.16 previous __result__ values - # are not erased before a 'case'. + def reply (workitem) - @offset = nil + if @evaluating_condition - trigger_child workitem, true - end + result = workitem.get_boolean_result - def reply (workitem) + #ldebug { "reply() result : '#{result.to_s}' (#{result.class})" } - if @evaluating_condition + trigger_child workitem, !result + else - result = workitem.get_boolean_result + reply_to_parent workitem + end + end - #ldebug { "reply() result : '#{result.to_s}' (#{result.class})" } + protected - trigger_child workitem, !result - else + def trigger_child (workitem, is_condition) - reply_to_parent workitem - end + @offset = if !@offset + 0 + elsif is_condition + @offset + 2 + else + @offset + 1 end - protected + #ldebug { "trigger_child() is_condition ? #{is_condition}" } + #ldebug { "trigger_child() next offset is #{@offset}" } - def trigger_child (workitem, is_condition) + unless @children[@offset] + reply_to_parent workitem + return + end - @offset = if !@offset - 0 - elsif is_condition - @offset + 2 - else - @offset + 1 - end + @evaluating_condition = is_condition - #ldebug { "trigger_child() is_condition ? #{is_condition}" } - #ldebug { "trigger_child() next offset is #{@offset}" } + store_itself - unless @children[@offset] - reply_to_parent workitem - return - end - - @evaluating_condition = is_condition - - store_itself - - get_expression_pool.apply(@children[@offset], workitem) - end - end + get_expression_pool.apply(@children[@offset], workitem) + end + end end