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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33862df282c4b5eae3fa1b4317e7762c299ace6ac8794f138efc86d6225645c0
4
- data.tar.gz: 7f67bb1e73ee9020c5f5bb5f67ff29c2312f3412ae8ae77a3be142c1d12c6a1e
3
+ metadata.gz: 833e8fd13dc9a05339b2b627ae312cdd9e48718263bbd3ebf07996eab83bcdc0
4
+ data.tar.gz: 32bf5785f28bd1807aa636da7efac8fa8e8cd77ccd8eea5fd7ec53cfa8444ade
5
5
  SHA512:
6
- metadata.gz: c4e9586ba65c154da496be6b5635000ab3f6e61624f8733a2b2fec87eecac5b193df176075d4db146d84e09d22e99fcce2090e559fd01ed8847d4399d3808b42
7
- data.tar.gz: f995dbb81528b381e56d8cd74286ae273d8e890a4a2f2f35fca8de736169cce2eddec467148a48d4bd4943a8b8345bed2b2d99285921417a07457dc8adecfe8f
6
+ metadata.gz: 42252aa851d8ce634c7a606e5f7fe4443934109171f645f409110275444791a587c283946fe7e42887b5d4966d2151a77471f2a22feadbc8da3f5026c9a7d29c
7
+ data.tar.gz: e8968a2da91a88bab1ee5c554ca0960716af06a5ecdb79d98b145a08a6fe744494d4dc5e5dc146679e9f0892ba5832db9bbfec6cbddadca58211085998115921
data/README.md CHANGED
@@ -15,14 +15,14 @@ Processes are made of a series of tasks. Tasks can be manual (require `signal` t
15
15
  - BusinessRuleTask (automated): evaluates the decision_id (expects dmn source to be included in the context).
16
16
  - ScriptTask (automated): evaluates the FEEL expression in the script property.
17
17
 
18
- To start the process, initialize SpotFlow with the BPMN and DMN source files, then call `start`.
18
+ To start the process, initialize with the BPMN and DMN source files, then call `start`.
19
19
 
20
20
  ```ruby
21
21
  sources = [
22
22
  File.read("hello_world.bpmn"),
23
23
  File.read("choose_greeting.dmn")
24
24
  ]
25
- execution = SpotFlow.new(sources).start
25
+ execution = BPMN.new(sources).start
26
26
  ```
27
27
 
28
28
  It's often useful to print the process state to the console.
@@ -39,7 +39,7 @@ HelloWorld started * Flow_080794y
39
39
  2 BoundaryEvent EggTimer: waiting
40
40
  ```
41
41
 
42
- The HelloWorld process began at the Start event and is _waiting_ at the IntroduceYourself user task. This is an important concept in the SpotFlow engine. It's designed to be used in a Rails application where a process might be waiting for a user to complete a form, or a background job to complete. It's common to save the state the process until a task is complete. Calling `serialize` on a process will return the execution state so it can be continued later.
42
+ The HelloWorld process began at the Start event and is _waiting_ at the IntroduceYourself user task. This is an important concept in the BPMN engine. It's designed to be used in a Rails application where a process might be waiting for a user to complete a form, or a background job to complete. It's common to save the state the process until a task is complete. Calling `serialize` on a process will return the execution state so it can be continued later.
43
43
 
44
44
  ```ruby
45
45
  # Returns a hash of the process state.
@@ -49,7 +49,7 @@ execution_state = execution.serialize
49
49
  # or a background job completes (ServiceTask)
50
50
 
51
51
  # Restores the process from the execution state.
52
- execution = SpotFlow.restore(sources, execution_state:)
52
+ execution = BPMN.restore(sources, execution_state:)
53
53
 
54
54
  # Now we can continue the process by `signaling` the waiting task.
55
55
  step = execution.step_by_element_id("IntroduceYourself")
@@ -162,13 +162,13 @@ HelloWorld completed *
162
162
  Execute:
163
163
 
164
164
  ```bash
165
- $ bundle add spot_flow
165
+ $ bundle add bpmn
166
166
  ```
167
167
 
168
168
  Or install it directly:
169
169
 
170
170
  ```bash
171
- $ gem install spot_flow
171
+ $ gem install bpmn
172
172
  ```
173
173
 
174
174
  ## Development
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module SpotFlow
3
+ module BPMN
4
4
  class Context
5
5
  attr_reader :sources, :processes, :decisions, :services, :executions
6
6
  attr_reader :bpmn_definitions, :dmn_definitions
@@ -11,15 +11,15 @@ module SpotFlow
11
11
  @bpmn_definitions = []
12
12
  @dmn_definitions = []
13
13
  @decisions = Array.wrap(decisions)
14
- @services = HashWithIndifferentAccess.new((SpotFlow.config.services || {}).merge(services))
14
+ @services = HashWithIndifferentAccess.new((BPMN.config.services || {}).merge(services))
15
15
 
16
16
  @sources.each do |source|
17
17
  if source.include?("http://www.omg.org/spec/DMN/20180521/DC/")
18
- definitions = SpotFeel.definitions_from_xml(source)
18
+ definitions = DMN.definitions_from_xml(source)
19
19
  @dmn_definitions << definitions
20
20
  @decisions += definitions.decisions
21
21
  else
22
- @processes += SpotFlow.processes_from_xml(source)
22
+ @processes += BPMN.processes_from_xml(source)
23
23
  end
24
24
  end
25
25
 
@@ -55,7 +55,7 @@ module SpotFlow
55
55
  end
56
56
 
57
57
  def notify_listener(*args)
58
- SpotFlow.config.listener&.call(args)
58
+ BPMN.config.listener&.call(args)
59
59
  end
60
60
 
61
61
  def default_process
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Definitions
5
+ include ActiveModel::Model
6
+
7
+ attr_accessor :id, :name, :target_namespace, :exporter, :exporter_version, :execution_platform, :execution_platform_version
8
+ attr_reader :messages, :signals, :errors, :processes
9
+
10
+ def self.from_xml(xml)
11
+ XmlHasher.configure do |config|
12
+ config.snakecase = true
13
+ config.ignore_namespaces = true
14
+ config.string_keys = false
15
+ end
16
+ hash = XmlHasher.parse(xml)
17
+ Definitions.new(hash[:definitions].except(:bpmn_diagram)).tap do |definitions|
18
+ definitions.processes.each do |process|
19
+ process.wire_references(definitions)
20
+ end
21
+ end
22
+ end
23
+
24
+ def initialize(attributes={})
25
+ super(attributes.except(:message, :signal, :error, :process))
26
+
27
+ @messages = Array.wrap(attributes[:message]).map { |atts| Message.new(atts) }
28
+ @signals = Array.wrap(attributes[:signal]).map { |atts| Signal.new(atts) }
29
+ @errors = Array.wrap(attributes[:error]).map { |atts| Error.new(atts) }
30
+ @processes = Array.wrap(attributes[:process]).map { |atts| Process.new(atts) }
31
+ end
32
+
33
+ def message_by_id(id)
34
+ messages.find { |message| message.id == id }
35
+ end
36
+
37
+ def signal_by_id(id)
38
+ signals.find { |signal| signal.id == id }
39
+ end
40
+
41
+ def error_by_id(id)
42
+ errors.find { |error| error.id == id }
43
+ end
44
+
45
+ def process_by_id(id)
46
+ processes.find { |process| process.id == id }
47
+ end
48
+
49
+ def inspect
50
+ "#<BPMN::Definitions @id=#{id.inspect} @name=#{name.inspect} @messages=#{messages.inspect} @signals=#{signals.inspect} @errors=#{errors.inspect} @processes=#{processes.inspect}>"
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Element
5
+ include ActiveModel::Model
6
+
7
+ attr_accessor :id, :name, :extension_elements
8
+
9
+ def initialize(attributes = {})
10
+ super(attributes.slice(:id, :name))
11
+
12
+ @extension_elements = ExtensionElements.new(attributes[:extension_elements]) if attributes[:extension_elements].present?
13
+ end
14
+
15
+ def inspect
16
+ "#<#{self.class.name.gsub(/BPMN::/, "")} @id=#{id.inspect} @name=#{name.inspect}>"
17
+ end
18
+ end
19
+
20
+ class Message < Element
21
+ end
22
+
23
+ class Signal < Element
24
+ end
25
+
26
+ class Error < Element
27
+ end
28
+
29
+ class Collaboration < Element
30
+ end
31
+
32
+ class LaneSet < Element
33
+ end
34
+
35
+ class Participant < Element
36
+ attr_accessor :process_ref, :process
37
+
38
+ def initialize(attributes = {})
39
+ super(attributes.except(:process_ref))
40
+ end
41
+ end
42
+ end
data/lib/bpmn/event.rb ADDED
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Event < Step
5
+ attr_accessor :event_definitions
6
+
7
+ def initialize(attributes = {})
8
+ super(attributes.except(:message_event_definition, :signal_event_definition, :error_event_definition, :terminate_event_definition, :timer_event_definition))
9
+
10
+ @event_definitions = []
11
+
12
+ Array.wrap(attributes[:message_event_definition]).each do |med|
13
+ @event_definitions.push MessageEventDefinition.new(med)
14
+ end if attributes[:message_event_definition].present?
15
+
16
+ Array.wrap(attributes[:signal_event_definition]).each do |sed|
17
+ @event_definitions.push SignalEventDefinition.new(sed)
18
+ end if attributes[:signal_event_definition].present?
19
+
20
+ Array.wrap(attributes[:error_event_definition]).each do |eed|
21
+ @event_definitions.push ErrorEventDefinition.new(eed)
22
+ end if attributes[:error_event_definition].present?
23
+
24
+ Array.wrap(attributes[:terminate_event_definition]).each do |ted|
25
+ @event_definitions.push TerminateEventDefinition.new(ted)
26
+ end if attributes[:terminate_event_definition].present?
27
+
28
+ Array.wrap(attributes[:timer_event_definition]).each do |ted|
29
+ @event_definitions.push TimerEventDefinition.new(ted)
30
+ end if attributes[:timer_event_definition].present?
31
+ end
32
+
33
+ def event_definition_ids
34
+ event_definitions.map(&:id)
35
+ end
36
+
37
+ def is_catching?
38
+ false
39
+ end
40
+
41
+ def is_throwing?
42
+ false
43
+ end
44
+
45
+ def is_none?
46
+ event_definitions.empty?
47
+ end
48
+
49
+ def is_conditional?
50
+ conditional_event_definition.present?
51
+ end
52
+
53
+ def is_escalation?
54
+ escalation_event_definition.present?
55
+ end
56
+
57
+ def is_error?
58
+ error_event_definition.present?
59
+ end
60
+
61
+ def is_message?
62
+ !message_event_definitions.empty?
63
+ end
64
+
65
+ def is_signal?
66
+ !signal_event_definitions.empty?
67
+ end
68
+
69
+ def is_terminate?
70
+ terminate_event_definition.present?
71
+ end
72
+
73
+ def is_timer?
74
+ timer_event_definition.present?
75
+ end
76
+
77
+ def conditional_event_definition
78
+ event_definitions.find { |ed| ed.is_a?(ConditionalEventDefinition) }
79
+ end
80
+
81
+ def escalation_event_definition
82
+ event_definitions.find { |ed| ed.is_a?(EscalationEventDefinition) }
83
+ end
84
+
85
+ def error_event_definitions
86
+ event_definitions.select { |ed| ed.is_a?(ErrorEventDefinition) }
87
+ end
88
+
89
+ def error_event_definition
90
+ event_definitions.find { |ed| ed.is_a?(ErrorEventDefinition) }
91
+ end
92
+
93
+ def message_event_definitions
94
+ event_definitions.select { |ed| ed.is_a?(MessageEventDefinition) }
95
+ end
96
+
97
+ def signal_event_definitions
98
+ event_definitions.select { |ed| ed.is_a?(SignalEventDefinition) }
99
+ end
100
+
101
+ def terminate_event_definition
102
+ event_definitions.find { |ed| ed.is_a?(TerminateEventDefinition) }
103
+ end
104
+
105
+ def timer_event_definition
106
+ event_definitions.find { |ed| ed.is_a?(TimerEventDefinition) }
107
+ end
108
+
109
+ def execute(execution)
110
+ event_definitions.each { |event_definition| event_definition.execute(execution) }
111
+ end
112
+ end
113
+
114
+ class StartEvent < Event
115
+
116
+ def is_catching?
117
+ true
118
+ end
119
+
120
+ def execute(execution)
121
+ super
122
+ leave(execution)
123
+ end
124
+ end
125
+
126
+ class IntermediateThrowEvent < Event
127
+
128
+ def is_throwing?
129
+ true
130
+ end
131
+
132
+ def execute(execution)
133
+ super
134
+ leave(execution)
135
+ end
136
+ end
137
+
138
+ class IntermediateCatchEvent < Event
139
+
140
+ def is_catching?
141
+ true
142
+ end
143
+
144
+ def execute(execution)
145
+ super
146
+ execution.wait
147
+ end
148
+
149
+ def signal(execution)
150
+ leave(execution)
151
+ end
152
+ end
153
+
154
+ class BoundaryEvent < Event
155
+ attr_accessor :attached_to_ref, :attached_to, :cancel_activity
156
+
157
+ def initialize(attributes = {})
158
+ super(attributes.except(:attached_to_ref, :cancel_activity))
159
+
160
+ @attached_to_ref = attributes[:attached_to_ref]
161
+ @cancel_activity = true
162
+ if attributes[:cancel_activity].present?
163
+ @cancel_activity = attributes[:cancel_activity] == "false" ? false : true
164
+ end
165
+ end
166
+
167
+ def is_catching?
168
+ true
169
+ end
170
+
171
+ def execute(execution)
172
+ super
173
+ execution.wait
174
+ end
175
+
176
+ def signal(execution)
177
+ execution.attached_to.terminate if cancel_activity
178
+ leave(execution)
179
+ end
180
+ end
181
+
182
+ class EndEvent < Event
183
+
184
+ def is_throwing?
185
+ true
186
+ end
187
+
188
+ def execute(execution)
189
+ super
190
+ execution.end(true)
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class EventDefinition < Element
5
+ def execute(execution)
6
+ end
7
+ end
8
+
9
+ class ConditionalEventDefinition < EventDefinition
10
+ attr_accessor :variable_name, :variable_events, :condition
11
+
12
+ def initialize(attributes = {})
13
+ super(attributes.except(:variable_name, :variable_events, :condition))
14
+
15
+ @variable_name = moddle[:variable_name] # "var1"
16
+ @variable_events = moddle[:variable_events] # "create, update"
17
+ @condition = moddle[:condition] # var1 = 1
18
+ end
19
+ end
20
+
21
+ class EscalationEventDefinition < EventDefinition
22
+ end
23
+
24
+ class ErrorEventDefinition < EventDefinition
25
+ attr_accessor :error_ref, :error
26
+ attr_accessor :error_code_variable, :error_message_variable
27
+
28
+ def initialize(attributes = {})
29
+ super(attributes.except(:error_ref, :error_code_variable, :error_message_variable))
30
+
31
+ @error_ref = attributes[:error_ref]
32
+ @error_code_variable = attributes[:error_code_variable]
33
+ @error_message_variable = attributes[:error_message_variable]
34
+ end
35
+
36
+ def execute(execution)
37
+ if execution.step.is_throwing?
38
+ execution.throw_error(error_name)
39
+ else
40
+ execution.error_names.push error_name
41
+ end
42
+ end
43
+
44
+ def error_id
45
+ error&.id
46
+ end
47
+
48
+ def error_name
49
+ error&.name
50
+ end
51
+ end
52
+
53
+ class MessageEventDefinition < EventDefinition
54
+ attr_accessor :message_ref, :message
55
+
56
+ def initialize(attributes = {})
57
+ super(attributes.except(:message_ref))
58
+
59
+ @message_ref = attributes[:message_ref]
60
+ end
61
+
62
+ def execute(execution)
63
+ if execution.step.is_throwing?
64
+ execution.throw_message(message_name)
65
+ else
66
+ execution.message_names.push message_name
67
+ end
68
+ end
69
+
70
+ def message_id
71
+ message&.id
72
+ end
73
+
74
+ def message_name
75
+ message&.name
76
+ end
77
+ end
78
+
79
+ class SignalEventDefinition < EventDefinition
80
+ attr_accessor :signal_ref, :signal
81
+
82
+ def initialize(attributes = {})
83
+ super(attributes.except(:signal_ref))
84
+
85
+ @signal_ref = moddle[:signal_ref]
86
+ end
87
+
88
+ def signal_id
89
+ signal&.id
90
+ end
91
+
92
+ def signal_name
93
+ signal&.name
94
+ end
95
+ end
96
+
97
+ class TerminateEventDefinition < EventDefinition
98
+
99
+ def execute(execution)
100
+ execution.parent&.terminate
101
+ end
102
+ end
103
+
104
+ class TimerEventDefinition < EventDefinition
105
+ attr_accessor :time_date, :time_duration_type, :time_duration, :time_cycle
106
+
107
+ def initialize(attributes = {})
108
+ super(attributes.except(:time_date, :time_duration, :time_cycle))
109
+
110
+ @time_duration_type = attributes[:time_duration_type]
111
+ @time_duration = attributes[:time_duration]
112
+ end
113
+
114
+ def execute(execution)
115
+ if execution.step.is_catching?
116
+ execution.timer_expires_at = time_due
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ def time_due
123
+ # Return the next time the timer is due
124
+ if time_date
125
+ return Date.parse(time_date)
126
+ elsif time_duration
127
+ return Time.zone.now + ActiveSupport::Duration.parse(time_duration)
128
+ else
129
+ return Time.zone.now # time_cycle not yet implemented
130
+ end
131
+ end
132
+ end
133
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module SpotFlow
3
+ module BPMN
4
4
  class Execution
5
5
  attr_accessor :id, :status, :started_at, :ended_at, :variables, :tokens_in, :tokens_out, :start_event_id, :timer_expires_at, :message_names, :error_names, :condition
6
6
  attr_accessor :step, :parent, :children, :context, :attached_to_id
@@ -29,7 +29,7 @@ module SpotFlow
29
29
  step = step_type == "Process" ? context.process_by_id(step_id) : context.element_by_id(step_id)
30
30
  child_attributes = attributes.delete("children")
31
31
  Execution.new(attributes.merge(step: step, context:)).tap do |execution|
32
- execution.children = child_attributes.map do |ca|
32
+ execution.children = child_attributes.map do |ca|
33
33
  Execution.from_json(ca, context:).tap { |child| child.parent = execution }
34
34
  end if child_attributes
35
35
  end
@@ -97,7 +97,7 @@ module SpotFlow
97
97
  @started_at = Time.zone.now
98
98
  map_input_variables if step&.input_mappings&.present?
99
99
  context.notify_listener(:execution_started, execution: self)
100
- step.attachments.each { |attachment| parent.execute_step(attachment, attached_to: self) } if step.is_a?(SpotFlow::Bpmn::Activity)
100
+ step.attachments.each { |attachment| parent.execute_step(attachment, attached_to: self) } if step.is_a?(BPMN::Activity)
101
101
  continue
102
102
  end
103
103
 
@@ -147,7 +147,7 @@ module SpotFlow
147
147
  def throw_message(message_name, variables: {})
148
148
  waiting_children.each do |child|
149
149
  step = child.step
150
- if step.is_a?(SpotFlow::Bpmn::Event) && step.message_event_definitions.any? { |message_event_definition| message_event_definition.message_name == message_name }
150
+ if step.is_a?(BPMN::Event) && step.message_event_definitions.any? { |message_event_definition| message_event_definition.message_name == message_name }
151
151
  child.signal(variables)
152
152
  break
153
153
  end
@@ -158,7 +158,7 @@ module SpotFlow
158
158
  def throw_error(error_name, variables: {})
159
159
  waiting_children.each do |child|
160
160
  step = child.step
161
- if step.is_a?(SpotFlow::Bpmn::Event) && step.error_event_definitions.any? { |error_event_definition| error_event_definition.error_name == error_name }
161
+ if step.is_a?(BPMN::Event) && step.error_event_definitions.any? { |error_event_definition| error_event_definition.error_name == error_name }
162
162
  child.signal(variables)
163
163
  break
164
164
  end
@@ -175,7 +175,7 @@ module SpotFlow
175
175
  end
176
176
 
177
177
  def evaluate_expression(expression, variables: parent&.variables || {}.with_indifferent_access)
178
- SpotFeel.evaluate(expression.delete_prefix("="), variables:)
178
+ DMN.evaluate(expression.delete_prefix("="), variables:)
179
179
  end
180
180
 
181
181
  def run_automated_tasks
@@ -202,7 +202,7 @@ module SpotFlow
202
202
  # Called by the child step executors when they have ended
203
203
  #
204
204
  def has_ended(_child)
205
- step.leave(self) if step.is_a?(SpotFlow::Bpmn::SubProcess) || step.is_a?(SpotFlow::Bpmn::CallActivity)
205
+ step.leave(self) if step.is_a?(BPMN::SubProcess) || step.is_a?(BPMN::CallActivity)
206
206
  self.end(true)
207
207
  end
208
208
 
@@ -219,7 +219,7 @@ module SpotFlow
219
219
  end
220
220
 
221
221
  def waiting_tasks
222
- waiting_children.select { |child| child.step.is_a?(SpotFlow::Bpmn::Task) }
222
+ waiting_children.select { |child| child.step.is_a?(BPMN::Task) }
223
223
  end
224
224
 
225
225
  def waiting_automated_tasks
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class ExtensionElements
5
+ VALID_EXTENSION_NAMESPACES = %w[zeebe]
6
+
7
+ attr_accessor :assignment_definition, :called_element, :called_decision, :form_definition, :io_mapping, :properties, :script, :subscription, :task_definition, :task_headers, :task_schedule
8
+
9
+ def initialize(attributes = {})
10
+ if attributes[:properties].present?
11
+ @properties = HashWithIndifferentAccess.new
12
+ Array.wrap(attributes[:properties][:property]).each { |property_moddle| @properties[property_moddle[:name]] = property_moddle[:value] }
13
+ end
14
+
15
+ @assignment_definition = Zeebe::AssignmentDefinition.new(attributes[:assignment_definition]) if attributes[:assignment_definition].present?
16
+ @called_element = Zeebe::CalledElement.new(attributes[:called_element]) if attributes[:called_element].present?
17
+ @called_decision = Zeebe::CalledDecision.new(attributes[:called_decision]) if attributes[:called_decision].present?
18
+ @form_definition = Zeebe::FormDefinition.new(attributes[:form_definition]) if attributes[:form_definition].present?
19
+ @io_mapping = Zeebe::IoMapping.new(attributes[:io_mapping]) if attributes[:io_mapping].present?
20
+ @script = Zeebe::Script.new(attributes[:script]) if attributes[:script].present?
21
+ @subscription = Zeebe::Subscription.new(attributes[:subscription]) if attributes[:subscription].present?
22
+ @task_definition = Zeebe::TaskDefinition.new(attributes[:task_definition]) if attributes[:task_definition].present?
23
+ @task_headers = Zeebe::TaskHeaders.new(attributes[:task_headers]) if attributes[:task_headers].present?
24
+ @task_schedule = Zeebe::TaskSchedule.new(attributes[:task_schedule]) if attributes[:task_schedule].present?
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BPMN
4
+ class Extension
5
+ include ActiveModel::Model
6
+ end
7
+ end
8
+
9
+ module Zeebe
10
+ class AssignmentDefinition < BPMN::Extension
11
+ attr_accessor :assignee, :candidate_groups, :candidate_users
12
+ end
13
+
14
+ class CalledElement < BPMN::Extension
15
+ attr_accessor :process_id, :propagate_all_child_variables, :propagate_all_parent_variables
16
+
17
+ def initialize(attributes = {})
18
+ super(attributes.except(:propagate_all_child_variables))
19
+
20
+ @propagate_all_parent_variables = true
21
+ @propagate_all_parent_variables = attributes[:propagate_all_parent_variables] == "true" if attributes[:propagate_all_parent_variables].present?
22
+ @propagate_all_child_variables = attributes[:propagate_all_child_variables] == "true"
23
+ end
24
+ end
25
+
26
+ class CalledDecision < BPMN::Extension
27
+ attr_accessor :decision_id, :result_variable
28
+ end
29
+
30
+ class FormDefinition < BPMN::Extension
31
+ attr_accessor :form_key
32
+ end
33
+
34
+ class IoMapping < BPMN::Extension
35
+ attr_reader :inputs, :outputs
36
+
37
+ def initialize(attributes = {})
38
+ super(attributes.except(:input, :output))
39
+
40
+ @inputs = Array.wrap(attributes[:input]).map { |atts| Parameter.new(atts) } if attributes[:input].present?
41
+ @outputs = Array.wrap(attributes[:output]).map { |atts| Parameter.new(atts) } if attributes[:output].present?
42
+ end
43
+ end
44
+
45
+ class Parameter < BPMN::Extension
46
+ attr_accessor :source, :target
47
+ end
48
+
49
+ class Script < BPMN::Extension
50
+ attr_accessor :expression, :result_variable
51
+ end
52
+
53
+ class Subscription < BPMN::Extension
54
+ attr_accessor :correlation_key
55
+ end
56
+
57
+ class TaskDefinition < BPMN::Extension
58
+ attr_accessor :type, :retries
59
+ end
60
+
61
+ class TaskHeaders < BPMN::Extension
62
+ attr_accessor :headers
63
+
64
+ def initialize(attributes = {})
65
+ super(attributes.except(:header))
66
+
67
+ @headers = HashWithIndifferentAccess.new
68
+ Array.wrap(attributes[:header]).each { |header| @headers[header[:key]] = header[:value] }
69
+ end
70
+ end
71
+
72
+ class TaskSchedule < BPMN::Extension
73
+ attr_accessor :due_date, :follow_up_date
74
+ end
75
+ end