GONE | = | "gone" | ||
GONE_PARENT_ID | = | FlowExpressionId.new | This special flow expression id is used by the forget() method (which is used by the forget expression and the concurrence synchronization expressions) | |
SPLIT_MAP | = | { "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" => UuidWfidGenerator, "[0-9]{8}-[a-z]*" => KotobaWfidGenerator | "module methods" | |
VAR_PAUSED | = | '/__paused__' | When this variable is set to true (at the process root), it means the process is paused. | |
KEYWORDS | = | [ :if, :do, :redo, :undo, :print, :sleep, :loop, :break, :when |
OpenWFE process definitions do use some Ruby
keywords… The workaround is to put an underscore just before the name
to ‘escape’ it.
‘undo’ isn‘t reserved by Ruby, but lets keep it in line with ‘do’ and ‘redo’ that are. |
|
NAME | = | 'name' | ||
STORE | = | 'store' | ||
STORES | = | 'stores' | ||
WORKITEM_COUNT | = | 'workitem-count' | ||
PERMISSIONS | = | 'permissions' | ||
HEADER | = | 'header' | ||
HEADERS | = | 'headers' | ||
A_LAST_MODIFIED | = | 'last-modified' | ||
A_LOCKED | = | 'locked' | ||
FLOW_EXPRESSION_ID | = | 'flow-expression-id' | ||
ATTRIBUTES | = | 'attributes' | ||
OWFE_VERSION | = | 'owfe-version' | ||
ENGINE_ID | = | 'engine-id' | ||
INITIAL_ENGINE_ID | = | 'initial-engine-id' | ||
WORKFLOW_DEFINITION_URL | = | 'workflow-definition-url' | ||
WORKFLOW_DEFINITION_NAME | = | 'workflow-definition-name' | ||
WORKFLOW_DEFINITION_REVISION | = | 'workflow-definition-revision' | ||
WORKFLOW_INSTANCE_ID | = | 'workflow-instance-id' | ||
EXPRESSION_NAME | = | 'expression-name' | ||
EXPRESSION_ID | = | 'expression-id' | ||
E_STRING | = | 'string' | ||
E_INTEGER | = | 'integer' | ||
E_BOOLEAN | = | 'boolean' | ||
E_LONG | = | 'long' | ||
E_DOUBLE | = | 'double' | ||
E_RAW_XML | = | 'raw-xml' | ||
E_XML_DOCUMENT | = | 'xml-document' | ||
E_BASE64 | = | 'base64' | ||
E_LIST | = | 'list' | ||
E_MAP | = | 'map' | ||
E_SMAP | = | 'smap' | ||
M_ENTRY | = | 'entry' | ||
M_KEY | = | 'key' | ||
M_VALUE | = | 'value' | ||
MAP_TYPE | = | '___map_type' | ||
FLOW_EXPRESSION_IDS | = | 'flow-expression-ids' | ||
LAUNCHITEM | = | 'launchitem' | ||
ENGINEID | = | "engineid" | ||
OK | = | "ok" | ||
A_FLOW_ID | = | "flow-id" | ||
IN_FLOW_WORKITEM | = | 'workitem' | ||
A_DISPATCH_TIME | = | 'dispatch-time' | ||
A_PARTICIPANT_NAME | = | 'participant-name' | ||
E_LAST_EXPRESSION_ID | = | 'last-expression-id' | ||
LAUNCHABLES | = | 'launchables' | ||
LAUNCHABLE | = | 'launchable' | ||
URL | = | 'url' | ||
TARGETSTORE | = | 'targetstore' | ||
EXPRESSIONS | = | 'expressions' | ||
EXPRESSION | = | 'expression' | ||
APPLY_TIME | = | 'apply-time' | ||
STATE | = | 'state' | ||
STATE_SINCE | = | 'state-since' | ||
HISTORY | = | 'history' | ||
HISTORY_ITEM | = | 'history-item' | ||
A_AUTHOR | = | 'author' | ||
A_DATE | = | 'date' | ||
A_HOST | = | 'host' | ||
S_LOGGER | = | :logger | service names | |
S_ENGINE | = | 'engine' | ||
S_EXPRESSION_MAP | = | 'expressionMap' | ||
S_WFID_GENERATOR | = | 'wfidGenerator' | ||
S_EXPRESSION_POOL | = | 'expressionPool' | ||
S_EXPRESSION_STORAGE | = | 'expressionStorage' | ||
S_PARTICIPANT_MAP | = | 'participantMap' | ||
S_SCHEDULER | = | 'scheduler' | ||
S_ERROR_JOURNAL | = | 'errorJournal' | ||
EN_ENVIRONMENT | = | 'environment' | some special expression names | |
DEFAULT_WORK_DIRECTORY | = | 'work' | some file storage default values | |
DSUB_SAFETY_LEVEL | = | 4 | ||
OPENWFERU_VERSION | = | '0.9.18' | ||
FIELD_RESULT | = | "__result__" | The convention for the result of some expressions is to store their result in a workitem field named "result". |
Some code for writing thinks like :
if async OpenWFE::call_in_thread "launch()", self do raw_expression.apply(wi) end else raw_expression.apply(wi) end
Returns the new thread instance.
# File lib/openwfe/utils.rb, line 291 291: def OpenWFE.call_in_thread (caller_name, caller_object=nil, &block) 292: 293: return unless block 294: 295: Thread.new do 296: 297: #set_current_thread_name "call_in_thread() for '#{caller_name}'" 298: set_current_thread_name caller_name 299: 300: begin 301: #$SAFE = safe_level 302: # 303: # (note) 304: # doesn't work : the block inherits the safety level 305: # of its surroundings, it's a closure, ne ? 306: 307: block.call 308: 309: rescue Exception => e 310: msg = "#{caller_name} caught an exception\n" + exception_to_s(e) 311: if caller_object and caller_object.respond_to? :lwarn 312: caller_object.lwarn { msg } 313: else 314: puts msg 315: end 316: end 317: end 318: # returns the thread 319: end
Pretty printing a caller() array
# File lib/openwfe/utils.rb, line 256 256: def OpenWFE.caller_to_s (start_index, max_lines=nil) 257: s = "" 258: caller(start_index + 1).each_with_index do |line, index| 259: break if max_lines and index >= max_lines 260: s << " #{line}\n" 261: end 262: s 263: end
"my//path" -> "my/path"
# File lib/openwfe/utils.rb, line 381 381: def OpenWFE.clean_path (s) 382: s.gsub(/\/+/, "/") 383: end
see wiki.rubygarden.org/Ruby/page/show/Make_A_Deep_Copy_Of_An_Object
It‘s not perfect (that‘s why fulldup() uses it only in certain cases).
For example :
TypeError: singleton can't be dumped ./lib/openwfe/utils.rb:74:in `dump' ./lib/openwfe/utils.rb:74:in `deep_clone'
# File lib/openwfe/utils.rb, line 72 72: def OpenWFE.deep_clone (object) 73: 74: Marshal::load(Marshal.dump(object)) 75: end
Dispatches a workitem over TCP, the workitem will be encoded with XML The default encode_method is
# File lib/openwfe/orest/osocket.rb, line 93 93: def OpenWFE.dispatch_workitem (host, port, workitem) 94: 95: #sXml = OpenWFE.xml_encode(workitem) 96: sXml = OpenWFE::XmlCodec::encode workitem 97: 98: socket = TCPSocket.new(host, port) 99: socket.puts "xmlCoder #{sXml.length}" 100: socket.puts 101: socket.puts sXml 102: socket.puts 103: socket.close_write 104: 105: reply = socket.gets 106: 107: #reply = reply + socket.gets 108: # 109: # a bit ridiculous, but it works 110: # socket.close_write fixed it 111: 112: socket.close 113: 114: #puts "dispatch() reply is >#{reply}<" 115: end
Performs ‘dollar substitution’ on a piece of text with as input a flow expression and a workitem (fields and variables).
# File lib/openwfe/util/dollar.rb, line 62 62: def OpenWFE.dosub (text, flow_expression, workitem) 63: 64: # 65: # patch by Nick Petrella (2008/03/20) 66: # 67: 68: if text.is_a?(String) 69: 70: Rufus::dsub(text, FlowDict.new(flow_expression, workitem)) 71: 72: elsif text.is_a?(Array) 73: 74: text.collect { |e| dosub(e, flow_expression, workitem) } 75: 76: elsif text.is_a?(Hash) 77: 78: text.inject({}) do |r, (k, v)| 79: 80: r[dosub(k, flow_express, workitem)] = 81: dosub(v, flow_expression, workitem) 82: r 83: end 84: 85: else 86: 87: text 88: end 89: end
Returns true if the given string ends with the ‘_end’ string.
# File lib/openwfe/utils.rb, line 237 237: def OpenWFE.ends_with (string, _end) 238: return false unless string 239: return false if string.length < _end.length 240: string[-_end.length..-1] == _end 241: end
Returns a version of s that is usable as or within a filename (removes for examples things like ’/’ or ’\’…)
# File lib/openwfe/utils.rb, line 364 364: def OpenWFE.ensure_for_filename (s) 365: 366: s = s.gsub(" ", "_") 367: s = s.gsub("/", "_") 368: s = s.gsub(":", "_") 369: s = s.gsub(";", "_") 370: s = s.gsub("\*", "_") 371: s = s.gsub("\\", "_") 372: s = s.gsub("\+", "_") 373: s = s.gsub("\?", "_") 374: 375: s 376: end
Attempts at displaying a nice stack trace
# File lib/openwfe/utils.rb, line 246 246: def OpenWFE.exception_to_s (exception) 247: s = "exception : " 248: s << "#{exception}\n" 249: s << exception.backtrace.join("\n") 250: s 251: end
Returns the first subelt of xmlElt that matches the given xpath. If xpath is null, the first elt will be returned.
# File lib/openwfe/utils.rb, line 51 51: def OpenWFE.first_element (xmlElt, elementName=nil) 52: 53: return nil if not xmlElt 54: 55: return xmlElt.elements[1] if not elementName 56: 57: xmlElt.elements.detect { |elt| elt.name == elementName } 58: end
an automatic dup implementation attempt
# File lib/openwfe/utils.rb, line 80 80: def OpenWFE.fulldup (object) 81: 82: return nil if object == nil 83: 84: return object.fulldup if object.respond_to?("fulldup") 85: # trusting client objects providing a fulldup() implementation 86: # Tomaso Tosolini 2007.12.11 87: 88: return object if object.kind_of?(Float) 89: return object if object.kind_of?(Fixnum) 90: return object if object.kind_of?(TrueClass) 91: return object if object.kind_of?(FalseClass) 92: return object if object.kind_of?(Symbol) 93: 94: return object.dup if object.kind_of?(String) 95: 96: #return deep_clone(object) if object.kind_of? REXML::Document 97: 98: #return REXML::Document.new(object.to_s) # if object.kind_of? REXML::Document 99: 100: if object.kind_of?(REXML::Element) 101: d = REXML::Document.new object.to_s 102: return d if object.kind_of?(REXML::Document) 103: return d.root 104: end 105: 106: return Rational(object.denominator, object.numerator) \ 107: if object.kind_of?(Rational) 108: 109: o = nil 110: 111: begin 112: o = object.class.new 113: rescue ArgumentError => ae 114: return deep_clone(object) 115: end 116: 117: # 118: # some kind of collection ? 119: 120: if object.kind_of?(Array) 121: object.each do |i| 122: o << fulldup(i) 123: end 124: elsif object.kind_of?(Hash) 125: object.each do |k, v| 126: o[fulldup(k)] = fulldup(v) 127: end 128: end 129: 130: # 131: # duplicate the attributes of the object 132: 133: object.instance_variables.each do |v| 134: 135: #puts "v is #{v}" 136: 137: value = object.instance_variable_get(v) 138: 139: #puts "value is '#{value}'" 140: 141: value = fulldup(value) 142: 143: begin 144: o.instance_variable_set(v, value) 145: rescue 146: # ignore, must be readonly 147: end 148: end 149: 150: o 151: end
# File lib/openwfe/workitem.rb, line 481 481: def OpenWFE.get_class (h) 482: 483: cl = h[:type] 484: return nil if cl.index(";") 485: return nil if cl.index(" ") 486: eval(cl) 487: end
Returns a list of lines matching the pattern in the given file.
This is also possible :
OpenWFE::grep "^..) ", "path/to/file.txt" do |line| puts " - '#{line.downcase}'" end
TODO : find a ruby library and use it instead of that code
# File lib/openwfe/utils.rb, line 441 441: def OpenWFE.grep (pattern, filepath, &block) 442: 443: result = [] 444: r = Regexp.new pattern 445: 446: File.open filepath do |file| 447: file.readlines.each do |l| 448: if r.match l 449: if block 450: block.call l 451: else 452: result << l 453: end 454: end 455: end 456: end 457: result unless block 458: end
This method is used within the InFlowWorkItem and the CsvTable classes.
# File lib/openwfe/utils.rb, line 410 410: def OpenWFE.has_attribute? (container, key) 411: 412: key, last_key = pop_last_key(key) 413: 414: container = lookup_attribute(container, key) if key 415: 416: if container.respond_to?(:has_key?) 417: 418: (container.has_key?(last_key) or container.has_key?(last_key.to_s)) 419: 420: elsif container.is_a?(Array) and last_key.is_a?(Fixnum) 421: 422: (last_key < container.length) 423: 424: else 425: 426: false 427: end 428: end
This method is used within the InFlowWorkItem and the CsvTable classes.
# File lib/openwfe/utils.rb, line 388 388: def OpenWFE.lookup_attribute (container, key) 389: 390: key, rest = pop_key(key) 391: 392: #value = nil 393: #begin 394: # value = container[key] 395: #rescue Exception => e 396: #end 397: 398: value = flex_lookup(container, key) 399: 400: return value unless rest 401: 402: return nil unless value 403: 404: lookup_attribute(value, rest) 405: end
# File lib/openwfe/utils.rb, line 169 169: def OpenWFE.name_to_symbol (name) 170: 171: return name if name.is_a?(Symbol) 172: to_underscore(name).intern 173: end
Returns a URI instance if the given ref is a http, https, file or ftp URI. Returns nil else. The sister method parse_uri() is OK with things like mailto:, gopher:, …
# File lib/openwfe/utils.rb, line 205 205: def OpenWFE.parse_known_uri (ref) 206: 207: uri = OpenWFE::parse_uri(ref.to_s) 208: 209: return nil unless uri 210: 211: return uri if uri.scheme == "file" 212: return uri if uri.scheme == "http" 213: return uri if uri.scheme == "https" 214: return uri if uri.scheme == "ftp" 215: # what else ... 216: 217: nil 218: end
Returns an URI if the string is one, else returns nil. No exception is thrown by this method.
# File lib/openwfe/utils.rb, line 188 188: def OpenWFE.parse_uri (string) 189: 190: return nil if string.split("\n").size > 1 191: 192: begin 193: return URI::parse(string) 194: rescue Exception => e 195: end 196: 197: nil 198: end
Renders a nice, terminal oriented, representation of an Engine.get_process_status() result.
You usually directly benefit from this when doing
puts engine.get_process_status.to_s
# File lib/openwfe/engine/status_methods.rb, line 241 241: def OpenWFE.pretty_print_process_status (ps) 242: 243: # TODO : include launch_time and why is process_id so long ? 244: 245: s = "" 246: s << "process_id | name | rev | brn | err | paused? \n" 247: s << "--------------------+-------------------+---------+-----+-----+---------\n" 248: 249: ps.keys.sort.each do |wfid| 250: 251: status = ps[wfid] 252: fexp = status.expressions.first 253: ffei = fexp.fei 254: 255: s << "%-19s" % wfid[0, 19] 256: s << " | " 257: s << "%-17s" % ffei.workflow_definition_name[0, 17] 258: s << " | " 259: s << "%-7s" % ffei.workflow_definition_revision[0, 7] 260: s << " | " 261: s << "%3s" % status.expressions.size.to_s[0, 3] 262: s << " | " 263: s << "%3s" % status.errors.size.to_s[0, 3] 264: s << " | " 265: s << "%5s" % status.paused?.to_s 266: s << "\n" 267: end 268: s 269: end
This method is used within the InFlowWorkItem and the CsvTable classes.
# File lib/openwfe/utils.rb, line 463 463: def OpenWFE.set_attribute (container, key, value) 464: 465: i = key.rindex(".") 466: 467: if not i 468: container[key] = value 469: return 470: end 471: 472: container = lookup_attribute(container, key[0..i-1]) 473: container[key[i+1..-1]] = value 474: end
Sets the name of the current thread (the attribute :name if it is a ruby thread, the java thread name if we‘re in JRuby)
# File lib/openwfe/utils.rb, line 269 269: def OpenWFE.set_current_thread_name (name) 270: if defined?(JRUBY_VERSION) 271: require 'java' 272: java.lang.Thread.current_thread.name = "#{name} (Ruby Thread)" 273: else 274: Thread.current[:name] = name 275: end 276: end
This method should be able to split any wfid whose scheme is implemented here.
# File lib/openwfe/expool/wfidgen.rb, line 376 376: def OpenWFE.split_wfid (wfid) 377: 378: SPLIT_MAP.each do |regex, clazz| 379: return clazz.split_wfid(wfid) if wfid.match(regex) 380: end 381: # 382: # else 383: # 384: DefaultWfidGenerator.split_wfid(wfid) 385: end
Returns true if the given string starts with the ‘start’ string.
# File lib/openwfe/utils.rb, line 223 223: def OpenWFE.starts_with (string, start) 224: # 225: # my favourite way of doing that would be by adding this 226: # method to the String class, but that could be intrusive 227: # (as OpenWFE is meant at first as an embeddable workflow engine). 228: # 229: return false unless string 230: return false if string.length < start.length 231: string[0, start.length] == start 232: end
Turns all the spaces in string into underscores. Returns the new String.
# File lib/openwfe/utils.rb, line 179 179: def OpenWFE.stu (s) 180: 181: s.gsub("\s", "_") 182: end
# File lib/openwfe/utils.rb, line 164 164: def OpenWFE.symbol_to_name (symbol) 165: 166: to_dash(symbol.to_s) 167: end
# File lib/openwfe/utils.rb, line 159 159: def OpenWFE.to_dash (string) 160: 161: string.gsub("_", "-") 162: end
# File lib/openwfe/utils.rb, line 154 154: def OpenWFE.to_underscore (string) 155: 156: string.gsub("-", "_") 157: end
Binds the SIGINT signal so that a console is opened with the bindings specified in ‘args’.
# File lib/openwfe/util/irb.rb, line 57 57: def OpenWFE.trap_int_irb (*args) 58: trap 'INT' do 59: OpenWFE.start_irb_session(*args) 60: #OpenWFE.trap_int_irb(*args) if $openwfe_irb 61: OpenWFE.trap_int_irb(*args) 62: end 63: end
This method is used within the InFlowWorkItem and the CsvTable classes.
# File lib/openwfe/utils.rb, line 479 479: def OpenWFE.unset_attribute (container, key) 480: 481: i = key.rindex(".") 482: 483: if not i 484: container.delete key 485: return 486: end 487: 488: container = lookup_attribute container, key[0..i-1] 489: 490: if container.is_a?(Array) 491: 492: container.delete_at key[i+1..-1].to_i 493: else 494: 495: container.delete key[i+1..-1] 496: end 497: end
Turns a hash into its corresponding workitem (InFlowWorkItem, CancelItem, LaunchItem).
# File lib/openwfe/workitem.rb, line 474 474: def OpenWFE.workitem_from_h (h) 475: 476: #wi_class = eval(h[:type]) 477: wi_class = get_class(h) 478: wi_class.from_h(h) 479: end
An alias for OpenWFE::xmldoc_to_string()
# File lib/openwfe/orest/xmlcodec.rb, line 649 649: def OpenWFE.xml_to_s (xml, decl=true) 650: 651: OpenWFE::xmldoc_to_string(xml, decl) 652: end
Just turns some XML to a String (if decl is set to false, no XML declaration will be printed).
# File lib/openwfe/orest/xmlcodec.rb, line 633 633: def OpenWFE.xmldoc_to_string (xml, decl=true) 634: 635: #return xml if xml.is_a?(String) 636: 637: xml << REXML::XMLDecl.new \ 638: if decl and (not xml[0].is_a?(REXML::XMLDecl)) 639: 640: #s = "" 641: #xml.write(s, 0) 642: #return s 643: xml.to_s 644: end
looks up in a container (something that has a [] method) with a key, if nothing has been found and the key is a number, turns the the number into a String a does a last lookup.
# File lib/openwfe/utils.rb, line 541 541: def OpenWFE.flex_lookup (container, key) 542: 543: value = nil 544: 545: begin 546: value = container[key] 547: rescue Exception => e 548: end 549: 550: if value == nil and key.kind_of?(Fixnum) 551: begin 552: value = container[key.to_s] 553: rescue Exception => e 554: end 555: end 556: 557: value 558: end
# File lib/openwfe/utils.rb, line 529 529: def OpenWFE.narrow (key) 530: return 0 if key == "0" 531: i = key.to_i 532: return i if i != 0 533: key 534: end
# File lib/openwfe/utils.rb, line 517 517: def OpenWFE.pop_key (key) 518: i = key.index(".") 519: return narrow(key), nil unless i 520: [ narrow(key[0..i-1]), key[i+1..-1] ] 521: end
# File lib/openwfe/utils.rb, line 523 523: def OpenWFE.pop_last_key (key) 524: i = key.rindex(".") 525: return nil, narrow(key) unless i 526: [ key[0..i-1], narrow(key[i+1..-1]) ] 527: end
# File lib/openwfe/util/irb.rb, line 67 67: def OpenWFE.start_irb_session (*args) 68: 69: IRB::setup nil unless $openwfe_irb 70: 71: ws = IRB::WorkSpace.new *args 72: 73: $openwfe_irb = IRB::Irb.new ws 74: 75: IRB::conf[:MAIN_CONTEXT] = $openwfe_irb.context 76: 77: trap 'INT' do 78: $openwfe_irb.signal_handle 79: end 80: 81: $openwfe_irb.eval_input 82: 83: puts "\nbye!" 84: end
Returns true if this host is currently online (has access to the web / internet).
# File lib/openwfe/utils.rb, line 503 503: def online? 504: 505: require 'open-uri' 506: 507: begin 508: open("http://www.openwfe.org") 509: true 510: rescue SocketError => se 511: false 512: end 513: end
# File lib/openwfe/tools/flowtracer.rb, line 50 50: def trace_flow (process_definition) 51: 52: li = LaunchItem.new process_definition 53: 54: engine = Engine.new 55: 56: i = 0 57: 58: engine.register_participant(".*") do |workitem| 59: 60: puts "-- #{i} ------------------------------------------------------------------------" 61: puts 62: puts " participant '#{workitem.participant_name}' received workitem :" 63: puts 64: puts workitem.to_s 65: puts 66: puts "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" 67: puts 68: puts " expression pool state :" 69: #puts 70: puts engine.get_expression_storage.to_s 71: puts 72: #puts 73: 74: i = i + 1 75: end 76: 77: engine.launch li 78: end