lib/openwfe/participants/participants.rb in ruote-0.9.18 vs lib/openwfe/participants/participants.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.
#++
#
#
@@ -47,361 +47,361 @@
#
# some base participant implementations
#
module OpenWFE
+ #
+ # Just dumps the incoming workitem in a file as a YAML String.
+ #
+ # By default, this participant will not reply to the engine once
+ # the workitem got dumped to its file, but you can set its
+ # reply_anyway field to true to make it reply anyway...
+ #
+ class FileParticipant
+ include LocalParticipant
+
+ attr_accessor :reply_anyway, :workdir
+
#
- # Just dumps the incoming workitem in a file as a YAML String.
+ # The constructor expects as a unique optional param either the
+ # application_context either the 'output' dir for the participant.
#
- # By default, this participant will not reply to the engine once
- # the workitem got dumped to its file, but you can set its
- # reply_anyway field to true to make it reply anyway...
- #
- class FileParticipant
- include LocalParticipant
+ def initialize (context_or_dir=nil)
- attr_accessor :reply_anyway, :workdir
+ @workdir = get_work_directory(context_or_dir) + "/out/"
- #
- # The constructor expects as a unique optional param either the
- # application_context either the 'output' dir for the participant.
- #
- def initialize (context_or_dir=nil)
+ @reply_anyway = false
+ end
- @workdir = get_work_directory(context_or_dir) + "/out/"
+ #
+ # The method called by the engine for each incoming workitem.
+ #
+ def consume (workitem)
- @reply_anyway = false
- end
+ FileUtils.makedirs(@workdir) unless File.exist?(@workdir)
- #
- # The method called by the engine for each incoming workitem.
- #
- def consume (workitem)
+ file_name = @workdir + determine_file_name(workitem)
- FileUtils.makedirs(@workdir) unless File.exist?(@workdir)
+ dump_to_file(file_name, workitem)
- file_name = @workdir + determine_file_name(workitem)
+ reply_to_engine(workitem) if @reply_anyway
+ end
- dump_to_file(file_name, workitem)
+ #
+ # This method does the actual job of dumping the workitem (as some
+ # YAML to a file).
+ # It can be easily overriden.
+ #
+ def dump_to_file (file_name, workitem)
- reply_to_engine(workitem) if @reply_anyway
- end
+ File.open(file_name, "w") do |file|
+ file.print encode_workitem(workitem)
+ end
+ end
- #
- # This method does the actual job of dumping the workitem (as some
- # YAML to a file).
- # It can be easily overriden.
- #
- def dump_to_file (file_name, workitem)
+ #
+ # You can override this method to control into which file (name)
+ # each workitem gets dumped.
+ # You could even have a unique file for all workitems transiting
+ # through this participant.
+ #
+ def determine_file_name (workitem)
- File.open(file_name, "w") do |file|
- file.print encode_workitem(workitem)
- end
- end
+ fei = workitem.fei
- #
- # You can override this method to control into which file (name)
- # each workitem gets dumped.
- # You could even have a unique file for all workitems transiting
- # through this participant.
- #
- def determine_file_name (workitem)
+ OpenWFE::ensure_for_filename(
+ "#{fei.wfid}_#{fei.expression_id}__" +
+ "#{fei.workflow_definition_name}__" +
+ "#{fei.workflow_definition_revision}" +
+ "#{workitem.participant_name}.yaml")
+ end
- fei = workitem.fei
+ protected
- OpenWFE::ensure_for_filename(
- "#{fei.wfid}_#{fei.expression_id}__" +
- "#{fei.workflow_definition_name}__" +
- "#{fei.workflow_definition_revision}" +
- "#{workitem.participant_name}.yaml")
- end
+ #
+ # By default, uses YAML to serialize the workitem
+ # (of course you can override this method).
+ #
+ def encode_workitem (wi)
+ YAML.dump wi
+ end
+ end
- protected
+ #
+ # This participant is used by the register_participant() method of
+ # Engine class.
+ #
+ # engine.register_participant("the_boss") do |workitem|
+ # puts "the boss received a workitem"
+ # end
+ #
+ # After the block executes, the BlockParticipant immediately replies
+ # to the engine.
+ #
+ # You can pass a block with two arguments : flow_expression and workitem
+ # to BlockParticipant, it will automatically adapt.
+ #
+ # engine.register_participant("the_boss") do |fexp, wi|
+ # puts "the boss received a workitem from exp #{fexp.fei.to_s}"
+ # end
+ #
+ # Having the FlowExpression instance at hand allows for advanced tricks,
+ # beware...
+ #
+ # It's also OK to register a block participant without params :
+ #
+ # engine.register_participant :alice do
+ # puts "Alice received a workitem"
+ # end
+ #
+ class BlockParticipant
+ include LocalParticipant
- #
- # By default, uses YAML to serialize the workitem
- # (of course you can override this method).
- #
- def encode_workitem (wi)
- YAML.dump(wi)
- end
+ def initialize (block0=nil, &block1)
+ @block = if block1
+ block1
+ else
+ block0
+ end
+ raise "Missing a block parameter" \
+ unless @block
end
-
- #
- # This participant is used by the register_participant() method of
- # Engine class.
- #
- # engine.register_participant("the_boss") do |workitem|
- # puts "the boss received a workitem"
- # end
- #
- # After the block executes, the BlockParticipant immediately replies
- # to the engine.
- #
- # You can pass a block with two arguments : flow_expression and workitem
- # to BlockParticipant, it will automatically adapt.
- #
- # engine.register_participant("the_boss") do |fexp, wi|
- # puts "the boss received a workitem from exp #{fexp.fei.to_s}"
- # end
- #
- # Having the FlowExpression instance at hand allows for advanced tricks,
- # beware...
- #
- # It's also OK to register a block participant without params :
- #
- # engine.register_participant :alice do
- # puts "Alice received a workitem"
- # end
- #
- class BlockParticipant
- include LocalParticipant
- def initialize (block0=nil, &block1)
- @block = if block1
- block1
- else
- block0
- end
- raise "Missing a block parameter" \
- unless @block
- end
+ def consume (workitem)
- def consume (workitem)
+ result = call_block @block, workitem
- result = call_block @block, workitem
+ workitem.set_result(result) \
+ if result and result != workitem
- workitem.set_result(result) \
- if result and result != workitem
-
- reply_to_engine(workitem) \
- if workitem.kind_of? InFlowWorkItem
- # else it's a cancel ite
- end
+ reply_to_engine(workitem) \
+ if workitem.kind_of? InFlowWorkItem
+ # else it's a cancel ite
end
+ end
- #
- # Simply aliasing a participant.
- #
- # engine.register_participant "toto" do |workitem|
- # workitem.toto_message = "toto was here"
- # end
- # engine.register_participant "user_.*", AliasParticipant.new("toto")
- #
- # Workitems for participant whose name starts with 'user_' will be handled
- # by participant 'toto'.
- # Note that you can't use use a regex as the aliased name ("toto" in the
- # example).
- #
- class AliasParticipant
- include LocalParticipant
+ #
+ # Simply aliasing a participant.
+ #
+ # engine.register_participant "toto" do |workitem|
+ # workitem.toto_message = "toto was here"
+ # end
+ # engine.register_participant "user_.*", AliasParticipant.new("toto")
+ #
+ # Workitems for participant whose name starts with 'user_' will be handled
+ # by participant 'toto'.
+ # Note that you can't use use a regex as the aliased name ("toto" in the
+ # example).
+ #
+ class AliasParticipant
+ include LocalParticipant
- attr_reader :aliased_name
+ attr_reader :aliased_name
- def initialize (aliased_name)
+ def initialize (aliased_name)
- @aliased_name = aliased_name
- end
+ @aliased_name = aliased_name
+ end
- def consume (workitem)
+ def consume (workitem)
- get_participant_map.dispatch(nil, @aliased_name, workitem)
- end
+ get_participant_map.dispatch(nil, @aliased_name, workitem)
end
+ end
+ #
+ # The NullParticipant never replies, it simply discards the workitems
+ # it receives.
+ #
+ class NullParticipant
+ include LocalParticipant
+
#
- # The NullParticipant never replies, it simply discards the workitems
- # it receives.
+ # Simply discards the incoming workitem
#
- class NullParticipant
- include LocalParticipant
-
- #
- # Simply discards the incoming workitem
- #
- def consume (workitem)
- # does nothing and does not reply to the engine.
- end
+ def consume (workitem)
+ # does nothing and does not reply to the engine.
end
+ end
+ #
+ # The NoOperationParticipant immediately replies to the engine upon
+ # receiving a workitem.
+ #
+ # Is used in testing. Could also be useful during the 'development'
+ # phase of a business process, as an empty placeholder.
+ #
+ class NoOperationParticipant
+ include LocalParticipant
+
#
- # The NoOperationParticipant immediately replies to the engine upon
- # receiving a workitem.
+ # Simply discards the incoming workitem
#
- # Is used in testing. Could also be useful during the 'development'
- # phase of a business process, as an empty placeholder.
- #
- class NoOperationParticipant
- include LocalParticipant
+ def consume (workitem)
- #
- # Simply discards the incoming workitem
- #
- def consume (workitem)
-
- reply_to_engine workitem
- end
+ reply_to_engine workitem
end
+ end
- #
- # The PrintParticipant will just emit its name to the
- # test tracer if any or to the stdout else.
- # Used by some unit tests.
- #
- class PrintParticipant
- include LocalParticipant
+ #
+ # The PrintParticipant will just emit its name to the
+ # test tracer if any or to the stdout else.
+ # Used by some unit tests.
+ #
+ class PrintParticipant
+ include LocalParticipant
- def consume (workitem)
+ def consume (workitem)
- tracer = @application_context['__tracer']
+ tracer = @application_context['__tracer']
- if tracer
- tracer << workitem.participant_name
- tracer << "\n"
- else
- puts workitem.participant_name
- end
+ if tracer
+ tracer << workitem.participant_name
+ tracer << "\n"
+ else
+ puts workitem.participant_name
+ end
- reply_to_engine(workitem)
- end
+ reply_to_engine(workitem)
end
+ end
+ #
+ # Links a process under a participant [name].
+ #
+ # Turns top level processes into participants
+ #
+ # Some examples :
+ #
+ # require 'engine/participants/participants'
+ #
+ # engine.register_participant(
+ # "transmit_to_accounting",
+ # "http://company.process.server.ie/processes/acc0.xml")
+ #
+ # engine.register_participant(
+ # "hr_resume_review_process",
+ # "file:/var/processes/hr_resume_review_process.rb")
+ #
+ # Some more examples :
+ #
+ # class RegistrationProcess < OpenWFE::ProcessDefinition
+ # sequence do
+ # participant :ref => "Alice"
+ # participant :ref => "Bob"
+ # end
+ # end
+ #
+ # # later in the code ...
+ #
+ # engine.register_participant("registration", RegistrationProcess)
+ #
+ # Or directly with some XML string :
+ #
+ # engine.register_participant("registration", '''
+ # <process-definition name="registration" revision="0.1">
+ # <sequence>
+ # <participant ref="Alice" />
+ # <participant ref="Bob" />
+ # </sequence>
+ # </process-definition>
+ # '''.strip)
+ #
+ # It's then easy to call the subprocess as if it were a participant :
+ #
+ # sequence do
+ # participant :ref => "registration"
+ # # or
+ # participant "registration"
+ # # or simply
+ # registration
+ # end
+ #
+ # Note that the 'subprocess' expression may be used as well :
+ #
+ # sequence do
+ # subprocess ref => "http://dms.company.org/processes/proc1.rb"
+ # end
+ #
+ # But you can't use the URL as an expression name for writing nice,
+ # concise, process definitions.
+ #
+ class ProcessParticipant
+ include LocalParticipant
+
#
- # Links a process under a participant [name].
+ # The 'object' may be the URL of a process definition or the process
+ # definition itself as an XML string or a Ruby process definition
+ # (as a class or in a String).
#
- # Turns top level processes into participants
- #
- # Some examples :
- #
- # require 'engine/participants/participants'
- #
- # engine.register_participant(
- # "transmit_to_accounting",
- # "http://company.process.server.ie/processes/acc0.xml")
- #
- # engine.register_participant(
- # "hr_resume_review_process",
- # "file:/var/processes/hr_resume_review_process.rb")
- #
- # Some more examples :
- #
- # class RegistrationProcess < OpenWFE::ProcessDefinition
- # sequence do
- # participant :ref => "Alice"
- # participant :ref => "Bob"
- # end
- # end
- #
- # # later in the code ...
- #
- # engine.register_participant("registration", RegistrationProcess)
- #
- # Or directly with some XML string :
- #
- # engine.register_participant("registration", '''
- # <process-definition name="registration" revision="0.1">
- # <sequence>
- # <participant ref="Alice" />
- # <participant ref="Bob" />
- # </sequence>
- # </process-definition>
- # '''.strip)
- #
- # It's then easy to call the subprocess as if it were a participant :
- #
- # sequence do
- # participant :ref => "registration"
- # # or
- # participant "registration"
- # # or simply
- # registration
- # end
- #
- # Note that the 'subprocess' expression may be used as well :
- #
- # sequence do
- # subprocess ref => "http://dms.company.org/processes/proc1.rb"
- # end
- #
- # But you can't use the URL as an expression name for writing nice,
- # concise, process definitions.
- #
- class ProcessParticipant
- include LocalParticipant
+ def initialize (object)
- #
- # The 'object' may be the URL of a process definition or the process
- # definition itself as an XML string or a Ruby process definition
- # (as a class or in a String).
- #
- def initialize (object)
+ super()
- super()
+ template_uri = OpenWFE::parse_known_uri object
- template_uri = OpenWFE::parse_known_uri object
+ @template = template_uri || object
+ end
- @template = template_uri || object
- end
+ #
+ # This is the method called by the engine when it has a workitem
+ # for this participant.
+ #
+ def consume (workitem)
- #
- # This is the method called by the engine when it has a workitem
- # for this participant.
- #
- def consume (workitem)
-
- #get_expression_pool.launch_template(
- # get_flow_expression(workitem),
- # nil, # new environment
- # 0, # sub_id
- # @template,
- # workitem)
- # #params)
- get_expression_pool.launch_subprocess(
- get_flow_expression(workitem),
- @template,
- false, # don't forget
- workitem,
- nil) # no params for the new subprocess env
- end
+ #get_expression_pool.launch_template(
+ # get_flow_expression(workitem),
+ # nil, # new environment
+ # 0, # sub_id
+ # @template,
+ # workitem)
+ # #params)
+ get_expression_pool.launch_subprocess(
+ get_flow_expression(workitem),
+ @template,
+ false, # don't forget
+ workitem,
+ nil) # no params for the new subprocess env
end
+ end
+ #
+ # This mixin provides an eval_template() method. This method assumes
+ # the target class has a @block_template and a @template, it also
+ # assumes the class includes the module LocalParticipant.
+ #
+ # This mixin is used for example in the MailParticipant class.
+ #
+ module TemplateMixin
+
#
- # This mixin provides an eval_template() method. This method assumes
- # the target class has a @block_template and a @template, it also
- # assumes the class includes the module LocalParticipant.
+ # Given a workitem, expands the template and returns it as a String.
#
- # This mixin is used for example in the MailParticipant class.
- #
- module TemplateMixin
+ def eval_template (workitem)
- #
- # Given a workitem, expands the template and returns it as a String.
- #
- def eval_template (workitem)
+ fe = get_flow_expression workitem
- fe = get_flow_expression workitem
+ template = if @block_template
- template = if @block_template
+ call_block @block_template, workitem
- call_block @block_template, workitem
+ elsif @template
- elsif @template
+ template = if @template.kind_of?(File)
+ @template.readlines
+ else
+ @template.to_s
+ end
- template = if @template.kind_of?(File)
- @template.readlines
- else
- @template.to_s
- end
+ else
- else
+ nil
+ end
- nil
- end
+ return "(no template given)" unless template
- return "(no template given)" unless template
-
- OpenWFE::dosub template, fe, workitem
- end
+ OpenWFE::dosub template, fe, workitem
end
+ end
end