lib/openwfe/expressions/fe_concurrence.rb in ruote-0.9.18 vs lib/openwfe/expressions/fe_concurrence.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.
#++
#
#
@@ -49,614 +49,614 @@
# base expressions like 'sequence' and 'concurrence'
#
module OpenWFE
- #
- # The concurrence expression will execute each of its (direct) children
- # in parallel threads.
- #
- # Thus,
- #
- # <concurrence>
- # <participant ref="pa" />
- # <participant ref="pb" />
- # </concurrence>
- #
- # Participants pa and pb will be 'treated' in parallel (quasi
- # simultaneously).
- #
- # The concurrence expressions accept many attributes, that can get
- # combined. By default, the concurrence waits for all its children to
- # reply and returns the workitem of the first child that replied.
- # The attributes tune this behaviour.
- #
- # <em>count</em>
- #
- # <concurrence count="1">
- # <participant ref="pa" />
- # <participant ref="pb" />
- # </concurrence>
- #
- # The concurrence will be over as soon as 'pa' or 'pb' replied, i.e.
- # as soon as "1" child replied.
- #
- # <em>remaining</em>
- #
- # The attribute 'remaining' can take two values 'cancel' (the default) and
- # 'forget'.
- # Cancelled children are completely wiped away, forgotten ones continue
- # to operate but their reply will simply get discarded.
- #
- # <em>over-if</em>
- #
- # 'over-if' accepts a 'boolean expression' (something replying 'true' or
- # 'false'), if the expression evaluates to true, the concurrence will be
- # over and the remaining children will get cancelled (the default) or
- # forgotten.
- #
- # <em>merge</em>
- #
- # By default, the first child to reply to its parent 'concurrence'
- # expression 'wins', i.e. its workitem is used for resuming the flow (after
- # the concurrence).
- #
- # [first] The default : the first child to reply wins
- # [last] The last child to reply wins
- # [highest] The first 'defined' child (in the list of children) will win
- # [lowest] The last 'defined' child (in the list of children) will win
- #
- # Thus, in that example
- #
- # <concurrence merge="lowest">
- # <participant ref="pa" />
- # <participant ref="pb" />
- # </concurrence>
- #
- # when the concurrence is done, the workitem of 'pb' is used to resume the
- # flow after the concurrence.
- #
- # <em>merge-type</em>
- #
- # [override] The default : no mix of values between the workitems do occur
- # [mix] Priority is given to the 'winning' workitem but their values
- # get mixed
- # [isolate] the attributes of the workitem of each branch is placed
- # in a field in the resulting workitem. For example, the
- # attributes of the first branch will be stored under the
- # field named '0' of the resulting workitem.
- #
- # The merge occurs are the top level of workitem attributes.
- #
- # More complex merge behaviour can be obtained by extending the
- # GenericSyncExpression class. But the default sync options are already
- # numerous and powerful by their combinations.
- #
- class ConcurrenceExpression < SequenceExpression
- include ConditionMixin
+ #
+ # The concurrence expression will execute each of its (direct) children
+ # in parallel threads.
+ #
+ # Thus,
+ #
+ # <concurrence>
+ # <participant ref="pa" />
+ # <participant ref="pb" />
+ # </concurrence>
+ #
+ # Participants pa and pb will be 'treated' in parallel (quasi
+ # simultaneously).
+ #
+ # The concurrence expressions accept many attributes, that can get
+ # combined. By default, the concurrence waits for all its children to
+ # reply and returns the workitem of the first child that replied.
+ # The attributes tune this behaviour.
+ #
+ # <em>count</em>
+ #
+ # <concurrence count="1">
+ # <participant ref="pa" />
+ # <participant ref="pb" />
+ # </concurrence>
+ #
+ # The concurrence will be over as soon as 'pa' or 'pb' replied, i.e.
+ # as soon as "1" child replied.
+ #
+ # <em>remaining</em>
+ #
+ # The attribute 'remaining' can take two values 'cancel' (the default) and
+ # 'forget'.
+ # Cancelled children are completely wiped away, forgotten ones continue
+ # to operate but their reply will simply get discarded.
+ #
+ # <em>over-if</em>
+ #
+ # 'over-if' accepts a 'boolean expression' (something replying 'true' or
+ # 'false'), if the expression evaluates to true, the concurrence will be
+ # over and the remaining children will get cancelled (the default) or
+ # forgotten.
+ #
+ # <em>merge</em>
+ #
+ # By default, the first child to reply to its parent 'concurrence'
+ # expression 'wins', i.e. its workitem is used for resuming the flow (after
+ # the concurrence).
+ #
+ # [first] The default : the first child to reply wins
+ # [last] The last child to reply wins
+ # [highest] The first 'defined' child (in the list of children) will win
+ # [lowest] The last 'defined' child (in the list of children) will win
+ #
+ # Thus, in that example
+ #
+ # <concurrence merge="lowest">
+ # <participant ref="pa" />
+ # <participant ref="pb" />
+ # </concurrence>
+ #
+ # when the concurrence is done, the workitem of 'pb' is used to resume the
+ # flow after the concurrence.
+ #
+ # <em>merge-type</em>
+ #
+ # [override] The default : no mix of values between the workitems do occur
+ # [mix] Priority is given to the 'winning' workitem but their values
+ # get mixed
+ # [isolate] the attributes of the workitem of each branch is placed
+ # in a field in the resulting workitem. For example, the
+ # attributes of the first branch will be stored under the
+ # field named '0' of the resulting workitem.
+ #
+ # The merge occurs are the top level of workitem attributes.
+ #
+ # More complex merge behaviour can be obtained by extending the
+ # GenericSyncExpression class. But the default sync options are already
+ # numerous and powerful by their combinations.
+ #
+ class ConcurrenceExpression < SequenceExpression
+ include ConditionMixin
- names :concurrence
+ names :concurrence
- attr_accessor \
- :sync_expression
+ attr_accessor \
+ :sync_expression
- def apply (workitem)
+ def apply (workitem)
- sync = lookup_sym_attribute(
- :sync, workitem, :default => :generic)
+ sync = lookup_sym_attribute(
+ :sync, workitem, :default => :generic)
- @sync_expression =
- get_expression_map.get_sync_class(sync).new(self, workitem)
+ @sync_expression =
+ get_expression_map.get_sync_class(sync).new(self, workitem)
- @children.each do |child|
- @sync_expression.add_child child
- end
+ @children.each do |child|
+ @sync_expression.add_child child
+ end
- store_itself
+ store_itself
- #concurrence = self
+ #concurrence = self
- @children.each_with_index do |child, index|
+ @children.each_with_index do |child, index|
- get_expression_pool.apply(
- child,
- get_workitem(workitem, index))
+ get_expression_pool.apply(
+ child,
+ get_workitem(workitem, index))
- #Thread.new do
- # begin
- # #ldebug { "apply() child : #{child.to_debug_s}" }
- # concurrence.synchronize do
- # get_expression_pool().apply(
- # child,
- # #workitem.dup)
- # get_workitem(workitem, index))
- # end
- # rescue Exception => e
- # lwarn do
- # "apply() " +
- # "caught exception in concurrent child " +
- # child.to_debug_s + "\n" +
- # OpenWFE::exception_to_s(e)
- # end
- # end
- #end
- end
+ #Thread.new do
+ # begin
+ # #ldebug { "apply() child : #{child.to_debug_s}" }
+ # concurrence.synchronize do
+ # get_expression_pool().apply(
+ # child,
+ # #workitem.dup)
+ # get_workitem(workitem, index))
+ # end
+ # rescue Exception => e
+ # lwarn do
+ # "apply() " +
+ # "caught exception in concurrent child " +
+ # child.to_debug_s + "\n" +
+ # OpenWFE::exception_to_s(e)
+ # end
+ # end
+ #end
+ end
- #@sync_expression.ready(self)
- #
- # this is insufficient, have to do that :
+ #@sync_expression.ready(self)
+ #
+ # this is insufficient, have to do that :
- #synchronize do
- #
- # Making sure the freshest version of the concurrence
- # expression is used.
- # This is especially important when using pure persistence.
- #
- reloaded_self, _fei = get_expression_pool.fetch @fei
- reloaded_self.sync_expression.ready reloaded_self
- #end
- end
+ #synchronize do
+ #
+ # Making sure the freshest version of the concurrence
+ # expression is used.
+ # This is especially important when using pure persistence.
+ #
+ reloaded_self, _fei = get_expression_pool.fetch @fei
+ reloaded_self.sync_expression.ready reloaded_self
+ #end
+ end
- def reply (workitem)
- @sync_expression.reply(self, workitem)
- end
-
- protected
-
- def get_workitem (workitem, index)
- workitem.dup
- end
+ def reply (workitem)
+ @sync_expression.reply(self, workitem)
end
- #
- # This expression is a mix between a 'concurrence' and an 'iterator'.
- # It understands the same attributes and behaves as an interator that
- # forks its children concurrently.
- #
- # Some examples :
- #
- # <concurrent-iterator on-value="sales, logistics, lob2" to-field="p">
- # <participant field-ref="p" />
- # </concurrent-iterator>
- #
- # Within a Ruby process definition :
- #
- # sequence do
- # set :field => f, :value => %w{ Alan, Bob, Clarence }
- # #...
- # concurrent_iterator :on_field => "f", :to_field => "p" do
- # participant "${p}"
- # end
- # end
- #
- class ConcurrentIteratorExpression < ConcurrenceExpression
+ protected
- names :concurrent_iterator
+ def get_workitem (workitem, index)
+ workitem.dup
+ end
+ end
- #attr_accessor :template
+ #
+ # This expression is a mix between a 'concurrence' and an 'iterator'.
+ # It understands the same attributes and behaves as an interator that
+ # forks its children concurrently.
+ #
+ # Some examples :
+ #
+ # <concurrent-iterator on-value="sales, logistics, lob2" to-field="p">
+ # <participant field-ref="p" />
+ # </concurrent-iterator>
+ #
+ # Within a Ruby process definition :
+ #
+ # sequence do
+ # set :field => f, :value => %w{ Alan, Bob, Clarence }
+ # #...
+ # concurrent_iterator :on_field => "f", :to_field => "p" do
+ # participant "${p}"
+ # end
+ # end
+ #
+ class ConcurrentIteratorExpression < ConcurrenceExpression
- uses_template
+ names :concurrent_iterator
+ #attr_accessor :template
- def apply (workitem)
+ uses_template
- return reply_to_parent(workitem) \
- if raw_children.length < 1
- @workitems = []
+ def apply (workitem)
- iterator = Iterator.new self, workitem
+ return reply_to_parent(workitem) \
+ if raw_children.length < 1
- return reply_to_parent(workitem) \
- unless iterator.has_next?
+ @workitems = []
- while iterator.has_next?
+ iterator = Iterator.new self, workitem
- wi = workitem.dup
+ return reply_to_parent(workitem) \
+ unless iterator.has_next?
- @workitems << wi
+ while iterator.has_next?
- vars = iterator.next wi
+ wi = workitem.dup
- #rawexp = get_expression_pool.prepare_from_template(
- # self, nil, iterator.index, template, vars)
- #@children << rawexp.fei
+ @workitems << wi
- get_expression_pool.tprepare_child(
- self,
- raw_children.first,
- iterator.index,
- true, # register child
- vars)
- end
+ vars = iterator.next wi
- super
- end
+ #rawexp = get_expression_pool.prepare_from_template(
+ # self, nil, iterator.index, template, vars)
+ #@children << rawexp.fei
- protected
+ get_expression_pool.tprepare_child(
+ self,
+ raw_children.first,
+ iterator.index,
+ true, # register child
+ vars)
+ end
- def get_workitem (workitem, index)
-
- @workitems[index]
- end
+ super
end
- #
- # A base for sync expressions, currently empty.
- # That may change.
- #
- class SyncExpression < ObjectWithMeta
+ protected
- def initialize
+ def get_workitem (workitem, index)
- super
- end
+ @workitems[index]
+ end
+ end
- def self.names (*exp_names)
+ #
+ # A base for sync expressions, currently empty.
+ # That may change.
+ #
+ class SyncExpression < ObjectWithMeta
- exp_names = exp_names.collect do |n|
- n.to_s
- end
- meta_def :expression_names do
- exp_names
- end
- end
+ def initialize
+
+ super
end
- #
- # The classical OpenWFE sync expression.
- # Used by 'concurrence' and 'concurrent-iterator'
- #
- class GenericSyncExpression < SyncExpression
+ def self.names (*exp_names)
- names :generic
+ exp_names = exp_names.collect do |n|
+ n.to_s
+ end
+ meta_def :expression_names do
+ exp_names
+ end
+ end
+ end
- attr_accessor \
- :remaining_children,
- :count,
- :reply_count,
- :cancel_remaining,
- :unready_queue
+ #
+ # The classical OpenWFE sync expression.
+ # Used by 'concurrence' and 'concurrent-iterator'
+ #
+ class GenericSyncExpression < SyncExpression
- def initialize (synchable, workitem)
+ names :generic
- super()
+ attr_accessor \
+ :remaining_children,
+ :count,
+ :reply_count,
+ :cancel_remaining,
+ :unready_queue
- @remaining_children = []
- @reply_count = 0
+ def initialize (synchable, workitem)
- @count = determine_count(synchable, workitem)
- @cancel_remaining = cancel_remaining?(synchable, workitem)
+ super()
- merge = synchable.lookup_sym_attribute(
- :merge, workitem, :default => :first)
+ @remaining_children = []
+ @reply_count = 0
- merge_type = synchable.lookup_sym_attribute(
- :merge_type, workitem, :default => :mix)
+ @count = determine_count(synchable, workitem)
+ @cancel_remaining = cancel_remaining?(synchable, workitem)
- synchable.ldebug { "new() merge_type is '#{merge_type}'" }
+ merge = synchable.lookup_sym_attribute(
+ :merge, workitem, :default => :first)
- @merge_array = MergeArray.new synchable.fei, merge, merge_type
+ merge_type = synchable.lookup_sym_attribute(
+ :merge_type, workitem, :default => :mix)
- @unready_queue = []
- end
+ synchable.ldebug { "new() merge_type is '#{merge_type}'" }
- #
- # when all the children got applied concurrently, the concurrence
- # calls this method to notify the sync expression that replies
- # can be processed
- #
- def ready (synchable)
- #synchable.synchronize do
+ @merge_array = MergeArray.new synchable.fei, merge, merge_type
- synchable.ldebug do
- "ready() called by #{synchable.fei.to_debug_s} " +
- "#{@unready_queue.length} wi waiting"
- end
+ @unready_queue = []
+ end
- queue = @unready_queue
- @unready_queue = nil
- synchable.store_itself
+ #
+ # when all the children got applied concurrently, the concurrence
+ # calls this method to notify the sync expression that replies
+ # can be processed
+ #
+ def ready (synchable)
+ #synchable.synchronize do
- queue.each do |workitem|
- break if do_reply(synchable, workitem)
- #
- # do_reply() will return 'true' as soon as the
- # concurrence is over, if this is the case, the
- # queue should not be treated anymore
- end
- #end
- end
+ synchable.ldebug do
+ "ready() called by #{synchable.fei.to_debug_s} " +
+ "#{@unready_queue.length} wi waiting"
+ end
- def add_child (child)
- @remaining_children << child
- end
+ queue = @unready_queue
+ @unready_queue = nil
+ synchable.store_itself
- def reply (synchable, workitem)
- #synchable.synchronize do
+ queue.each do |workitem|
+ break if do_reply(synchable, workitem)
+ #
+ # do_reply() will return 'true' as soon as the
+ # concurrence is over, if this is the case, the
+ # queue should not be treated anymore
+ end
+ #end
+ end
- if @unready_queue
+ def add_child (child)
+ @remaining_children << child
+ end
- @unready_queue << workitem
+ def reply (synchable, workitem)
+ #synchable.synchronize do
- synchable.store_itself
+ if @unready_queue
- synchable.ldebug do
- "#{self.class}.reply() "+
- "#{@unready_queue.length} wi waiting..."
- end
+ @unready_queue << workitem
- else
- do_reply synchable, workitem
- end
- #end
+ synchable.store_itself
+
+ synchable.ldebug do
+ "#{self.class}.reply() "+
+ "#{@unready_queue.length} wi waiting..."
end
- protected
+ else
+ do_reply synchable, workitem
+ end
+ #end
+ end
- def do_reply (synchable, workitem)
+ protected
- synchable.ldebug do
- "#{self.class}.do_reply() from " +
- "#{workitem.last_expression_id.to_debug_s}"
- end
+ def do_reply (synchable, workitem)
- @merge_array.push(synchable, workitem)
+ synchable.ldebug do
+ "#{self.class}.do_reply() from " +
+ "#{workitem.last_expression_id.to_debug_s}"
+ end
- @reply_count = @reply_count + 1
+ @merge_array.push(synchable, workitem)
- @remaining_children.delete(workitem.last_expression_id)
+ @reply_count = @reply_count + 1
- #synchable.ldebug do
- # "#{self.class}.do_reply() "+
- # "remaining children : #{@remaining_children.length}"
- #end
+ @remaining_children.delete(workitem.last_expression_id)
- if @remaining_children.length <= 0
- reply_to_parent(synchable)
- return true
- end
+ #synchable.ldebug do
+ # "#{self.class}.do_reply() "+
+ # "remaining children : #{@remaining_children.length}"
+ #end
- if @count > 0 and @reply_count >= @count
- treat_remaining_children(synchable)
- reply_to_parent(synchable)
- return true
- end
+ if @remaining_children.length <= 0
+ reply_to_parent(synchable)
+ return true
+ end
- #
- # over-if
+ if @count > 0 and @reply_count >= @count
+ treat_remaining_children(synchable)
+ reply_to_parent(synchable)
+ return true
+ end
- conditional =
- synchable.eval_condition("over-if", workitem, "over-unless")
+ #
+ # over-if
- if conditional
- treat_remaining_children(synchable)
- reply_to_parent(synchable)
- return true
- end
+ conditional =
+ synchable.eval_condition("over-if", workitem, "over-unless")
- #
- # not over, resuming
+ if conditional
+ treat_remaining_children(synchable)
+ reply_to_parent(synchable)
+ return true
+ end
- synchable.store_itself()
+ #
+ # not over, resuming
- #synchable.ldebug do
- # "#{self.class}.do_reply() not replying to parent "+
- # "#{workitem.last_expression_id.to_debug_s}"
- #end
+ synchable.store_itself()
- false
- end
+ #synchable.ldebug do
+ # "#{self.class}.do_reply() not replying to parent "+
+ # "#{workitem.last_expression_id.to_debug_s}"
+ #end
- def reply_to_parent (synchable)
+ false
+ end
- workitem = @merge_array.do_merge
+ def reply_to_parent (synchable)
- synchable.reply_to_parent workitem
- end
+ workitem = @merge_array.do_merge
- def treat_remaining_children (synchable)
+ synchable.reply_to_parent workitem
+ end
- expool = synchable.get_expression_pool
+ def treat_remaining_children (synchable)
- @remaining_children.each do |child|
+ expool = synchable.get_expression_pool
- synchable.ldebug do
- "#{self.class}.treat_remainining_children() " +
- "#{child.to_debug_s} " +
- "(cancel ? #{@cancel_remaining})"
- end
+ @remaining_children.each do |child|
- if @cancel_remaining
- expool.cancel(child)
- else
- expool.forget(synchable, child)
- end
- end
- end
+ synchable.ldebug do
+ "#{self.class}.treat_remainining_children() " +
+ "#{child.to_debug_s} " +
+ "(cancel ? #{@cancel_remaining})"
+ end
- def cancel_remaining? (synchable_expression, workitem)
+ if @cancel_remaining
+ expool.cancel(child)
+ else
+ expool.forget(synchable, child)
+ end
+ end
+ end
- s = synchable_expression.lookup_sym_attribute(
- :remaining, workitem, :default => :cancel)
+ def cancel_remaining? (synchable_expression, workitem)
- (s == :cancel)
- end
+ s = synchable_expression.lookup_sym_attribute(
+ :remaining, workitem, :default => :cancel)
- def determine_count (synchable_expression, workitem)
+ (s == :cancel)
+ end
- c = synchable_expression.lookup_attribute :count, workitem
- return -1 if not c
- i = c.to_i
- return -1 if i < 1
- i
- end
+ def determine_count (synchable_expression, workitem)
- #
- # This inner class is used to gather workitems (via push()) before
- # the final merge
- # This final merge is triggered by calling the do_merge() method
- # which will return the resulting, merged workitem.
- #
- class MergeArray
- include MergeMixin
+ c = synchable_expression.lookup_attribute :count, workitem
+ return -1 if not c
+ i = c.to_i
+ return -1 if i < 1
+ i
+ end
- attr_accessor \
- :synchable_fei,
- :workitem,
- :workitems_by_arrival,
- :workitems_by_altitude,
- :merge,
- :merge_type
+ #
+ # This inner class is used to gather workitems (via push()) before
+ # the final merge
+ # This final merge is triggered by calling the do_merge() method
+ # which will return the resulting, merged workitem.
+ #
+ class MergeArray
+ include MergeMixin
- def initialize (synchable_fei, merge, merge_type)
+ attr_accessor \
+ :synchable_fei,
+ :workitem,
+ :workitems_by_arrival,
+ :workitems_by_altitude,
+ :merge,
+ :merge_type
- @synchable_fei = synchable_fei
+ def initialize (synchable_fei, merge, merge_type)
- @merge = merge
- @merge_type = merge_type
+ @synchable_fei = synchable_fei
- ensure_merge_settings
+ @merge = merge
+ @merge_type = merge_type
- @workitem = nil
+ ensure_merge_settings
- if highest? or lowest?
- @workitems_by_arrival = []
- @workitems_by_altitude = []
- end
- end
+ @workitem = nil
- def push (synchable, wi)
+ if highest? or lowest?
+ @workitems_by_arrival = []
+ @workitems_by_altitude = []
+ end
+ end
- #synchable.ldebug do
- # "push() isolate? #{isolate?}"
- #end
+ def push (synchable, wi)
- if isolate?
- push_in_isolation wi
- elsif last? or first?
- push_by_position wi
- else
- push_by_arrival wi
- end
- end
+ #synchable.ldebug do
+ # "push() isolate? #{isolate?}"
+ #end
- def push_by_position (wi)
+ if isolate?
+ push_in_isolation wi
+ elsif last? or first?
+ push_by_position wi
+ else
+ push_by_arrival wi
+ end
+ end
- source, target = if first?
- [ @workitem, wi ]
- else
- [ wi, @workitem ]
- end
- @workitem = merge_workitems target, source, override?
- end
+ def push_by_position (wi)
- def push_in_isolation (wi)
+ source, target = if first?
+ [ @workitem, wi ]
+ else
+ [ wi, @workitem ]
+ end
+ @workitem = merge_workitems target, source, override?
+ end
- unless @workitem
- @workitem = wi.dup
- att = @workitem.attributes
- @workitem.attributes = {}
- end
+ def push_in_isolation (wi)
- #key = synchable.children.index wi.last_expression_id
- #key = wi.last_expression_id.child_id
- key = get_child_id wi
+ unless @workitem
+ @workitem = wi.dup
+ att = @workitem.attributes
+ @workitem.attributes = {}
+ end
- @workitem.attributes[key.to_s] =
- OpenWFE::fulldup(wi.attributes)
- end
+ #key = synchable.children.index wi.last_expression_id
+ #key = wi.last_expression_id.child_id
+ key = get_child_id wi
- def push_by_arrival (wi)
+ @workitem.attributes[key.to_s] =
+ OpenWFE::fulldup(wi.attributes)
+ end
- #index = synchable.children.index wi.last_expression_id
- #index = Integer(wi.last_expression_id.child_id)
- index = Integer(get_child_id(wi))
+ def push_by_arrival (wi)
- @workitems_by_arrival << wi
- @workitems_by_altitude[index] = wi
- end
+ #index = synchable.children.index wi.last_expression_id
+ #index = Integer(wi.last_expression_id.child_id)
+ index = Integer(get_child_id(wi))
- #
- # merges the workitems stored here
- #
- def do_merge
+ @workitems_by_arrival << wi
+ @workitems_by_altitude[index] = wi
+ end
- return @workitem if @workitem
+ #
+ # merges the workitems stored here
+ #
+ def do_merge
- list = if first?
- @workitems_by_arrival.reverse
- elsif last?
- @workitems_by_arrival
- elsif highest?
- @workitems_by_altitude.reverse
- elsif lowest?
- @workitems_by_altitude
- end
+ return @workitem if @workitem
- result = nil
+ list = if first?
+ @workitems_by_arrival.reverse
+ elsif last?
+ @workitems_by_arrival
+ elsif highest?
+ @workitems_by_altitude.reverse
+ elsif lowest?
+ @workitems_by_altitude
+ end
- list.each do |wi|
- next unless wi
- result = merge_workitems result, wi, override?
- end
+ result = nil
- #puts "___ result :"
- #puts result.to_s
- #puts
+ list.each do |wi|
+ next unless wi
+ result = merge_workitems result, wi, override?
+ end
- result
- end
+ #puts "___ result :"
+ #puts result.to_s
+ #puts
- protected
+ result
+ end
- def first?
- @merge == :first
- end
- def last?
- @merge == :last
- end
- def highest?
- @merge == :highest
- end
- def lowest?
- @merge == :lowest
- end
+ protected
- def mix?
- @merge_type == :mix
- end
- def override?
- @merge_type == :override
- end
- def isolate?
- @merge_type == :isolate
- end
+ def first?
+ @merge == :first
+ end
+ def last?
+ @merge == :last
+ end
+ def highest?
+ @merge == :highest
+ end
+ def lowest?
+ @merge == :lowest
+ end
- #
- # Returns the child id of the expression that just
- # replied with the given workitem.
- #
- def get_child_id (workitem)
+ def mix?
+ @merge_type == :mix
+ end
+ def override?
+ @merge_type == :override
+ end
+ def isolate?
+ @merge_type == :isolate
+ end
- return workitem.fei.child_id \
- if workitem.fei.wfid == @synchable_fei.wfid
+ #
+ # Returns the child id of the expression that just
+ # replied with the given workitem.
+ #
+ def get_child_id (workitem)
- workitem.fei.last_sub_instance_id
- end
+ return workitem.fei.child_id \
+ if workitem.fei.wfid == @synchable_fei.wfid
- #
- # Making sure @merge and @merge_type are set to
- # appropriate values.
- #
- def ensure_merge_settings
+ workitem.fei.last_sub_instance_id
+ end
- @merge_type = :mix unless override? or isolate?
- @merge = :first unless last? or highest? or lowest?
- end
- end
+ #
+ # Making sure @merge and @merge_type are set to
+ # appropriate values.
+ #
+ def ensure_merge_settings
- end
+ @merge_type = :mix unless override? or isolate?
+ @merge = :first unless last? or highest? or lowest?
+ end
+ end
+
+ end
end