lib/ruote/fei.rb in ruote-2.1.11 vs lib/ruote/fei.rb in ruote-2.2.0
- old
+ new
@@ -1,7 +1,7 @@
#--
-# Copyright (c) 2005-2010, John Mettraux, jmettraux@gmail.com
+# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@@ -20,10 +20,12 @@
# THE SOFTWARE.
#
# Made in Japan.
#++
+require 'digest/md5'
+
require 'ruote/version'
require 'ruote/workitem'
require 'ruote/util/misc'
require 'ruote/util/hashdot'
@@ -32,25 +34,54 @@
# A shortcut for
#
# Ruote::FlowExpressionId.to_storage_id(fei)
#
- def self.to_storage_id (fei)
+ def self.to_storage_id(fei)
Ruote::FlowExpressionId.to_storage_id(fei)
end
# A shorter shortcut for
#
# Ruote::FlowExpressionId.to_storage_id(fei)
#
- def self.sid (fei)
+ def self.sid(fei)
Ruote::FlowExpressionId.to_storage_id(fei)
end
+ # A shortcut for
#
+ # Ruote::FlowExpressionId.is_a_fei?(o)
+ #
+ def self.is_a_fei?(o)
+
+ Ruote::FlowExpressionId.is_a_fei?(o)
+ end
+
+ # Will do its best to return a wfid (String) or a fei (Hash instance)
+ # extract from the given o argument.
+ #
+ def self.extract_id(o)
+
+ return o if o.is_a?(String) and o.index('!').nil? # wfid
+
+ Ruote::FlowExpressionId.extract_h(o)
+ end
+
+ # This function is used to generate the subids. Each flow
+ # expression receives such an id (it's useful for cursors, loops and
+ # forgotten branches).
+ #
+ def self.generate_subid(salt)
+
+ Digest::MD5.hexdigest(
+ "#{rand}-#{salt}-#{$$}-#{Thread.current.object_id}#{Time.now.to_f}")
+ end
+
+ #
# The FlowExpressionId (fei for short) is an process expression identifier.
# Each expression when instantiated gets a unique fei.
#
# Feis are also used in workitems, where the fei is the fei of the
# [participant] expression that emitted the workitem.
@@ -58,103 +89,110 @@
# Feis can thus indicate the position of a workitem in a process tree.
#
# Feis contain four pieces of information :
#
# * wfid : workflow instance id, the identifier for the process instance
- # * sub_wfid : the identifier for the sub process within the main instance
+ # * subid : a unique identifier for expressions (useful in loops)
# * expid : the expression id, where in the process tree
# * engine_id : only relevant in multi engine scenarii (defaults to 'engine')
#
class FlowExpressionId
CHILD_SEP = '_'
attr_reader :h
- def initialize (h)
+ def initialize(h)
@h = h
class << h; include Ruote::HashDot; end
- end
- def expid
- @h['expid']
+ @h['subid'] = @h.delete('sub_wfid') if @h['sub_wfid']
+ # TODO : for 2.1.13, remove this
end
- def wfid
- @h['wfid']
- end
+ def expid; @h['expid']; end
+ def wfid; @h['wfid']; end
+ def engine_id; @h['engine_id']; end
+ def subid; @h['subid']; end
- def sub_wfid
- @h['sub_wfid']
- end
+ alias sub_wfid subid
- def engine_id
- @h['engine_id']
- end
-
def to_storage_id
- "#{@h['expid']}!#{@h['sub_wfid']}!#{@h['wfid']}"
+ "#{@h['expid']}!#{@h['subid']}!#{@h['wfid']}"
end
-
alias sid to_storage_id
- def self.to_storage_id (hfei)
+ def self.to_storage_id(hfei)
hfei.respond_to?(:to_storage_id) ?
hfei.to_storage_id :
- "#{hfei['expid']}!#{hfei['sub_wfid']}!#{hfei['wfid']}"
+ "#{hfei['expid']}!#{hfei['subid'] || hfei['sub_wfid']}!#{hfei['wfid']}"
+
+ # TODO : for 2.1.13, remove the subid || sub_wfid trick
end
# Turns the result of to_storage_id back to a FlowExpressionId instance.
#
- def self.from_id (s, engine_id='engine')
+ def self.from_id(s, engine_id='engine')
extract("#{engine_id}!#{s}")
end
# Returns the last number in the expid. For instance, if the expid is
# '0_5_7', the child_id will be '7'.
#
def child_id
+
h.expid.split(CHILD_SEP).last.to_i
end
def hash
+
to_storage_id.hash
end
- def == (other)
+ # Returns true if the other is a FlowExpressionId instance and it
+ # points to the same expression as this one.
+ #
+ def ==(other)
return false unless other.is_a?(Ruote::FlowExpressionId)
(hash == other.hash)
end
alias eql? ==
+ SUBS = %w[ subid sub_wfid ]
+ IDS = %w[ engine_id expid wfid ]
+
# Returns true if the h is a representation of a FlowExpressionId instance.
#
- def self.is_a_fei? (h)
+ def self.is_a_fei?(h)
- h.respond_to?(:keys) &&
- (h.keys - [ 'sub_wfid' ]).sort == %w[ engine_id expid wfid ]
+ h.respond_to?(:keys) && (h.keys - SUBS).sort == IDS
end
# Returns child_id... For an expid of '0_1_4', this will be 4.
#
- def self.child_id (h)
+ def self.child_id(h)
+
h['expid'].split(CHILD_SEP).last.to_i
end
def to_h
+
@h
end
- def self.direct_child? (parent_fei, other_fei)
+ # Returns true if other_fei is the fei of a child expression of
+ # parent_fei.
+ #
+ def self.direct_child?(parent_fei, other_fei)
- %w[ sub_wfid wfid engine_id ].each do |k|
+ %w[ wfid engine_id ].each do |k|
return false if parent_fei[k] != other_fei[k]
end
pei = other_fei['expid'].split(CHILD_SEP)[0..-2].join(CHILD_SEP)
@@ -164,19 +202,19 @@
# Attempts at extracting a FlowExpressionId from the given argument
# (workitem, string, ...)
#
# Uses .extract_h
#
- def self.extract (arg)
+ def self.extract(arg)
FlowExpressionId.new(extract_h(arg))
end
# Attempts at extracting a FlowExpressionId (as a Hash instance) from the
# given argument (workitem, string, ...)
#
- def self.extract_h (arg)
+ def self.extract_h(arg)
if arg.is_a?(Hash)
return arg if arg['expid']
return arg['fei'] if arg['fei']
end
@@ -189,10 +227,12 @@
ss = arg.split('!')
return {
'engine_id' => ss[-4] || 'engine',
- 'expid' => ss[-3], 'sub_wfid' => ss[-2], 'wfid' => ss[-1] }
+ 'expid' => ss[-3],
+ 'subid' => ss[-2],
+ 'wfid' => ss[-1] }
end
raise ArgumentError.new(
"couldn't extract fei out of instance of #{arg.class}")
end