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

- old
+ new

@@ -35,387 +35,379 @@ # "made in Japan" # # John Mettraux at openwfe.org # -require 'rufus/eval' require 'openwfe/expressions/flowexpression' require 'openwfe/expressions/value' +require 'openwfe/util/treechecker' module OpenWFE - # - # The 'description' expression, simply binds the given text in - # the 'description' variable in the current process. - # - # class TestDefinition2 < OpenWFE::ProcessDefinition - # - # description :lang => "fr" do "rien de rien" end - # - # sequence do - # _print "${description}" - # _print "${description__fr}" - # end - # end - # - class DescriptionExpression < FlowExpression - include ValueMixin + # + # The 'description' expression, simply binds the given text in + # the 'description' variable in the current process. + # + # class TestDefinition2 < OpenWFE::ProcessDefinition + # + # description :lang => "fr" do "rien de rien" end + # + # sequence do + # _print "${description}" + # _print "${description__fr}" + # end + # end + # + class DescriptionExpression < FlowExpression + include ValueMixin - is_definition + is_definition - names :description + names :description - DESC = 'description' + DESC = 'description' - def reply (workitem) + def reply (workitem) - lang = - lookup_attribute(:lang, workitem) || - lookup_attribute(:language, workitem) + lang = + lookup_attribute(:lang, workitem) || + lookup_attribute(:language, workitem) - vname = DESC - vname += "__#{lang}" if lang + vname = DESC + vname += "__#{lang}" if lang - text = lookup_attribute('text', workitem) || workitem.get_result + text = lookup_attribute('text', workitem) || workitem.get_result - set_variable(vname, text) - set_variable(DESC, text) unless lookup_variable(DESC) - # set default if not set + set_variable(vname, text) + set_variable(DESC, text) unless lookup_variable(DESC) + # set default if not set - reply_to_parent workitem - end + reply_to_parent workitem end + end - # - # A debug/test expression (it's mostly used in the test suite - # used for the development of OpenWFEru). - # Outputs a message to the STDOUT (via the "puts" Ruby method). - # - # <print>hello</print> - # - # _print "hello" - # _print do - # "in a block" - # end - # - # Note that when expressing the process in Ruby, an underscore has to be - # placed in front of the expression name to avoid a collision with the - # Ruby 'print' function. - # - # If there is an object bound in the application context under the - # name '__tracer', this expression will append its message to this - # instance instead of emitting to the STDOUT. (this is how the - # OpenWFEru test suite uses this expression). - # - class PrintExpression < FlowExpression - include ValueMixin + # + # A debug/test expression (it's mostly used in the test suite + # used for the development of OpenWFEru). + # Outputs a message to the STDOUT (via the "puts" Ruby method). + # + # <print>hello</print> + # + # _print "hello" + # _print do + # "in a block" + # end + # + # Note that when expressing the process in Ruby, an underscore has to be + # placed in front of the expression name to avoid a collision with the + # Ruby 'print' function. + # + # If there is an object bound in the application context under the + # name '__tracer', this expression will append its message to this + # instance instead of emitting to the STDOUT. (this is how the + # OpenWFEru test suite uses this expression). + # + class PrintExpression < FlowExpression + include ValueMixin - names :print + names :print - def reply (workitem) + def reply (workitem) - text = workitem.get_result.to_s - text << "\n" + text = workitem.get_result.to_s + text << "\n" - tracer = @application_context['__tracer'] + tracer = @application_context['__tracer'] - if tracer - tracer << text - else - puts text - end + if tracer + tracer << text + else + puts text + end - reply_to_parent workitem - end + reply_to_parent workitem end + end - # - # Evals some Ruby code contained within the process definition - # or within the workitem. - # - # The code is evaluated at a SAFE level of 3. - # - # If the :ruby_eval_allowed isn't set to true - # (<tt>engine.application_context[:ruby_eval_allowed] = true</tt>), this - # expression will throw an exception at apply. - # - # some examples : - # - # <reval> - # workitem.customer_name = "doug" - # # or for short - # wi.customer_address = "midtown 21_21 design" - # </reval> - # - # in a Ruby process definition : - # - # sequence do - # _set :field => "customer" do - # reval """ - # { - # :name => "Cheezburger", - # :age => 34, - # :comment => "I can haz ?", - # :timestamp => Time.now.to_s - # } - # """ - # end - # end - # - # Don't embed too much Ruby into your process definitions, it might - # hurt... - # - # Reval can also be used with the 'code' attribute (or 'field-code' or - # 'variable-code') : - # - # <reval field-code="f0" /> - # - # to eval the Ruby code held in the field named "f0". - # - class RevalExpression < FlowExpression - include ValueMixin + # + # Evals some Ruby code contained within the process definition + # or within the workitem. + # + # If the :ruby_eval_allowed isn't set to true + # (<tt>engine.application_context[:ruby_eval_allowed] = true</tt>), this + # expression will throw an exception at apply. + # + # some examples : + # + # <reval> + # workitem.customer_name = "doug" + # # or for short + # wi.customer_address = "midtown 21_21 design" + # </reval> + # + # in a Ruby process definition : + # + # sequence do + # _set :field => "customer" do + # reval """ + # { + # :name => "Cheezburger", + # :age => 34, + # :comment => "I can haz ?", + # :timestamp => Time.now.to_s + # } + # """ + # end + # end + # + # Don't embed too much Ruby into your process definitions, it might + # hurt... + # + # Reval can also be used with the 'code' attribute (or 'field-code' or + # 'variable-code') : + # + # <reval field-code="f0" /> + # + # to eval the Ruby code held in the field named "f0". + # + class RevalExpression < FlowExpression + include ValueMixin - names :reval + names :reval - # - # See for an explanation on Ruby safety levels : - # http://www.rubycentral.com/book/taint.html - # - # 'reval' is entitled a safe level of 3. - # - SAFETY_LEVEL = 3 + def reply (workitem) - def reply (workitem) + raise 'evaluation of ruby code is not allowed' \ + if @application_context[:ruby_eval_allowed] != true - raise "evaluation of ruby code is not allowed" \ - if @application_context[:ruby_eval_allowed] != true + code = lookup_vf_attribute(workitem, 'code') || workitem.get_result + code = code.to_s - code = lookup_vf_attribute(workitem, 'code') || workitem.get_result - code = code.to_s + wi = workitem + # so that the ruby code being evaluated sees 'wi' and 'workitem' - wi = workitem - # so that the ruby code being evaluated sees 'wi' and 'workitem' + get_tree_checker.check code - result = Rufus::eval_safely code, SAFETY_LEVEL, binding() + result = eval code, binding() - workitem.set_result(result) \ - if result != nil # 'false' is a valid result + workitem.set_result(result) \ + if result != nil # as 'false' is a valid result - reply_to_parent workitem - end + reply_to_parent workitem end + end - # - # An advanced expression : it takes the value in a field or variable (or - # the nested value) and evaluates it as a process definition. - # - # sequence - # set :field => "code", :value => "<print>hello 0</print>" - # _eval :field_def => "code" - # set :field => "code", :value => "_print 'hello 1'" - # _eval :field_def => "code" - # end - # - # will print "hello0\nhello1". - # - # This expression can be useful for evaluating process definition snippets - # coming from participants directly. - # - # It's also dangerous. This 'eval' expression will raise an error if - # the parameter :dynamic_eval_allowed in the engine's application context - # is not set to true. - # - class EvalExpression < FlowExpression - include ValueMixin + # + # An advanced expression : it takes the value in a field or variable (or + # the nested value) and evaluates it as a process definition. + # + # sequence + # set :field => "code", :value => "<print>hello 0</print>" + # _eval :field_def => "code" + # set :field => "code", :value => "_print 'hello 1'" + # _eval :field_def => "code" + # end + # + # will print "hello0\nhello1". + # + # This expression can be useful for evaluating process definition snippets + # coming from participants directly. + # + # It's also dangerous. This 'eval' expression will raise an error if + # the parameter :dynamic_eval_allowed in the engine's application context + # is not set to true. + # + class EvalExpression < FlowExpression + include ValueMixin - names :eval + names :eval - def reply (workitem) + def reply (workitem) - raise "dynamic evaluation of process definitions is not allowed" \ - if @application_context[:dynamic_eval_allowed] != true + raise "dynamic evaluation of process definitions is not allowed" \ + if @application_context[:dynamic_eval_allowed] != true - df = lookup_vf_attribute(workitem, 'def') || workitem.get_result + df = lookup_vf_attribute(workitem, 'def') || workitem.get_result - return reply_to_parent(workitem) unless df - # - # currently, 'nothing to eval' means, 'just go on' + return reply_to_parent(workitem) unless df + # + # currently, 'nothing to eval' means, 'just go on' - ldebug { "apply() def is >#{df}<" } + ldebug { "apply() def is >#{df}<" } - raw_expression = build_raw_expression df + raw_expression = build_raw_expression df - #puts - #puts "======================================" - #puts raw_expression.to_s - #puts raw_expression.raw_representation - #puts "======================================" - #puts + #puts + #puts "======================================" + #puts raw_expression.to_s + #puts raw_expression.raw_representation + #puts "======================================" + #puts - raw_expression.apply workitem - end + raw_expression.apply workitem + end - protected + protected - def build_raw_expression (df) + def build_raw_expression (df) - procdf = get_expression_pool.determine_rep df + procdf = get_expression_pool.determine_rep df - RawExpression.new_raw( - fei, parent_id, environment_id, application_context, procdf) - end - end + RawExpression.new_raw( + fei, parent_id, environment_id, application_context, procdf) + end + end - # - # Some kind of limited 'eval' expression. - # - # Here is an usage example : - # - # class ExampleDef < OpenWFE::ProcessDefinition - # - # sequence do - # - # exp :name => "p0" - # exp :name => "sub0" - # - # exp :name => "sequence" do - # p0 - # sub0 - # end - # - # set :var => "a", :value => { "ref" => "p0" } - # exp :name => "participant", :variable_attributes => "a" - # end - # - # process_definition :name => "sub0" do - # _print "sub0" - # end - # end - # - # This example is a bit static, but the point is that the 'exp' - # is extracting the real expression name (or participant or subprocess - # name) from its 'name' attribute. - # - # The 'eval' expression is about evaluating a complete process definition - # branch, 'exp' is only about one node in the process definition. - # - class ExpExpression < RawExpression + # + # Some kind of limited 'eval' expression. + # + # Here is an usage example : + # + # class ExampleDef < OpenWFE::ProcessDefinition + # + # sequence do + # + # exp :name => "p0" + # exp :name => "sub0" + # + # exp :name => "sequence" do + # p0 + # sub0 + # end + # + # set :var => "a", :value => { "ref" => "p0" } + # exp :name => "participant", :variable_attributes => "a" + # end + # + # process_definition :name => "sub0" do + # _print "sub0" + # end + # end + # + # This example is a bit static, but the point is that the 'exp' + # is extracting the real expression name (or participant or subprocess + # name) from its 'name' attribute. + # + # The 'eval' expression is about evaluating a complete process definition + # branch, 'exp' is only about one node in the process definition. + # + class ExpExpression < RawExpression - names :exp + names :exp - #-- - #def initialize (fei, parent_id, env_id, app_context, att) - # # - # # this responds to the FlowExpression constructor... - # super fei, parent_id, env_id, app_context, nil - # # - # # but this triggers the RawExpression constructor :) - # @attributes = att - # # - # # as this is not done by the RawExpression constructor - #end - #++ + #-- + #def initialize (fei, parent_id, env_id, app_context, att) + # # + # # this responds to the FlowExpression constructor... + # super fei, parent_id, env_id, app_context, nil + # # + # # but this triggers the RawExpression constructor :) + # @attributes = att + # # + # # as this is not done by the RawExpression constructor + #end + #++ - def apply (workitem) + def apply (workitem) - @applied_workitem = workitem + @applied_workitem = workitem - super - end + super + end - protected + protected - # - # Evaluates the 'name' attribute, if it's not present or empty, - # will return the value for the 'default' attribute. - # - def expression_name + # + # Evaluates the 'name' attribute, if it's not present or empty, + # will return the value for the 'default' attribute. + # + def expression_name - n = lookup_attribute :name, @applied_workitem + n = lookup_attribute :name, @applied_workitem - return lookup_attribute(:default, @applied_workitem) \ - if (not n) or (n.strip == '') + return lookup_attribute(:default, @applied_workitem) \ + if (not n) or (n.strip == '') - n - end + n + end - # - # If the 'attributes' attribute is present, will return its - # value. Else, will simply return the attributes of the 'exp' - # expression itself ('name' and 'default' included). - # - def extract_attributes + # + # If the 'attributes' attribute is present, will return its + # value. Else, will simply return the attributes of the 'exp' + # expression itself ('name' and 'default' included). + # + def extract_attributes - att = lookup_vf_attribute @applied_workitem, :attributes - # will currently only work with an attribute hash - # whose keys are strings... symbols :( + att = lookup_vf_attribute @applied_workitem, :attributes + # will currently only work with an attribute hash + # whose keys are strings... symbols :( - att || @attributes - end + att || @attributes + end - #-- - #def extract_descriptions - # [] - #end - #++ + #-- + #def extract_descriptions + # [] + #end + #++ - def extract_children - @children - end + def extract_children + @children + end - def extract_parameters - [] - end - end + def extract_parameters + [] + end + end - # - # This expression simply emits a message to the application - # log (by default logs/openwferu.log). - # - # <sequence> - # <log>before participant alpha</log> - # <participant ref="alpha" /> - # <log>after participant alpha</log> - # <log level="warn">after participant alpha</log> - # </sequence> - # - # And an example with a Ruby process definition : - # - # sequence do - # log "simple debug message" - # log do - # "another debug message" - # end - # log :message => "yet another debug message" - # log :message => "an info level message", :level => "info" - # end - # - # Possible log levels are 'debug' (the default), 'info', 'warn' and - # 'fatal'. - # - class LogExpression < FlowExpression - include ValueMixin + # + # This expression simply emits a message to the application + # log (by default logs/openwferu.log). + # + # <sequence> + # <log>before participant alpha</log> + # <participant ref="alpha" /> + # <log>after participant alpha</log> + # <log level="warn">after participant alpha</log> + # </sequence> + # + # And an example with a Ruby process definition : + # + # sequence do + # log "simple debug message" + # log do + # "another debug message" + # end + # log :message => "yet another debug message" + # log :message => "an info level message", :level => "info" + # end + # + # Possible log levels are 'debug' (the default), 'info', 'warn' and + # 'fatal'. + # + class LogExpression < FlowExpression + include ValueMixin - names :log + names :log - def reply (workitem) + def reply (workitem) - text = lookup_attribute('message', workitem) || workitem.get_result + text = lookup_attribute('message', workitem) || workitem.get_result - level = lookup_attribute('level', workitem) - level = level.downcase.to_sym if level + level = lookup_attribute('level', workitem) + level = level.downcase.to_sym if level - level = :debug \ - unless [ :info, :warn, :error, :fatal ].include?(level) + level = :debug \ + unless [ :info, :warn, :error, :fatal ].include?(level) - get_engine.llog(level, text) if text + get_engine.llog(level, text) if text - reply_to_parent workitem - end + reply_to_parent workitem end + end end