bpmn 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/bpmn/flow.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Flow < Element
5
+ attr_accessor :source_ref, :target_ref
6
+ attr_accessor :source, :target
7
+
8
+ def initialize(attributes = {})
9
+ super(attributes.except(:source_ref, :target_ref))
10
+
11
+ @source_ref = attributes[:source_ref]
12
+ @target_ref = attributes[:target_ref]
13
+ @source = nil
14
+ @target = nil
15
+ end
16
+
17
+ def inspect
18
+ parts = ["#<#{self.class.name.gsub(/BPMN::/, "")} @id=#{id.inspect}"]
19
+ parts << "@source_ref=#{source_ref.inspect}" if source_ref
20
+ parts << "@target_ref=#{target_ref.inspect}" if target_ref
21
+ parts.join(" ") + ">"
22
+ end
23
+ end
24
+
25
+ class Association < Flow
26
+ end
27
+
28
+ class SequenceFlow < Flow
29
+ attr_accessor :condition
30
+
31
+ def initialize(attributes = {})
32
+ super(attributes.except(:condition))
33
+
34
+ @condition = attributes[:condition_expression]
35
+ end
36
+
37
+ def evaluate(execution)
38
+ return true unless condition
39
+ execution.evaluate_condition(condition)
40
+ end
41
+ end
42
+
43
+ class TextAnnotation < Flow
44
+ end
45
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Gateway < Step
5
+
6
+ def execute(execution)
7
+ if converging?
8
+ if is_enabled?(execution)
9
+ return leave(execution)
10
+ else
11
+ execution.wait
12
+ end
13
+ else
14
+ return leave(execution)
15
+ end
16
+ end
17
+
18
+ #
19
+ # Algorithm from https://researcher.watson.ibm.com/researcher/files/zurich-hvo/bpm2010-1.pdf
20
+ #
21
+ def is_enabled?(execution)
22
+ filled = []
23
+ empty = []
24
+
25
+ incoming.each { |flow| execution.tokens_in.include?(flow.id) ? filled.push(flow) : empty.push(flow) }
26
+
27
+ # Filled slots don't need to be searched for tokens
28
+ index = 0
29
+ while (index < filled.length)
30
+ current_flow = filled[index]
31
+ current_flow.source.incoming.each do |incoming_flow|
32
+ filled.push(incoming_flow) unless filled.include?(incoming_flow) || incoming_flow.target == self
33
+ end
34
+ index = index + 1
35
+ end
36
+
37
+ # Empty slots need to be searched for tokens
38
+ index = 0
39
+ while (index < empty.length)
40
+ current_flow = empty[index]
41
+ current_flow.source.incoming.each do |incoming_flow|
42
+ empty.push(incoming_flow) unless filled.include?(incoming_flow) || empty.include?(incoming_flow) || incoming_flow.target == self
43
+ end
44
+ index = index + 1
45
+ end
46
+
47
+ empty_ids = empty.map { |g| g.id }
48
+
49
+ # If there are empty slots with tokens we need to wait
50
+ return false if (empty_ids & execution.parent.tokens).length > 0
51
+ return true
52
+ end
53
+ end
54
+
55
+ class ExclusiveGateway < Gateway
56
+ # RULE: Only one flow is taken
57
+ def outgoing_flows(step_execution)
58
+ flows = super
59
+ return [flows.first]
60
+ end
61
+ end
62
+
63
+ class ParallelGateway < Gateway
64
+ # RULE: All flows are taken
65
+ end
66
+
67
+ class InclusiveGateway < Gateway
68
+ # RULE: All valid flows are taken
69
+ # NOTE: Camunda 8 only support diverging but not converging inclusive gateways
70
+ end
71
+
72
+ class EventBasedGateway < Gateway
73
+ #
74
+ # RULE: when an event created from an event gateway is caught,
75
+ # all other waiting events must be canceled.
76
+ #
77
+ def cancel_waiting_events(execution)
78
+ execution.targets.each do |target_execution|
79
+ target_execution.terminate unless target_execution.ended?
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Process < Step
5
+ attr_accessor :is_executable
6
+
7
+ attr_accessor :start_events, :end_events, :intermediate_catch_events, :intermediate_throw_events, :boundary_events
8
+ attr_accessor :tasks, :user_tasks, :service_tasks, :script_tasks, :send_tasks, :receive_tasks, :manual_tasks, :business_rule_tasks, :call_activities
9
+ attr_accessor :sub_processes, :ad_hoc_sub_processes
10
+ attr_accessor :sequence_flows, :message_flows, :associations, :data_associations, :data_inputs, :data_outputs
11
+ attr_accessor :data_objects, :data_stores, :data_stores_references
12
+ attr_accessor :gateways, :exclusive_gateways, :parallel_gateways, :inclusive_gateways, :event_based_gateways, :complex_gateways
13
+
14
+ attr_accessor :parent
15
+
16
+ def initialize(attributes = {})
17
+ super(attributes.slice(:id, :name, :extension_elements, :incoming, :outgoing, :default))
18
+
19
+ @is_executable = attributes[:is_executable] == ("true" || true)
20
+
21
+ @start_events = Array.wrap(attributes[:start_event]).map { |se| StartEvent.new(se) }
22
+ @end_events = Array.wrap(attributes[:end_event]).map { |ee| EndEvent.new(ee) }
23
+ @intermediate_catch_events = Array.wrap(attributes[:intermediate_catch_event]).map { |ice| IntermediateCatchEvent.new(ice) }
24
+ @intermediate_throw_events = Array.wrap(attributes[:intermediate_throw_event]).map { |ite| IntermediateThrowEvent.new(ite) }
25
+ @boundary_events = Array.wrap(attributes[:boundary_event]).map { |be| BoundaryEvent.new(be) }
26
+ @tasks = Array.wrap(attributes[:task]).map { |t| Task.new(t) }
27
+ @user_tasks = Array.wrap(attributes[:user_task]).map { |ut| UserTask.new(ut) }
28
+ @service_tasks = Array.wrap(attributes[:service_task]).map { |st| ServiceTask.new(st) }
29
+ @script_tasks = Array.wrap(attributes[:script_task]).map { |st| ScriptTask.new(st) }
30
+ @business_rule_tasks = Array.wrap(attributes[:business_rule_task]).map { |brt| BusinessRuleTask.new(brt) }
31
+ @call_activities = Array.wrap(attributes[:call_activity]).map { |ca| CallActivity.new(ca) }
32
+ @sub_processes = Array.wrap(attributes[:sub_process]).map { |sp| SubProcess.new(sp) }
33
+ @ad_hoc_sub_processes = Array.wrap(attributes[:ad_hoc_sub_processe]).map { |ahsp| AdHocSubProcess.new(ahsp) }
34
+ @exclusive_gateways = Array.wrap(attributes[:exclusive_gateway]).map { |eg| ExclusiveGateway.new(eg) }
35
+ @parallel_gateways = Array.wrap(attributes[:parallel_gateway]).map { |pg| ParallelGateway.new(pg) }
36
+ @inclusive_gateways = Array.wrap(attributes[:inclusive_gateway]).map { |ig| InclusiveGateway.new(ig) }
37
+ @event_based_gateways = Array.wrap(attributes[:event_based_gateway]).map { |ebg| EventBasedGateway.new(ebg) }
38
+ @sequence_flows = Array.wrap(attributes[:sequence_flow]).map { |sf| SequenceFlow.new(sf) }
39
+ end
40
+
41
+ def elements
42
+ @elements ||= {}.tap do |elements|
43
+ elements.merge!(start_events.index_by(&:id))
44
+ elements.merge!(end_events.index_by(&:id))
45
+ elements.merge!(intermediate_catch_events.index_by(&:id))
46
+ elements.merge!(intermediate_throw_events.index_by(&:id))
47
+ elements.merge!(boundary_events.index_by(&:id))
48
+ elements.merge!(tasks.index_by(&:id))
49
+ elements.merge!(user_tasks.index_by(&:id))
50
+ elements.merge!(service_tasks.index_by(&:id))
51
+ elements.merge!(script_tasks.index_by(&:id))
52
+ elements.merge!(business_rule_tasks.index_by(&:id))
53
+ elements.merge!(call_activities.index_by(&:id))
54
+ elements.merge!(sub_processes.index_by(&:id))
55
+ elements.merge!(ad_hoc_sub_processes.index_by(&:id))
56
+ elements.merge!(exclusive_gateways.index_by(&:id))
57
+ elements.merge!(parallel_gateways.index_by(&:id))
58
+ elements.merge!(inclusive_gateways.index_by(&:id))
59
+ elements.merge!(event_based_gateways.index_by(&:id))
60
+ elements.merge!(sequence_flows.index_by(&:id))
61
+ end
62
+ end
63
+
64
+ def wire_references(definitions)
65
+ elements.values.each do |element|
66
+ if element.is_a?(Step)
67
+ element.incoming = element.incoming.map { |id| element_by_id(id) }
68
+ element.outgoing = element.outgoing.map { |id| element_by_id(id) }
69
+
70
+ if element.is_a?(Event)
71
+
72
+ element.event_definitions.each do |event_definition|
73
+ if event_definition.is_a?(MessageEventDefinition)
74
+ event_definition.message = definitions.message_by_id(event_definition.message_ref)
75
+ elsif event_definition.is_a?(SignalEventDefinition)
76
+ event_definition.signal = definitions.signal_by_id(event_definition.signal_ref)
77
+ elsif event_definition.is_a?(ErrorEventDefinition)
78
+ event_definition.error = definitions.error_by_id(event_definition.error_ref)
79
+ end
80
+ end
81
+
82
+ if element.is_a?(BoundaryEvent)
83
+ host_element = element_by_id(element.attached_to_ref)
84
+ host_element.attachments << element
85
+ element.attached_to = host_element
86
+ end
87
+
88
+ end
89
+
90
+ if element.is_a?(Gateway)
91
+ element.default = element_by_id(element.default_ref)
92
+ end
93
+
94
+ if element.is_a?(SubProcess)
95
+ element.wire_references(definitions)
96
+ end
97
+
98
+ elsif element.is_a?(SequenceFlow)
99
+ element.source = element_by_id(element.source_ref)
100
+ element.target = element_by_id(element.target_ref)
101
+ end
102
+
103
+ # Not handled participant process ref
104
+ end
105
+ end
106
+
107
+ def element_by_id(id)
108
+ elements[id]
109
+ end
110
+
111
+ def elements_by_type(type)
112
+ elements.select { |e| e.class == type }
113
+ end
114
+
115
+ def default_start_event
116
+ start_events.find { |se| se.event_definitions.empty? }
117
+ end
118
+
119
+ def execute(execution)
120
+ start_event = execution.start_event_id ? element_by_id(execution.start_event_id) : default_start_event
121
+ raise ExecutionErrorNew.new("Process must have at least one start event.") if start_event.blank?
122
+ execution.execute_step(start_event)
123
+ end
124
+
125
+ def inspect
126
+ parts = ["#<#{self.class.name.gsub(/BPMN::/, "")} @id=#{id.inspect} @name=#{name.inspect} @is_executable=#{is_executable.inspect}"]
127
+ parts << "@parent=#{parent.inspect}" if parent
128
+ event_attrs = (start_events + intermediate_catch_events + intermediate_throw_events + boundary_events + end_events).compact
129
+ parts << "@events=#{event_attrs.inspect}" unless event_attrs.blank?
130
+ activity_attrs = (tasks + user_tasks + service_tasks + script_tasks + business_rule_tasks + call_activities).compact
131
+ parts << "@activities=#{activity_attrs.inspect}" unless activity_attrs.blank?
132
+ gateway_attrs = (exclusive_gateways + parallel_gateways + inclusive_gateways + event_based_gateways).compact
133
+ parts << "@gateways=#{gateway_attrs.inspect}" unless gateway_attrs.blank?
134
+ sub_process_attrs = (sub_processes + ad_hoc_sub_processes).compact
135
+ parts << "@sub_processes=#{sub_process_attrs.inspect}" unless sub_process_attrs.blank?
136
+ parts << "@sequence_flows=#{sequence_flows.inspect}" unless sequence_flows.blank?
137
+ parts.join(" ") + ">"
138
+ end
139
+ end
140
+
141
+ class SubProcess < Process
142
+ attr_accessor :triggered_by_event
143
+
144
+ def initialize(attributes = {})
145
+ super(attributes.except(:triggered_by_event))
146
+
147
+ @is_executable = false
148
+ @sub_processes = []
149
+ @triggered_by_event = attributes[:triggered_by_event]
150
+ end
151
+
152
+ def execution_ended(execution)
153
+ leave(execution)
154
+ end
155
+ end
156
+
157
+ class AdHocSubProcess < SubProcess
158
+
159
+ end
160
+
161
+ class CallActivity < Activity
162
+ attr_reader :process_id
163
+
164
+ def execute(execution)
165
+ if extension_elements&.called_element&.process_id&.start_with?("=")
166
+ @process_id = DMN.evaluate(extension_elements&.called_element&.process_id, variables: execution.variables)
167
+ else
168
+ @process_id = extension_elements&.called_element&.process_id
169
+ end
170
+
171
+ execution.wait
172
+
173
+ process = execution.context.process_by_id(@process_id) if @process_id
174
+ execution.execute_step(process.default_start_event) if process
175
+ end
176
+ end
177
+ end
data/lib/bpmn/step.rb ADDED
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Step < Element
5
+ attr_accessor :incoming, :outgoing, :default, :default_ref
6
+
7
+ def initialize(attributes = {})
8
+ super(attributes.except(:incoming, :outgoing, :default))
9
+
10
+ @incoming = Array.wrap(attributes[:incoming]) || []
11
+ @outgoing = Array.wrap(attributes[:outgoing]) || []
12
+ @default_ref = attributes[:default]
13
+ end
14
+
15
+ def diverging?
16
+ outgoing.length > 1
17
+ end
18
+
19
+ def converging?
20
+ incoming.length > 1
21
+ end
22
+
23
+ def leave(execution)
24
+ execution.end(false)
25
+ execution.take_all(outgoing_flows(execution))
26
+ end
27
+
28
+ def outgoing_flows(execution)
29
+ flows = []
30
+ outgoing.each do |flow|
31
+ result = flow.evaluate(execution) unless default&.id == flow.id
32
+ flows.push flow if result
33
+ end
34
+ flows = [default] if flows.empty? && default
35
+ return flows
36
+ end
37
+
38
+ def input_mappings
39
+ extension_elements&.io_mapping&.inputs || []
40
+ end
41
+
42
+ def output_mappings
43
+ extension_elements&.io_mapping&.outputs || []
44
+ end
45
+ end
46
+
47
+ class Activity < Step
48
+ attr_accessor :attachments
49
+
50
+ def initialize(attributes = {})
51
+ super(attributes.except(:attachments))
52
+
53
+ @attachments = []
54
+ end
55
+ end
56
+ end
data/lib/bpmn/task.rb ADDED
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Task < Activity
5
+
6
+ def is_automated?
7
+ false
8
+ end
9
+
10
+ def is_manual?
11
+ true
12
+ end
13
+
14
+ def execute(execution)
15
+ execution.wait
16
+ end
17
+
18
+ def signal(execution)
19
+ leave(execution)
20
+ end
21
+
22
+ def result_to_variables(result)
23
+ if result_variable
24
+ return { "#{result_variable}": result }
25
+ else
26
+ if result.is_a? Hash
27
+ result
28
+ else
29
+ {}.tap { |h| h[id.underscore] = result }
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ class UserTask < Task
36
+
37
+ def form_key
38
+ extension_elements&.form_definition&.form_key
39
+ end
40
+
41
+ def assignee
42
+ extension_elements&.assignment_definition&.assignee
43
+ end
44
+
45
+ def candidate_groups
46
+ extension_elements&.assignment_definition&.candidate_groups
47
+ end
48
+
49
+ def candidate_users
50
+ extension_elements&.assignment_definition&.candidate_users
51
+ end
52
+
53
+ def due_date
54
+ extension_elements&.task_schedule&.due_date
55
+ end
56
+
57
+ def follow_up_date
58
+ extension_elements&.task_schedule&.follow_up_date
59
+ end
60
+ end
61
+
62
+ class ServiceTask < Task
63
+ attr_accessor :service
64
+
65
+ def is_automated?
66
+ true
67
+ end
68
+
69
+ def is_manual?
70
+ false
71
+ end
72
+
73
+ def execute(execution)
74
+ execution.wait
75
+ end
76
+
77
+ def task_type
78
+ extension_elements&.task_definition&.type
79
+ end
80
+
81
+ def task_retries
82
+ extension_elements&.task_definition&.retries
83
+ end
84
+
85
+ def headers
86
+ extension_elements&.task_headers&.headers
87
+ end
88
+
89
+ def run(execution)
90
+ if defined?(task_type)
91
+ klass = task_type.constantize
92
+ klass.new.call(execution.parent.variables, headers || {})
93
+ end
94
+ end
95
+ end
96
+
97
+ class ScriptTask < ServiceTask
98
+
99
+ def script
100
+ extension_elements&.script&.expression
101
+ end
102
+
103
+ def result_variable
104
+ extension_elements&.script&.result_variable
105
+ end
106
+
107
+ def run(execution)
108
+ DMN.evaluate(script.delete_prefix("="), variables: execution.parent.variables)
109
+ end
110
+ end
111
+
112
+ class BusinessRuleTask < ServiceTask
113
+
114
+ def decision_id
115
+ extension_elements&.called_decision&.decision_id
116
+ end
117
+
118
+ def result_variable
119
+ extension_elements&.called_decision&.result_variable
120
+ end
121
+
122
+ def run(execution)
123
+ DMN.decide(decision_id, definitions: execution.context.dmn_definitions_by_decision_id(decision_id), variables: execution.parent.variables)
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ VERSION = "0.0.3"
5
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spot_flow/version"
3
+ require "bpmn/version"
4
4
 
5
5
  require "active_support"
6
6
  require "active_support/time"
@@ -9,13 +9,24 @@ require "active_support/core_ext/object/json"
9
9
  require "active_support/configurable"
10
10
  require "active_model"
11
11
 
12
- require "spot_feel"
12
+ require "dmn"
13
13
 
14
- require "spot_flow/bpmn"
15
- require "spot_flow/context"
16
- require "spot_flow/execution"
14
+ require "bpmn/element"
15
+ require "bpmn/extensions"
16
+ require "bpmn/extension_elements"
17
+ require "bpmn/step"
18
+ require "bpmn/flow"
19
+ require "bpmn/event_definition"
20
+ require "bpmn/event"
21
+ require "bpmn/gateway"
22
+ require "bpmn/task"
23
+ require "bpmn/process"
24
+ require "bpmn/definitions"
17
25
 
18
- module SpotFlow
26
+ require "bpmn/context"
27
+ require "bpmn/execution"
28
+
29
+ module BPMN
19
30
  include ActiveSupport::Configurable
20
31
 
21
32
  #
@@ -36,14 +47,14 @@ module SpotFlow
36
47
  # Extract processes from a BMPN XML file.
37
48
  #
38
49
  def self.processes_from_xml(xml)
39
- Bpmn::Definitions.from_xml(xml)&.processes || []
50
+ Definitions.from_xml(xml)&.processes || []
40
51
  end
41
52
 
42
53
  #
43
54
  # Extract decisions from a DMN XML file.
44
55
  #
45
56
  def self.decisions_from_xml(xml)
46
- definitions = SpotFeel.definitions_from_xml(xml)
57
+ definitions = DMN.definitions_from_xml(xml)
47
58
  definitions.decisions
48
59
  end
49
60
  end
metadata CHANGED
@@ -1,15 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bpmn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Connected Bits
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-30 00:00:00.000000000 Z
10
+ date: 2025-03-03 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: dmn
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 0.0.3
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 0.0.3
13
26
  - !ruby/object:Gem::Dependency
14
27
  name: activemodel
15
28
  requirement: !ruby/object:Gem::Requirement
@@ -189,29 +202,27 @@ files:
189
202
  - MIT-LICENSE
190
203
  - README.md
191
204
  - Rakefile
192
- - lib/spot_flow.rb
193
- - lib/spot_flow/bpmn.rb
194
- - lib/spot_flow/bpmn/definitions.rb
195
- - lib/spot_flow/bpmn/element.rb
196
- - lib/spot_flow/bpmn/event.rb
197
- - lib/spot_flow/bpmn/event_definition.rb
198
- - lib/spot_flow/bpmn/extension_elements.rb
199
- - lib/spot_flow/bpmn/extensions.rb
200
- - lib/spot_flow/bpmn/flow.rb
201
- - lib/spot_flow/bpmn/gateway.rb
202
- - lib/spot_flow/bpmn/process.rb
203
- - lib/spot_flow/bpmn/step.rb
204
- - lib/spot_flow/bpmn/task.rb
205
- - lib/spot_flow/context.rb
206
- - lib/spot_flow/execution.rb
207
- - lib/spot_flow/version.rb
205
+ - lib/bpmn.rb
206
+ - lib/bpmn/context.rb
207
+ - lib/bpmn/definitions.rb
208
+ - lib/bpmn/element.rb
209
+ - lib/bpmn/event.rb
210
+ - lib/bpmn/event_definition.rb
211
+ - lib/bpmn/execution.rb
212
+ - lib/bpmn/extension_elements.rb
213
+ - lib/bpmn/extensions.rb
214
+ - lib/bpmn/flow.rb
215
+ - lib/bpmn/gateway.rb
216
+ - lib/bpmn/process.rb
217
+ - lib/bpmn/step.rb
218
+ - lib/bpmn/task.rb
219
+ - lib/bpmn/version.rb
208
220
  homepage: https://www.connectedbits.com
209
221
  licenses:
210
222
  - MIT
211
223
  metadata:
212
224
  homepage_uri: https://www.connectedbits.com
213
225
  source_code_uri: https://github.com/connectedbits/process_pilot
214
- post_install_message:
215
226
  rdoc_options: []
216
227
  require_paths:
217
228
  - lib
@@ -226,8 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
237
  - !ruby/object:Gem::Version
227
238
  version: '0'
228
239
  requirements: []
229
- rubygems_version: 3.3.21
230
- signing_key:
240
+ rubygems_version: 3.6.5
231
241
  specification_version: 4
232
242
  summary: A BPMN workflow engine in Ruby
233
243
  test_files: []
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SpotFlow
4
- module Bpmn
5
- class Definitions
6
- include ActiveModel::Model
7
-
8
- attr_accessor :id, :name, :target_namespace, :exporter, :exporter_version, :execution_platform, :execution_platform_version
9
- attr_reader :messages, :signals, :errors, :processes
10
-
11
- def self.from_xml(xml)
12
- XmlHasher.configure do |config|
13
- config.snakecase = true
14
- config.ignore_namespaces = true
15
- config.string_keys = false
16
- end
17
- hash = XmlHasher.parse(xml)
18
- Definitions.new(hash[:definitions].except(:bpmn_diagram)).tap do |definitions|
19
- definitions.processes.each do |process|
20
- process.wire_references(definitions)
21
- end
22
- end
23
- end
24
-
25
- def initialize(attributes={})
26
- super(attributes.except(:message, :signal, :error, :process))
27
-
28
- @messages = Array.wrap(attributes[:message]).map { |atts| Message.new(atts) }
29
- @signals = Array.wrap(attributes[:signal]).map { |atts| Signal.new(atts) }
30
- @errors = Array.wrap(attributes[:error]).map { |atts| Error.new(atts) }
31
- @processes = Array.wrap(attributes[:process]).map { |atts| Process.new(atts) }
32
- end
33
-
34
- def message_by_id(id)
35
- messages.find { |message| message.id == id }
36
- end
37
-
38
- def signal_by_id(id)
39
- signals.find { |signal| signal.id == id }
40
- end
41
-
42
- def error_by_id(id)
43
- errors.find { |error| error.id == id }
44
- end
45
-
46
- def process_by_id(id)
47
- processes.find { |process| process.id == id }
48
- end
49
-
50
- def inspect
51
- "#<Bpmn::Definitions @id=#{id.inspect} @name=#{name.inspect} @messages=#{messages.inspect} @signals=#{signals.inspect} @errors=#{errors.inspect} @processes=#{processes.inspect}>"
52
- end
53
- end
54
- end
55
- end