lib/openwfe/workitem.rb in ruote-0.9.18 vs lib/openwfe/workitem.rb in ruote-0.9.19
- old
+ new
@@ -1,34 +1,34 @@
#
#--
# Copyright (c) 2005-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.
#++
#
#
@@ -41,459 +41,466 @@
require 'openwfe/utils'
module OpenWFE
- #
- # The convention for the result of some expressions is to store
- # their result in a workitem field named "__result__".
- #
- FIELD_RESULT = "__result__"
+ #
+ # The convention for the result of some expressions is to store
+ # their result in a workitem field named "__result__".
+ #
+ FIELD_RESULT = "__result__"
- #--
- # WORKITEMS
- #++
+ #--
+ # WORKITEMS
+ #++
- #
- # The base class for all the workitems.
- #
- class WorkItem
+ #
+ # The base class for all the workitems.
+ #
+ class WorkItem
- attr_accessor :last_modified, :attributes
+ attr_accessor :last_modified, :attributes
- def initialize
- @last_modified = nil
- @attributes = {}
- end
+ def initialize
+ @last_modified = nil
+ @attributes = {}
+ end
- alias :fields :attributes
- alias :fields= :attributes=
+ alias :fields :attributes
+ alias :fields= :attributes=
- #
- # Sets the last_modified field to now
- #
- def touch
+ #
+ # Sets the last_modified field to now
+ #
+ def touch
- @last_modified = Time.now
- end
+ @last_modified = Time.now
+ end
- def to_h
+ def to_h
- h = {}
- h[:type] = self.class.name
- h[:last_modified] = @last_modified
- h[:attributes] = @attributes
- h
- end
+ h = {}
+ h['type'] = self.class.name
+ h['last_modified'] = @last_modified
+ h['attributes'] = @attributes
+ h
+ end
- def self.from_h (h)
+ def self.from_h (h)
- #wi = eval("#{h[:type]}.new")
- wi = OpenWFE.get_class(h).new
- wi.last_modified = h[:last_modified]
- wi.attributes = h[:attributes]
- wi
- end
+ wi = OpenWFE.get_class(h).new
+ wi.last_modified = h['last_modified']
+ wi.attributes = h['attributes']
+ wi
+ end
- #
- # A shortcut for
- #
- # workitem.attributes['key']
- #
- # is
- #
- # workitem['key']
- #
- # (Note that
- #
- # workitem.key
- #
- # will raise an exception if there is no attribute key).
- #
- def [] (key)
+ #
+ # A shortcut for
+ #
+ # workitem.attributes['key']
+ #
+ # is
+ #
+ # workitem['key']
+ #
+ # (Note that
+ #
+ # workitem.key
+ #
+ # will raise an exception if there is no attribute key).
+ #
+ def [] (key)
- @attributes[key]
- end
+ @attributes[key]
+ end
- #
- # A shortcut for
- #
- # workitem.attributes['key'] = value
- #
- # is
- #
- # workitem['key'] = value
- #
- def []= (key, value)
+ #
+ # A shortcut for
+ #
+ # workitem.attributes['key'] = value
+ #
+ # is
+ #
+ # workitem['key'] = value
+ #
+ def []= (key, value)
- @attributes[key] = value
- end
+ @attributes[key] = value
+ end
- #
- # In order to simplify code like :
- #
- # value = workitem.attributes['xyz']
- #
- # to
- #
- # value = workitem.xyz
- #
- # or
- #
- # value = workitem['xyz']
- #
- # we overrode method_missing.
- #
- # workitem.xyz = "my new value"
- #
- # is also possible
- #
- def method_missing (m, *args)
+ #
+ # In order to simplify code like :
+ #
+ # value = workitem.attributes['xyz']
+ #
+ # to
+ #
+ # value = workitem.xyz
+ #
+ # or
+ #
+ # value = workitem['xyz']
+ #
+ # we overrode method_missing.
+ #
+ # workitem.xyz = "my new value"
+ #
+ # is also possible
+ #
+ def method_missing (m, *args)
- methodname = m.to_s
+ methodname = m.to_s
- if args.length == 0
- value = @attributes[methodname]
- return value if value
- raise "Missing attribute '#{methodname}' in workitem"
- end
+ if args.length == 0
+ value = @attributes[methodname]
+ return value if value != nil
+ raise "Missing attribute '#{methodname}' in workitem"
+ end
- #if methodname == "[]" and args.length == 1
- # value = @attributes[args[0]]
- # return value if value
- # raise "Missing attribute '#{methodname}' in workitem"
- #end
- #if methodname == "[]=" and args.length == 2
- # return @attributes[args[0]] = args[1]
- #end
+ #if methodname == "[]" and args.length == 1
+ # value = @attributes[args[0]]
+ # return value if value
+ # raise "Missing attribute '#{methodname}' in workitem"
+ #end
+ #if methodname == "[]=" and args.length == 2
+ # return @attributes[args[0]] = args[1]
+ #end
- if args.length == 1 and methodname[-1, 1] == "="
- return @attributes[methodname[0..-2]] = args[0]
- end
+ if args.length == 1 and methodname[-1, 1] == '='
+ return @attributes[methodname[0..-2]] = args[0]
+ end
- super(m, args)
- end
+ super(m, args)
+ end
- #
- # Produces a deep copy of the workitem
- #
- def dup
- OpenWFE::fulldup(self)
- end
+ #
+ # Produces a deep copy of the workitem
+ #
+ def dup
+ OpenWFE::fulldup(self)
+ end
- #
- # A smarter alternative to
- #
- # value = workitem.attributes[x]
- #
- # Via this method, nested values can be reached. For example :
- #
- # wi = InFlowWorkItem.new()
- # wi.attributes = {
- # "field0" => "value0",
- # "field1" => [ 0, 1, 2, 3, [ "a", "b", "c" ]],
- # "field2" => {
- # "a" => "AA",
- # "b" => "BB",
- # "c" => [ "C0", "C1", "C3" ]
- # },
- # "field3" => 3,
- # "field99" => nil
- # }
- #
- # will verify the following assertions :
- #
- # assert wi.lookup_attribute("field3") == 3
- # assert wi.lookup_attribute("field1.1") == 1
- # assert wi.lookup_attribute("field1.4.1") == "b"
- # assert wi.lookup_attribute("field2.c.1") == "C1"
- #
- def lookup_attribute (key)
- OpenWFE.lookup_attribute(@attributes, key)
- end
+ #
+ # A smarter alternative to
+ #
+ # value = workitem.attributes[x]
+ #
+ # Via this method, nested values can be reached. For example :
+ #
+ # wi = InFlowWorkItem.new()
+ # wi.attributes = {
+ # "field0" => "value0",
+ # "field1" => [ 0, 1, 2, 3, [ "a", "b", "c" ]],
+ # "field2" => {
+ # "a" => "AA",
+ # "b" => "BB",
+ # "c" => [ "C0", "C1", "C3" ]
+ # },
+ # "field3" => 3,
+ # "field99" => nil
+ # }
+ #
+ # will verify the following assertions :
+ #
+ # assert wi.lookup_attribute("field3") == 3
+ # assert wi.lookup_attribute("field1.1") == 1
+ # assert wi.lookup_attribute("field1.4.1") == "b"
+ # assert wi.lookup_attribute("field2.c.1") == "C1"
+ #
+ def lookup_attribute (key)
+ OpenWFE.lookup_attribute(@attributes, key)
+ end
- #
- # The partner to the lookup_attribute() method. Behaves like it.
- #
- def has_attribute? (key)
- OpenWFE.has_attribute?(@attributes, key)
- end
+ #
+ # The partner to the lookup_attribute() method. Behaves like it.
+ #
+ def has_attribute? (key)
+ OpenWFE.has_attribute?(@attributes, key)
+ end
- #
- # set_attribute() accomodates itself with nested key constructs.
- #
- def set_attribute (key, value)
- OpenWFE.set_attribute(@attributes, key, value)
- end
-
- #
- # unset_attribute() accomodates itself with nested key constructs.
- #
- def unset_attribute (key)
- OpenWFE.unset_attribute(@attributes, key)
- end
-
- alias :lookup_field :lookup_attribute
- alias :has_field? :has_attribute?
- alias :set_field :set_attribute
- alias :unset_field :unset_attribute
-
+ #
+ # set_attribute() accomodates itself with nested key constructs.
+ #
+ def set_attribute (key, value)
+ OpenWFE.set_attribute(@attributes, key, value)
end
#
- # The common parent class for InFlowWorkItem and CancelItem.
+ # unset_attribute() accomodates itself with nested key constructs.
#
- class InFlowItem < WorkItem
+ def unset_attribute (key)
+ OpenWFE.unset_attribute(@attributes, key)
+ end
- attr_accessor :flow_expression_id, :participant_name
+ alias :lookup_field :lookup_attribute
+ alias :has_field? :has_attribute?
+ alias :set_field :set_attribute
+ alias :unset_field :unset_attribute
- def last_expression_id
- @flow_expression_id
- end
+ end
- def last_expression_id= (fei)
- @flow_expression_id = fei
- end
+ #
+ # The common parent class for InFlowWorkItem and CancelItem.
+ #
+ class InFlowItem < WorkItem
- #
- # Just a handy alias for flow_expression_id
- #
- alias :fei :flow_expression_id
- alias :fei= :flow_expression_id=
+ attr_accessor :flow_expression_id, :participant_name
- def to_h
- h = super
- h[:flow_expression_id] = @flow_expression_id.to_h
- h[:participant_name] = @participant_name
- h
- end
+ def last_expression_id
+ @flow_expression_id
+ end
- def InFlowItem.from_h (h)
- wi = super
- wi.flow_expression_id = FlowExpressionId.from_h(h[:flow_expression_id])
- wi.participant_name = h[:participant_name]
- wi
- end
+ def last_expression_id= (fei)
+ @flow_expression_id = fei
end
#
- # When the term 'workitem' is used it's generally referring to instances
- # of this InFlowWorkItem class.
- # InFlowWorkItem are circulating within process instances and carrying
- # data around. Their 'payload' is located in their attribute Hash field.
+ # Just a handy alias for flow_expression_id
#
- class InFlowWorkItem < InFlowItem
+ alias :fei :flow_expression_id
+ alias :fei= :flow_expression_id=
- attr_accessor :dispatch_time
- attr_accessor :filter
+ def to_h
+ h = super
+ h['flow_expression_id'] = @flow_expression_id.to_h
+ h['participant_name'] = @participant_name
+ h
+ end
- #
- # In OpenWFEja, workitem history was stored, OpenWFEru doesn't do
- # it (no need to copy history over and over).
- #
- # (deprecated)
- #
- attr_accessor :history
+ def InFlowItem.from_h (h)
+ wi = super
+ wi.flow_expression_id = FlowExpressionId.from_h(h['flow_expression_id'])
+ wi.participant_name = h['participant_name']
+ wi
+ end
+ end
- attr_accessor :store
- #
- # special : added by the ruby lib, not given by the worklist
+ #
+ # When the term 'workitem' is used it's generally referring to instances
+ # of this InFlowWorkItem class.
+ # InFlowWorkItem are circulating within process instances and carrying
+ # data around. Their 'payload' is located in their attribute Hash field.
+ #
+ class InFlowWorkItem < InFlowItem
- #
- # Outputting the workitem in a human readable format
- #
- def to_s
+ attr_accessor :dispatch_time
+ attr_accessor :filter
- s = ""
- s << " #{self.class} :\n"
- s << " - flow_expression_id : #{@flow_expression_id}\n"
- s << " - participant_name : #{@participant_name}\n"
- s << " - last_modified : #{@last_modified}\n"
- s << " - dispatch_time : #{@dispatch_time}\n"
- s << " - attributes :\n"
+ #
+ # in some contexts (ruote-rest, ruote-web2, the web...) workitems
+ # have an URI
+ #
+ attr_accessor :uri
- s << " {\n"
- @attributes.keys.sort.each do |k|
- v = @attributes[k]
- s << " #{k.inspect} => #{v.inspect},\n"
- end
- s << " }"
- s
- end
+ #
+ # In OpenWFEja, workitem history was stored, OpenWFEru doesn't do
+ # it (no need to copy history over and over).
+ #
+ # (deprecated)
+ #
+ attr_accessor :history
- #
- # For some easy YAML encoding, turns the workitem into a Hash
- # (Any YAML-enabled platform can thus read it).
- #
- def to_h
+ attr_accessor :store
+ #
+ # special : added by the ruby lib, not given by the worklist
- h = super
- h[:dispatch_time] = @dispatch_time
- #h[:history] = @history
- h[:filter] = @filter
- h
- end
+ #
+ # Outputting the workitem in a human readable format
+ #
+ def to_s
- #
- # Rebuilds an InFlowWorkItem from its hash version.
- #
- def InFlowWorkItem.from_h (h)
+ s = ""
+ s << " #{self.class} :\n"
+ s << " - flow_expression_id : #{@flow_expression_id}\n"
+ s << " - participant_name : #{@participant_name}\n"
+ s << " - last_modified : #{@last_modified}\n"
+ s << " - dispatch_time : #{@dispatch_time}\n"
+ s << " - attributes :\n"
- wi = super
- wi.dispatch_time = h[:dispatch_time]
- #wi.history = h[:history]
- wi.filter = h[:filter]
- wi
- end
+ s << " {\n"
+ @attributes.keys.sort.each do |k|
+ v = @attributes[k]
+ s << " #{k.inspect} => #{v.inspect},\n"
+ end
+ s << " }"
+ s
+ end
- #
- # Sets the '__result__' field of this workitem
- #
- def set_result (result)
+ #
+ # For some easy YAML encoding, turns the workitem into a Hash
+ # (Any YAML-enabled platform can thus read it).
+ #
+ def to_h
- @attributes[FIELD_RESULT] = result
- end
+ h = super
+ h['dispatch_time'] = @dispatch_time
+ #h[:history] = @history
+ h['filter'] = @filter
+ h
+ end
- #
- # Makes sure the '__result__' field of this workitem is empty.
- #
- def unset_result
+ #
+ # Rebuilds an InFlowWorkItem from its hash version.
+ #
+ def InFlowWorkItem.from_h (h)
- @attributes.delete FIELD_RESULT
- end
+ wi = super
+ wi.dispatch_time = h['dispatch_time']
+ wi.filter = h['filter']
+ wi
+ end
- #
- # Just a shortcut (for consistency) of
- #
- # workitem.attributes["__result__"]
- #
- def get_result
+ #
+ # Sets the '__result__' field of this workitem
+ #
+ def set_result (result)
- @attributes[FIELD_RESULT]
- end
+ @attributes[FIELD_RESULT] = result
+ end
- #
- # Returns true or false.
- #
- def get_boolean_result
+ #
+ # Makes sure the '__result__' field of this workitem is empty.
+ #
+ def unset_result
- r = get_result
- return false unless r
- (r == true or r == "true")
- end
+ @attributes.delete FIELD_RESULT
end
#
- # When it needs to cancel a branch of a process instance, the engine
- # emits a CancelItem towards it.
- # It's especially important for participants to react correctly upon
- # receiving a cancel item.
+ # Just a shortcut (for consistency) of
#
- class CancelItem < InFlowItem
+ # workitem.attributes["__result__"]
+ #
+ def get_result
- def initialize (workitem)
-
- super()
- @flow_expression_id = workitem.fei.dup
- end
+ @attributes[FIELD_RESULT]
end
#
- # LaunchItem instances are used to instantiate and launch processes.
- # They contain attributes that are used as the initial payload of the
- # workitem circulating in the process instances.
+ # Returns true or false.
#
- class LaunchItem < WorkItem
+ def get_boolean_result
- DEF = "__definition"
- FIELD_DEF = "field:#{DEF}"
+ r = get_result
+ return false unless r
+ (r == true or r == 'true')
+ end
+ end
- attr_accessor :workflow_definition_url
- #, :description_map
+ #
+ # When it needs to cancel a branch of a process instance, the engine
+ # emits a CancelItem towards it.
+ # It's especially important for participants to react correctly upon
+ # receiving a cancel item.
+ #
+ class CancelItem < InFlowItem
- alias :wfdurl :workflow_definition_url
- alias :wfdurl= :workflow_definition_url=
+ def initialize (workitem)
- #
- # This constructor will build an empty LaunchItem.
- #
- # If the optional parameter process_definition is set, the
- # definition will be embedded in the launchitem attributes
- # for retrieval by the engine.
- #
- # There are several ways to specify the process definition.
- # Here are some examples:
- #
- # # Use a Ruby class that extends OpenWFE::ProcessDefinition
- # LaunchItem.new(MyProcessDefinition)
- #
- # # Provide an XML process definition as a string
- # definition = """
- # <process-definition name="x" revision="y">
- # <sequence>
- # <participant ref="alpha" />
- # <participant ref="bravo" />
- # </sequence>
- # </process-definition>
- # """.strip
- # LaunchItem.new(definition)
- #
- # # Load an XML process definition from a local file
- # require 'uri'
- # LaunchItem.new(URI.parse("file:///tmp/my_process_definition.xml"))
- #
- # # If you initialized your engine with
- # # {:remote_definitions_allowed => true}, then you can also load an
- # # XML process definition from a remote url
- # require 'uri'
- # LaunchItem.new(URI.parse("http://foo.bar/my_process_definition.xml"))
- #
- def initialize (process_definition=nil)
+ super()
+ @flow_expression_id = workitem.fei.dup
+ end
+ end
- super()
+ #
+ # LaunchItem instances are used to instantiate and launch processes.
+ # They contain attributes that are used as the initial payload of the
+ # workitem circulating in the process instances.
+ #
+ class LaunchItem < WorkItem
- if process_definition
- @workflow_definition_url = FIELD_DEF
- @attributes[DEF] = process_definition
- end
- end
+ DEF = "__definition"
+ FIELD_DEF = "field:#{DEF}"
- #
- # Turns the LaunchItem instance into a simple 'hash' (easily
- # serializable to other formats).
- #
- def to_h
+ attr_accessor :workflow_definition_url
+ #, :description_map
- h = super
- h[:workflow_definition_url] = @workflow_definition_url
- h
- end
+ alias :wfdurl :workflow_definition_url
+ alias :wfdurl= :workflow_definition_url=
- def self.from_h (h)
+ #
+ # This constructor will build an empty LaunchItem.
+ #
+ # If the optional parameter process_definition is set, the
+ # definition will be embedded in the launchitem attributes
+ # for retrieval by the engine.
+ #
+ # There are several ways to specify the process definition.
+ # Here are some examples:
+ #
+ # # Use a Ruby class that extends OpenWFE::ProcessDefinition
+ # LaunchItem.new(MyProcessDefinition)
+ #
+ # # Provide an XML process definition as a string
+ # definition = """
+ # <process-definition name="x" revision="y">
+ # <sequence>
+ # <participant ref="alpha" />
+ # <participant ref="bravo" />
+ # </sequence>
+ # </process-definition>
+ # """.strip
+ # LaunchItem.new(definition)
+ #
+ # # Load an XML process definition from a local file
+ # require 'uri'
+ # LaunchItem.new(URI.parse("file:///tmp/my_process_definition.xml"))
+ #
+ # # If you initialized your engine with
+ # # {:remote_definitions_allowed => true}, then you can also load an
+ # # XML process definition from a remote url
+ # require 'uri'
+ # LaunchItem.new(URI.parse("http://foo.bar/my_process_definition.xml"))
+ #
+ def initialize (process_definition=nil)
- li = super
- li.workflow_definition_url = h[:workflow_definition_url]
- li
- end
+ super()
+
+ if process_definition
+ @workflow_definition_url = FIELD_DEF
+ @attributes[DEF] = process_definition
+ end
end
#
- # Turns a hash into its corresponding workitem (InFlowWorkItem, CancelItem,
- # LaunchItem).
+ # Turns the LaunchItem instance into a simple 'hash' (easily
+ # serializable to other formats).
#
- def OpenWFE.workitem_from_h (h)
+ def to_h
- #wi_class = eval(h[:type])
- wi_class = get_class(h)
- wi_class.from_h(h)
+ h = super
+ h['workflow_definition_url'] = @workflow_definition_url
+ h
end
- def OpenWFE.get_class (h)
+ def self.from_h (h)
- cl = h[:type]
- return nil if cl.index(";")
- return nil if cl.index(" ")
- eval(cl)
+ li = super
+ li.workflow_definition_url = h['workflow_definition_url']
+ li
end
+ end
+
+ #
+ # Turns a hash into its corresponding workitem (InFlowWorkItem, CancelItem,
+ # LaunchItem).
+ #
+ def OpenWFE.workitem_from_h (h)
+
+ wi_class = get_class(h)
+ wi_class.from_h(h)
+ end
+
+ WI_CLASSES = [
+ OpenWFE::LaunchItem, OpenWFE::InFlowWorkItem, OpenWFE::CancelItem
+ ].inject({}) { |r, c| r[c.to_s] = c; r }
+
+ #
+ # returns the workitem class for the given hash
+ #
+ def OpenWFE.get_class (h)
+
+ WI_CLASSES[h['type']]
+ end
end