Class | OpenWFE::FlowExpression |
In: |
lib/openwfe/expressions/flowexpression.rb
lib/openwfe/storage/yamlcustom.rb |
Parent: | ObjectWithMeta |
opening for tuning yaml persistence
apply_time | [RW] | When the FlowExpression instance is applied, this time stamp is set to the current date. |
attributes | [RW] |
The attributes of the expression, as found in the process definition.
<participant ref='toto' timeout='1d10h' /> The attributes will be ref => "toto" and timeout => "1d10h" (yes, ‘attributes’ contains a hash. |
children | [RW] |
An array of ‘flow expression id’ instances. These are the ids
of the expressions children to this one.
<sequence> <participant ref="toto" /> <participant ref="bert" /> </sequence> The expression instance for ‘sequence’ will hold the feis of toto and bert in its children array. |
environment_id | [RW] | The ‘flow expression id’ of the environment this expression works with. |
fei | [RW] | The ‘flow expression id’ the unique identifier within a workflow instance for this expression instance. |
parent_id | [RW] | The ‘flow expression id’ of the parent expression. Will yield ‘nil’ if this expression is the root of its process instance. |
raw_representation | [RW] | Used by raw expressions to store the not yet interpreted branches of a process, used by other expressions to store their representation at ‘eval time’. |
# File lib/openwfe/expressions/flowexpression.rb, line 761 761: def self.is_definition 762: meta_def :is_definition? do 763: true 764: end 765: end
# File lib/openwfe/expressions/flowexpression.rb, line 758 758: def self.is_definition? 759: false 760: end
a nice ‘names’ tag/method for registering the names of the Expression classes.
# File lib/openwfe/expressions/flowexpression.rb, line 748 748: def self.names (*exp_names) 749: 750: exp_names = exp_names.collect do |n| 751: n.to_s 752: end 753: meta_def :expression_names do 754: exp_names 755: end 756: end
The classical no-params constructors.
# File lib/openwfe/expressions/flowexpression.rb, line 125 125: def initialize 126: 127: super 128: # 129: # very necessary as this class includes the MonitorMixin 130: end
Builds a new instance of an expression
# File lib/openwfe/expressions/flowexpression.rb, line 135 135: def self.new_exp (fei, parent_id, env_id, app_context, attributes) 136: 137: e = self.new 138: 139: e.fei = fei 140: e.parent_id = parent_id 141: e.environment_id = env_id 142: e.application_context = app_context 143: e.attributes = attributes 144: 145: e.children = [] 146: e.apply_time = nil 147: 148: e 149: end
this default implementation immediately replies to the parent expression
# File lib/openwfe/expressions/flowexpression.rb, line 159 159: def apply (workitem) 160: 161: get_parent.reply(workitem) if @parent_id 162: end
a default implementation for cancel : cancels all the children Attempts to return an InFlowWorkItem
# File lib/openwfe/expressions/flowexpression.rb, line 189 189: def cancel 190: 191: return nil if not @children 192: 193: inflowitem = nil 194: 195: @children.each do |child| 196: 197: next if child.kind_of?(String) 198: 199: i = get_expression_pool.cancel child 200: inflowitem ||= i 201: end 202: 203: inflowitem 204: end
Takes care of removing all the children of this expression, if any.
# File lib/openwfe/expressions/flowexpression.rb, line 576 576: def clean_children 577: 578: return unless @children 579: 580: @children.each do |child_fei| 581: get_expression_pool.remove(child_fei) \ 582: if child_fei.kind_of? FlowExpressionId 583: end 584: end
Unsets a variable in the current environment.
The variable name may be prefixed by / to indicate process level scope or by // to indicate engine level (global) scope.
# File lib/openwfe/expressions/flowexpression.rb, line 353 353: def delete_variable (varname) 354: 355: env, var = lookup_environment(varname) 356: env.delete var 357: end
This method is called in expressionpool.forget(). It duplicates the expression‘s current environment (deep copy) and attaches it as the expression own environment. Returns the duplicated environment.
# File lib/openwfe/expressions/flowexpression.rb, line 562 562: def dup_environment 563: 564: env = fetch_environment 565: env = env.dup 566: env.fei = @fei.dup 567: env.fei.expression_name = EN_ENVIRONMENT 568: @environment_id = env.fei 569: 570: env.store_itself 571: end
Just fetches the environment for this expression.
# File lib/openwfe/expressions/flowexpression.rb, line 268 268: def fetch_environment 269: 270: get_expression_pool.fetch_expression @environment_id 271: end
Returns the text stored as the children of the given expression
# File lib/openwfe/expressions/flowexpression.rb, line 627 627: def fetch_text_content (workitem, escape=false) 628: 629: text = "" 630: 631: children.each do |child| 632: 633: if child.is_a?(RawExpression) 634: 635: text << child.fei.to_s 636: 637: elsif child.is_a?(FlowExpressionId) 638: 639: text << get_expression_pool\ 640: .fetch_expression(child).raw_representation.to_s 641: 642: else 643: 644: text << child.to_s 645: end 646: end 647: 648: return nil if text == "" 649: 650: text = OpenWFE::dosub(text, self, workitem) \ 651: unless escape 652: 653: text 654: end
Currently only used by dollar.rb and its ${r:some_ruby_code}, returns the binding in this flow expression.
# File lib/openwfe/expressions/flowexpression.rb, line 602 602: def get_binding 603: 604: binding() 605: end
Returns the environment instance this expression uses. An environment is a container (a scope) for variables in the process definition. Environments themselves are FlowExpression instances.
# File lib/openwfe/expressions/flowexpression.rb, line 241 241: def get_environment 242: 243: fetch_environment || get_expression_pool.fetch_engine_environment 244: end
Returns the parent expression (not as a FlowExpressionId but directly as the FlowExpression instance it is).
# File lib/openwfe/expressions/flowexpression.rb, line 213 213: def get_parent 214: 215: #parent, parent_fei = get_expression_pool.fetch @parent_id 216: #parent 217: get_expression_pool.fetch_expression @parent_id 218: end
A shortcut for fetch_environment.get_root_environment
Returns the environment of the top process (the environement just before the engine environment in the hierarchy).
# File lib/openwfe/expressions/flowexpression.rb, line 252 252: def get_root_environment 253: 254: fetch_environment.get_root_environment 255: end
Returns true if the expression has the given attribute. The attname parameter can be a String or a Symbol.
# File lib/openwfe/expressions/flowexpression.rb, line 450 450: def has_attribute (attname) 451: 452: attname = OpenWFE::symbol_to_name(attname) \ 453: if attname.kind_of?(Symbol) 454: 455: (@attributes[attname] != nil) 456: end
Looks up the value for an attribute of this expression.
if the expression is
<participant ref="toto" />
then
participant_expression.lookup_attribute("toto", wi)
will yield "toto"
The various methods for looking up attributes do perform dollar variable substitution. It‘s ok to pass a Symbol for the attribute name.
# File lib/openwfe/expressions/flowexpression.rb, line 378 378: def lookup_attribute (attname, workitem, options={}) 379: 380: #p attname 381: 382: default = options[:default] 383: escape = options[:escape] 384: 385: attname = OpenWFE::symbol_to_name(attname) \ 386: if attname.kind_of?(Symbol) 387: 388: #ldebug { "lookup_attribute() '#{attname}' in #{@fei.to_debug_s}" } 389: 390: text = @attributes[attname] 391: 392: return default if text == nil 393: return text unless text.is_a?(String) 394: 395: return text if escape == true 396: # returns text if escape is set and is set to true 397: 398: OpenWFE::dosub text, self, workitem 399: end
Returns a hash of all the FlowExpression attributes with their values having undergone dollar variable substitution. If the attributes parameter is set (to an Array instance) then only the attributes named in that list will be looked up.
It‘s ok to pass an array of Symbol instances for the attributes parameter.
# File lib/openwfe/expressions/flowexpression.rb, line 467 467: def lookup_attributes (workitem, _attributes=nil) 468: 469: result = {} 470: 471: return result if not @attributes 472: 473: _attributes = @attributes.keys if not _attributes 474: 475: _attributes.each do |k| 476: 477: k = k.to_s 478: v = @attributes[k] 479: 480: result[k] = OpenWFE::dosub v, self, workitem 481: 482: #ldebug do 483: # "lookup_attributes() added '#{k}' -> '#{result[k]}'" 484: #end 485: end 486: 487: result 488: end
A convenience method for looking up a boolean value. It‘s ok to pass a Symbol for the attribute name.
# File lib/openwfe/expressions/flowexpression.rb, line 438 438: def lookup_boolean_attribute (attname, workitem, default=false) 439: 440: result = lookup_downcase_attribute attname, workitem 441: return default if result == nil 442: 443: (result == 'true') 444: end
For an expression like
iterator :on_value => "a, b, c", to-variable => "v0" do # ... end
this call
lookup_comma_list_attribute(:on_value, wi)
will return
[ 'a', 'b', 'c' ]
# File lib/openwfe/expressions/flowexpression.rb, line 505 505: def lookup_comma_list_attribute (attname, workitem, options={}) 506: 507: a = lookup_attribute(attname, workitem, options) 508: 509: return nil if not a 510: 511: result = [] 512: a.split(',').each do |elt| 513: elt = elt.strip 514: result << elt if elt.length > 0 515: end 516: 517: result 518: end
Like lookup_attribute() but returns the value downcased [ (and stripped). Returns nil if no such attribute was found.
# File lib/openwfe/expressions/flowexpression.rb, line 416 416: def lookup_downcase_attribute (attname, workitem, options={}) 417: 418: result = lookup_string_attribute attname, workitem, options 419: result = result.strip.downcase if result 420: result 421: end
looks up for ‘ref’, ‘variable-ref’ and then for ‘field-ref’ if necessary.
# File lib/openwfe/expressions/flowexpression.rb, line 670 670: def lookup_ref (workitem, prefix='') 671: 672: ref = lookup_vf_attribute workitem, 'ref', :prefix => prefix 673: return ref.to_s if ref 674: nil 675: end
Returns the attribute value as a String (or nil if it‘s not found).
# File lib/openwfe/expressions/flowexpression.rb, line 404 404: def lookup_string_attribute (attname, workitem, options={}) 405: 406: result = lookup_attribute attname, workitem, options 407: result = result.to_s if result 408: result 409: end
Returns the value of the attribute as a Symbol. Returns nil if there is no attribute under the given name.
# File lib/openwfe/expressions/flowexpression.rb, line 427 427: def lookup_sym_attribute (attname, workitem, options={}) 428: 429: result = lookup_downcase_attribute attname, workitem, options 430: result = result.to_sym if result 431: result 432: end
looks up for ‘value’, ‘variable-value’ and then for ‘field-value’ if necessary.
# File lib/openwfe/expressions/flowexpression.rb, line 660 660: def lookup_value (workitem, options={}) 661: 662: lookup_vf_attribute(workitem, 'value', options) || 663: lookup_vf_attribute(workitem, 'val', options) 664: end
Looks up the value of a variable in the current environment. If not found locally will lookup at the process level and even further in the engine scope.
The variable name may be prefixed by / to indicate process level scope or by // to indicate engine level (global) scope.
# File lib/openwfe/expressions/flowexpression.rb, line 338 338: def lookup_variable (varname) 339: 340: #puts "lv : #{varname}" 341: #puts OpenWFE.caller_to_s(0, 5) 342: 343: env, var = lookup_environment(varname) 344: env[var] 345: end
Looks up for value attributes like ‘field-ref’ or ‘variable-value‘
# File lib/openwfe/expressions/flowexpression.rb, line 680 680: def lookup_vf_attribute (workitem, att_name, options={}) 681: 682: att_name = att_name.to_s 683: 684: prefix = options[:prefix] || '' 685: prefix = prefix.to_s 686: 687: dash = (att_name.size > 0 and prefix.size > 0) ? "-" : "" 688: 689: v = lookup_attribute( 690: "#{prefix}#{dash}#{att_name}", workitem, options) 691: 692: att_name = "-#{att_name}" if att_name.size > 0 693: prefix = "#{prefix}-" if prefix.size > 0 694: 695: return v if v 696: 697: v = lookup_attribute( 698: "#{prefix}variable#{att_name}", workitem, options) || 699: lookup_attribute( 700: "#{prefix}var#{att_name}", workitem, options) || 701: lookup_attribute( 702: "#{prefix}v#{att_name}", workitem, options) 703: 704: return lookup_variable(v) if v 705: 706: f = lookup_attribute( 707: "#{prefix}field#{att_name}", workitem, options) || 708: lookup_attribute( 709: "#{prefix}f#{att_name}", workitem, options) 710: 711: #return workitem.attributes[f] if f 712: return workitem.attributes[f.to_s] if f 713: 714: nil 715: end
creates a new environment just for this expression
# File lib/openwfe/expressions/flowexpression.rb, line 523 523: def new_environment (initial_vars=nil) 524: 525: ldebug { "new_environment() for #{@fei.to_debug_s}" } 526: 527: @environment_id = @fei.dup 528: @environment_id.expression_name = EN_ENVIRONMENT 529: 530: parent_fei = nil 531: parent = nil 532: 533: parent, _fei = get_expression_pool.fetch(@parent_id) \ 534: if @parent_id 535: 536: parent_fei = parent.environment_id if parent 537: 538: env = Environment.new_env( 539: @environment_id, parent_fei, nil, @application_context, nil) 540: 541: env.variables.merge! initial_vars if initial_vars 542: 543: env[@fei.wfname] = self.raw_representation \ 544: if (not @parent_id) and (self.is_a?(RawExpression)) 545: # 546: # keeping track of the raw representation 547: # of the top expression (for top recursion) 548: 549: ldebug { "new_environment() is #{env.fei.to_debug_s}" } 550: 551: env.store_itself 552: 553: env 554: end
Returns true if the expression‘s environment was generated for itself (usually DefineExpression do have such envs)
# File lib/openwfe/expressions/flowexpression.rb, line 277 277: def owns_its_environment? 278: 279: #ldebug do 280: # "owns_its_environment?()\n" + 281: # " #{@fei.to_debug_s}\n" + 282: # " #{@environment_id.to_debug_s}" 283: #end 284: 285: return false if not @environment_id 286: 287: ei = @fei.dup 288: vi = @environment_id.dup 289: 290: ei.expression_name = "neutral" 291: vi.expression_name = "neutral" 292: 293: #ldebug do 294: # "owns_its_environment?()\n"+ 295: # " exp #{ei.to_debug_s}\n"+ 296: # " env #{vi.to_debug_s}" 297: #end 298: 299: (ei == vi) 300: end
Returns true if this expression belongs to a paused flow
# File lib/openwfe/expressions/flowexpression.rb, line 305 305: def paused? 306: 307: #(lookup_variable(VAR_PAUSED) == true) 308: get_expression_pool.is_paused?(self) 309: end
Removes a child from the expression children list.
# File lib/openwfe/expressions/flowexpression.rb, line 589 589: def remove_child (child_fei) 590: 591: fei = @children.delete child_fei 592: 593: store_itself if fei 594: # 595: # store_itself if the child was really removed. 596: end
this default implementation immediately replies to the parent expression
# File lib/openwfe/expressions/flowexpression.rb, line 168 168: def reply (workitem) 169: 170: reply_to_parent workitem 171: end
Triggers the reply to the parent expression (of course, via the expression pool). Expressions do call this method when their job is done and the flow should resume without them.
# File lib/openwfe/expressions/flowexpression.rb, line 179 179: def reply_to_parent (workitem) 180: 181: get_expression_pool.reply_to_parent self, workitem 182: end
Sets a variable in the current environment. Is usually called by the ‘set’ expression.
The variable name may be prefixed by / to indicate process level scope or by // to indicate engine level (global) scope.
# File lib/openwfe/expressions/flowexpression.rb, line 318 318: def set_variable (varname, value) 319: 320: env, var = lookup_environment(varname) 321: 322: ldebug do 323: "set_variable() '#{varname}' to '#{value}' " + 324: "in #{env.fei.to_debug_s}" 325: end 326: 327: env[var] = value 328: end
Stores itself in the expression pool. It‘s very important for expressions in persisted context to save themselves as soon as their state changed. Else this information would be lost at engine restart or simply if the expression got swapped out of memory and reloaded later.
# File lib/openwfe/expressions/flowexpression.rb, line 227 227: def store_itself 228: 229: ldebug { "store_itself() for #{@fei.to_debug_s}" } 230: #ldebug { "store_itself() \n#{OpenWFE::caller_to_s(0, 6)}" } 231: 232: get_expression_pool.update self 233: end
Used like the classical Ruby synchronize, but as the OpenWFE expression pool manages its own set of monitors, it‘s one of those monitors that is used. But the synchronize code looks like the class just included the MonitorMixin. No hassle.
# File lib/openwfe/expressions/flowexpression.rb, line 613 613: def synchronize 614: 615: #ldebug { "synchronize() ---in--- for #{@fei.to_debug_s}" } 616: 617: get_expression_pool.get_monitor(@fei).synchronize do 618: yield 619: end 620: 621: #ldebug { "synchronize() --out-- for #{@fei.to_debug_s}" } 622: end
Some eye candy
# File lib/openwfe/expressions/flowexpression.rb, line 720 720: def to_s 721: 722: s = "* #{@fei.to_debug_s} [#{self.class.name}]" 723: 724: s << "\n `--p--> #{@parent_id.to_debug_s}" \ 725: if @parent_id 726: 727: s << "\n `--e--> #{@environment_id.to_debug_s}" \ 728: if @environment_id 729: 730: return s unless @children 731: 732: @children.each do |c| 733: sc = if c.kind_of?(OpenWFE::FlowExpressionId) 734: c.to_debug_s 735: else 736: ">#{c.to_s}<" 737: end 738: s << "\n `--c--> #{sc}" 739: end 740: 741: s 742: end
# File lib/openwfe/storage/yamlcustom.rb, line 55 55: def to_yaml_properties 56: 57: l = super() 58: 59: l.delete("@application_context") 60: 61: #l.delete("@timeout_job_id") 62: #l.delete("@scheduler_job_id") 63: # scheduler ids should not get persisted 64: 65: l 66: end
Returns the next sub process id available (this counter is stored in the local environment under the key :next_sub_id)
# File lib/openwfe/expressions/flowexpression.rb, line 798 798: def get_next_sub_id 799: 800: env = get_environment 801: 802: c = nil 803: 804: env.synchronize do 805: c = env.variables[:next_sub_id] 806: n = if c 807: c + 1 808: else 809: c = 0 810: 1 811: end 812: env.variables[:next_sub_id] = n 813: env.store_itself 814: end 815: 816: c 817: end
If the varname starts with ’//’ will return the engine environment and the truncated varname… If the varname starts with ’/’ will return the root environment for the current process instance and the truncated varname…
# File lib/openwfe/expressions/flowexpression.rb, line 775 775: def lookup_environment (varname) 776: 777: if varname[0, 2] == '//' 778: return [ 779: get_expression_pool.fetch_engine_environment, 780: varname[2..-1] 781: ] 782: end 783: 784: if varname[0, 1] == '/' 785: return [ 786: get_environment.get_root_environment, 787: varname[1..-1] 788: ] 789: end 790: 791: [ get_environment, varname ] 792: end