Class OpenWFE::FlowExpression
In: lib/openwfe/expressions/flowexpression.rb
lib/openwfe/storage/yamlcustom.rb
Parent: ObjectWithMeta

opening for tuning yaml persistence

Methods

Included Modules

Contextual Logging OwfeServiceLocator

Attributes

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’.

Public Class methods

[Source]

     # 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

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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

[Source]

     # 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

Public Instance methods

this default implementation immediately replies to the parent expression

[Source]

     # 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

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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).

[Source]

     # 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).

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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' ]

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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).

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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‘

[Source]

     # 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

[Source]

     # 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)

[Source]

     # 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

[Source]

     # 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.

[Source]

     # 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

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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.

[Source]

     # 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

[Source]

     # 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

[Source]

    # 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
unset_variable(varname)

Alias for delete_variable

Protected Instance methods

Returns the next sub process id available (this counter is stored in the local environment under the key :next_sub_id)

[Source]

     # 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…

[Source]

     # 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

[Validate]