lib/openwfe/expressions/rprocdef.rb in ruote-0.9.19 vs lib/openwfe/expressions/rprocdef.rb in ruote-0.9.20

- old
+ new

@@ -1,52 +1,75 @@ -# #-- -# Copyright (c) 2007-2008, John Mettraux, OpenWFE.org -# All rights reserved. +# Copyright (c) 2007-2009, John Mettraux, jmettraux@gmail.com # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -# . Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -# . 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. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. # -# . 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. #++ -# -# -# "made in Japan" -# -# John Mettraux at openwfe.org -# require 'openwfe/util/treechecker' require 'openwfe/utils' require 'openwfe/expressions/raw' module OpenWFE # + # A shorthand for writing process definitions like : + # + # Test2 = OpenWFE.process_definition :name => 'ft_11b', :revision => '2' do + # sequence do + # participant 'alpha' + # sleep '3d' + # participant 'bravo' + # end + # end + # + # This will store in the constant Test2 the process definition in its + # 'raw' (tree) form : + # + # ["process-definition", {"name"=>"ft_11b", "revision"=>"2"}, [ + # ["sequence", {}, [ + # ["participant", {}, ["alpha"]], + # ["sleep", {}, ["3d"]], + # ["participant", {}, ["bravo"]]]]]] + # + def self.process_definition (*args, &block) + + pd = ProcessDefinition.new + pd.instance_eval(&block) + + [ + 'process-definition', + lambda() { |a| + atts = a.last.is_a?(Hash) ? a.last : {} + atts['name'] = a.first unless a.first.is_a?(Hash) + atts.inject({}) { |h, (k, v)| h[OpenWFE.symbol_to_name(k)] = v; h } + }.call(args), + #[ ProcessDefinition.new.instance_eval(&block) ] + pd.context.top_expressions + ] + end + + # # Extend this class to create a programmatic process definition. # # A short example : # # class MyProcessDefinition < OpenWFE::ProcessDefinition @@ -61,11 +84,10 @@ # end # # li = OpenWFE::LaunchItem.new(MyProcessDefinition) # engine.launch(li) # - # class ProcessDefinition def self.metaclass; class << self; self; end; end attr_reader :context @@ -76,23 +98,24 @@ @context = Context.new end def method_missing (m, *args, &block) - #puts "__i_method_missing >>>#{m}<<<<" + #p [ :method_missing, m ] + return nil if m == :make + ProcessDefinition.make_expression( @context, OpenWFE::to_expression_name(m), ProcessDefinition.pack_args(args), &block) end def self.method_missing (m, *args, &block) - @ccontext = Context.new \ - if (not @ccontext) or @ccontext.discarded? + @ccontext = Context.new if (not @ccontext) or @ccontext.discarded? ProcessDefinition.make_expression( @ccontext, OpenWFE::to_expression_name(m), ProcessDefinition.pack_args(args), @@ -104,15 +127,12 @@ # process definition tree). # def self.make_expression (context, exp_name, params, &block) string_child = nil - #attributes = OpenWFE::SymbolHash.new attributes = Hash.new - #puts " ... params.class is #{params.class}" - if params.kind_of?(Hash) params.each do |k, v| if k == '0' @@ -145,16 +165,15 @@ context.top_expressions << exp end return exp unless block - context.push_parent_expression exp + context.push_parent_expression(exp) result = block.call - exp.last << result \ - if result and result.kind_of?(String) + exp.last << result if result and result.is_a?(String) context.pop_parent_expression exp end @@ -178,10 +197,11 @@ elsif instance instance.make instance.context + else pdef = self.new pdef.make pdef.context @@ -191,12 +211,12 @@ name, revision = extract_name_and_revision(self.metaclass.to_s[8..-2]) top_expression = [ - "process-definition", - { "name" => name, "revision" => revision }, + 'process-definition', + { 'name' => name, 'revision' => revision }, context.top_expressions ] top_expression end @@ -225,53 +245,35 @@ #TreeChecker.check code # # checks for 'illicit' ruby code before the eval # (now done in the DefParser) - code, is_wrapped = wrap_code code + o = eval(code, binding()) - o = eval code, binding() + klass = extract_class(code) + # + # grab the first process definition class found + # in the given code - o = extract_class(code) \ - if (o == nil) or o.is_a?(Array) - #if (o == nil) or o.is_a?(SimpleExpRepresentation) - # - # grab the first process definition class found - # in the given code + return o unless klass - result = o.do_make - - return result.last.first if is_wrapped - - result + klass.do_make end protected ClassNameRex = Regexp.compile( " *class *([a-zA-Z0-9]*) *< .*ProcessDefinition") - ProcessDefinitionRex = Regexp.compile( - "^class *[a-zA-Z0-9]* *< .*ProcessDefinition") + #ProcessDefinitionRex = Regexp.compile( + # "^class *[a-zA-Z0-9]* *< .*ProcessDefinition") ProcessNameAndDefRex = Regexp.compile( "([^0-9_]*)_*([0-9].*)$") ProcessNameRex = Regexp.compile( "(.*$)") EndsInDefinitionRex = Regexp.compile( ".*Definition$") - def self.wrap_code (code) - - return [ code, false ] if ProcessDefinitionRex.match(code) - - s = "class NoName0 < ProcessDefinition" - s << "\n" - s << code - s << "\nend" - - [ s, true ] - end - def self.pack_args (args) return args[0] if args.length == 1 a = {} @@ -285,11 +287,11 @@ a end def self.extract_name_and_revision (s) - i = s.rindex("::") + i = s.rindex('::') s = s[i+2..-1] if i m = ProcessNameAndDefRex.match s return [ as_name(m[1]), as_revision(m[2]) ] if m @@ -305,11 +307,11 @@ s end def self.as_revision (s) - s.gsub("_", ".") + s.gsub('_', '.') end class Context attr_accessor :parent_expression, :top_expressions @@ -354,15 +356,16 @@ # This method returns the top expression among the # top expressions... # def top_expression - return nil if @top_expressions.size > 1 - exp = @top_expressions.first - return exp if exp.first == "process-definition" - nil + return nil unless exp + + exp_name = OpenWFE::to_underscore(exp[0]) + + DefineExpression.expression_names.include?(exp_name) ? exp : nil end end end end