cpee 1.3.137 → 1.3.138

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3d48178530a9f9c1885a88d46053086ae0cf9eed
4
+ data.tar.gz: 75e0da4973eb3d5b7db31e52859e5df70850c813
5
+ SHA512:
6
+ metadata.gz: 620e2cd33e1179c9affa8830f0854d74d796e170df7612361156a3d62d1900e79b3e14ab3cec58146581482d4a0e5c3015223a3d3d868dd1969aaa65f89f21a5
7
+ data.tar.gz: 61a3fed144b5e8d248d9296491d44aa317673ece5a2c2db43e1738cb0bbde67ee45570880e26c2bd91200424a5379492b04991f625d54acf0961fbbf84f5b9b1
data/cpee.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee"
3
- s.version = "1.3.137"
3
+ s.version = "1.3.138"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.license = "LGPL-3"
6
6
  s.summary = "Preliminary release of cloud process execution engine (cpee). If you just need workflow execution, without a rest/xmpp service exposing it, then use WEEL"
@@ -199,15 +199,15 @@ module CPEE
199
199
  end
200
200
  else
201
201
  loops = traces.loops
202
- if node.type == :exclusiveGateway || traces.length == 1
202
+ if node.type == :exclusiveGateway || traces.all_loops?
203
203
  ### as the first is a decision node, just remove and continue
204
204
  if node.incoming == 2
205
205
  node.incoming = 1
206
206
  branch << Loop.new(node.id)
207
207
  ### remove the gateway itself, as for a single loop it is no longer used.
208
208
  ### the condition will the loop condition
209
- if traces.length == 1
210
- loops.first.pop
209
+ if traces.all_loops?
210
+ loops.pop_all
211
211
  else
212
212
  traces.shift_all
213
213
  end
File without changes
@@ -286,6 +286,9 @@ module CPEE
286
286
  def shift_all
287
287
  self.each{ |tr| tr.shift }
288
288
  end
289
+ def pop_all
290
+ self.each{ |tr| tr.pop }
291
+ end
289
292
 
290
293
  def finished?
291
294
  self.reduce(0){|sum,t| sum += t.length} == 0
@@ -300,12 +303,19 @@ module CPEE
300
303
  self.each{|n| num += 1 if n.include?(e)}
301
304
  num == self.length
302
305
  end
306
+ def same_position_in_all?(e,i)
307
+ num = 0
308
+ self.each{|n| num += 1 if n[i] == e}
309
+ num == self.length
310
+ end
303
311
 
304
- def infinite_loop_fix
305
- self << self.first.dup
306
- self.last.pop
312
+ def all_loops?
313
+ num = 0
314
+ self.each{|n| num += 1 if n.first == n.last }
315
+ num == self.length
307
316
  end
308
317
 
318
+
309
319
  def add_breaks
310
320
  trueloops = self.find_all{ |t| t.last == t.first }.length
311
321
  if trueloops == self.length
@@ -364,8 +374,8 @@ module CPEE
364
374
  max = nil
365
375
  sh = self.shortest
366
376
  sh = sh[0..-2] if sh.first == sh.last
367
- sh.each do |e,i|
368
- if self.include_in_all?(e)
377
+ sh.each_with_index do |e,i|
378
+ if self.same_position_in_all?(e,i)
369
379
  max = e
370
380
  else
371
381
  break
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpee
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.137
5
- prerelease:
4
+ version: 1.3.138
6
5
  platform: ruby
7
6
  authors:
8
7
  - Juergen eTM Mangler
@@ -11,70 +10,62 @@ authors:
11
10
  autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2014-07-21 00:00:00.000000000 Z
13
+ date: 2014-07-29 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: riddl
18
17
  requirement: !ruby/object:Gem::Requirement
19
- none: false
20
18
  requirements:
21
- - - ! '>='
19
+ - - ">="
22
20
  - !ruby/object:Gem::Version
23
21
  version: '0'
24
22
  type: :runtime
25
23
  prerelease: false
26
24
  version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
25
  requirements:
29
- - - ! '>='
26
+ - - ">="
30
27
  - !ruby/object:Gem::Version
31
28
  version: '0'
32
29
  - !ruby/object:Gem::Dependency
33
30
  name: weel
34
31
  requirement: !ruby/object:Gem::Requirement
35
- none: false
36
32
  requirements:
37
- - - ! '>='
33
+ - - ">="
38
34
  - !ruby/object:Gem::Version
39
35
  version: '0'
40
36
  type: :runtime
41
37
  prerelease: false
42
38
  version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
39
  requirements:
45
- - - ! '>='
40
+ - - ">="
46
41
  - !ruby/object:Gem::Version
47
42
  version: '0'
48
43
  - !ruby/object:Gem::Dependency
49
44
  name: savon
50
45
  requirement: !ruby/object:Gem::Requirement
51
- none: false
52
46
  requirements:
53
- - - ! '>='
47
+ - - ">="
54
48
  - !ruby/object:Gem::Version
55
49
  version: '0'
56
50
  type: :runtime
57
51
  prerelease: false
58
52
  version_requirements: !ruby/object:Gem::Requirement
59
- none: false
60
53
  requirements:
61
- - - ! '>='
54
+ - - ">="
62
55
  - !ruby/object:Gem::Version
63
56
  version: '0'
64
57
  - !ruby/object:Gem::Dependency
65
58
  name: highline
66
59
  requirement: !ruby/object:Gem::Requirement
67
- none: false
68
60
  requirements:
69
- - - ! '>='
61
+ - - ">="
70
62
  - !ruby/object:Gem::Version
71
63
  version: '0'
72
64
  type: :runtime
73
65
  prerelease: false
74
66
  version_requirements: !ruby/object:Gem::Requirement
75
- none: false
76
67
  requirements:
77
- - - ! '>='
68
+ - - ">="
78
69
  - !ruby/object:Gem::Version
79
70
  version: '0'
80
71
  description: see http://cpee.org
@@ -110,7 +101,6 @@ files:
110
101
  - server/handlerwrappers/default.rb
111
102
  - lib/engine.xml
112
103
  - lib/cpee/callback.rb
113
- - lib/cpee/bpmn2.rb
114
104
  - lib/cpee/handler_notifications.rb
115
105
  - lib/cpee/controller.rb
116
106
  - lib/cpee/processtransformation/bpmn2.rb
@@ -125,9 +115,7 @@ files:
125
115
  - lib/cpee/processtransformation/bpel/Repository/booking.wsdl
126
116
  - lib/cpee/processtransformation/bpel/Repository/booking.bpel
127
117
  - lib/cpee/processtransformation/bpel/lib/BPEL_Transform.rb
128
- - lib/cpee/cpee.rb
129
118
  - lib/cpee/handler_properties.rb
130
- - lib/cpee/structures.rb
131
119
  - lib/cpee/implementation.rb
132
120
  - lib/cpee/empty_workflow.rb
133
121
  - lib/engine/instance-info.rng
@@ -204,27 +192,26 @@ files:
204
192
  homepage: http://cpee.org/
205
193
  licenses:
206
194
  - LGPL-3
195
+ metadata: {}
207
196
  post_install_message:
208
197
  rdoc_options: []
209
198
  require_paths:
210
199
  - lib
211
200
  required_ruby_version: !ruby/object:Gem::Requirement
212
- none: false
213
201
  requirements:
214
- - - ! '>='
202
+ - - ">="
215
203
  - !ruby/object:Gem::Version
216
204
  version: 1.9.3
217
205
  required_rubygems_version: !ruby/object:Gem::Requirement
218
- none: false
219
206
  requirements:
220
- - - ! '>='
207
+ - - ">="
221
208
  - !ruby/object:Gem::Version
222
209
  version: '0'
223
210
  requirements: []
224
211
  rubyforge_project:
225
- rubygems_version: 1.8.23
212
+ rubygems_version: 2.0.14
226
213
  signing_key:
227
- specification_version: 3
214
+ specification_version: 4
228
215
  summary: Preliminary release of cloud process execution engine (cpee). If you just
229
216
  need workflow execution, without a rest/xmpp service exposing it, then use WEEL
230
217
  test_files:
data/lib/cpee/bpmn2.rb DELETED
@@ -1,280 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # This file is part of CPEE.
4
- #
5
- # Apache License, Version 2.0
6
- #
7
- # Copyright (c) 2013 Juergen Mangler
8
- #
9
- # Licensed under the Apache License, Version 2.0 (the "License");
10
- # you may not use this file except in compliance with the License.
11
- # You may obtain a copy of the License at
12
- #
13
- # http://www.apache.org/licenses/LICENSE-2.0
14
- #
15
- # Unless required by applicable law or agreed to in writing, software
16
- # distributed under the License is distributed on an "AS IS" BASIS,
17
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
- # See the License for the specific language governing permissions and
19
- # limitations under the License.
20
-
21
- require File.expand_path(File.dirname(__FILE__) + '/structures')
22
- require 'rubygems'
23
- require 'xml/smart'
24
- require 'highline'
25
-
26
- module CPEE
27
-
28
- module ProcessTransformation
29
-
30
- module Source
31
-
32
- class BPMN2
33
- attr_reader :dataelements, :endpoints, :start, :graph
34
-
35
- def initialize(xml) #{{{
36
- @tree = Tree.new
37
- @hl = HighLine.new
38
- @start = nil
39
-
40
- doc = XML::Smart.string(xml)
41
- doc.register_namespace 'bm', "http://www.omg.org/spec/BPMN/20100524/MODEL"
42
-
43
- @dataelements = {}
44
- @endpoints = {}
45
- @graph = Graph.new
46
-
47
- extract_dataelements(doc)
48
- extract_endpoints(doc)
49
- extract_nodelink(doc)
50
-
51
- @traces = Traces.new [[@start]]
52
- end #}}}
53
-
54
- def extract_dataelements(doc)
55
- doc.find("/bm:definitions/bm:process/bm:property[bm:dataState/@name='cpee:dataelement']").each do |ref|
56
- if ref.attributes['itemSubjectRef']
57
- doc.find("/bm:definitions/bm:itemDefinition[@id=\"" + ref.attributes['itemSubjectRef'] + "\"]").each do |sref|
58
- @dataelements[ref.attributes['name']] = sref.attributes['structureRef'].to_s
59
- end
60
- else
61
- @dataelements[ref.attributes['name']] = ''
62
- end
63
- end
64
- end
65
-
66
- def extract_endpoints(doc)
67
- doc.find("/bm:definitions/bm:process/bm:property[bm:dataState/@name='cpee:endpoint']/@itemSubjectRef").each do |ref|
68
- doc.find("/bm:definitions/bm:itemDefinition[@id=\"" + ref.value + "\"]/@structureRef").each do |sref|
69
- @endpoints[ref.value] = sref.value
70
- end
71
- end
72
- end
73
-
74
- def extract_nodelink(doc)
75
- doc.find("/bm:definitions/bm:process/bm:*[@id and @name and not(@itemSubjectRef) and not(name()='sequenceFlow')]").each do |e|
76
- n = Node.new(e.attributes['id'],e.qname.name.to_sym,e.attributes['name'].strip,e.find('count(bm:incoming)'),e.find('count(bm:outgoing)'))
77
-
78
- if e.attributes['scriptFormat'] != ''
79
- n.script_type = e.attributes['scriptFormat']
80
- end
81
-
82
- e.find("bm:property[@name='cpee:endpoint']/@itemSubjectRef").each do |ep|
83
- n.endpoints << ep.value
84
- end
85
- e.find("bm:property[@name='cpee:method']/@itemSubjectRef").each do |m|
86
- n.methods << m.value
87
- end
88
- e.find("bm:script").each do |s|
89
- n.script ||= ''
90
- n.script << s.text.strip
91
- end
92
- e.find("bm:ioSpecification/bm:dataInput").each do |a|
93
- name = a.attributes['name']
94
- value = a.attributes['itemSubjectRef']
95
- if @dataelements.keys.include?(value)
96
- n.parameters[name] = 'data.' + value
97
- else
98
- n.parameters[name] = value
99
- end
100
- end
101
- e.find("bm:ioSpecification/bm:dataOutput").each do |a|
102
- ref = a.attributes['id']
103
- e.find("bm:dataOutputAssociation[bm:sourceRef=\"#{ref}\"]").each do |d|
104
- n.script_var = ref
105
- n.script_id = d.find("string(bm:targetRef)")
106
- end
107
- end
108
-
109
- @graph.add_node n
110
- @start = n if n.type == :startEvent && @start == nil
111
- end
112
-
113
- # extract all sequences to a links
114
- doc.find("/bm:definitions/bm:process/bm:sequenceFlow").each do |e|
115
- source = e.attributes['sourceRef']
116
- target = e.attributes['targetRef']
117
- cond = e.find('bm:conditionExpression')
118
- @graph.add_link Link.new(source, target, cond.empty? ? nil : cond.first.text.strip)
119
- end
120
-
121
- @graph.clean_up do |node|
122
- if node.type == :scriptTask && (x = @graph.find_script_id(node.id)).any?
123
- x.each do |k,n|
124
- n.script = node.script
125
- n.script_type = node.script_type
126
- end
127
- true
128
- else
129
- false
130
- end
131
- end
132
- end
133
-
134
- def build_traces #{{{
135
- build_extraces @traces, @start
136
- @traces
137
- end #}}}
138
- def build_tree(debug=false) #{{{
139
- build_ttree @tree, @traces.dup, nil, debug
140
- debug_print debug, 'Tree finished'
141
- @tree
142
- end #}}}
143
-
144
- def build_extraces(traces, node) #{{{
145
- dupt = traces.last.dup
146
- @graph.next_nodes(node).each_with_index do |n,i|
147
- traces << dupt.dup if i > 0
148
- if traces.last.include?(n)
149
- traces.last << n
150
- else
151
- traces.last << n
152
- build_extraces(traces,n)
153
- end
154
- end
155
- end #}}}
156
- private :build_extraces
157
-
158
- def map_node(node) #{{{
159
- case node.type
160
- when :parallelGateway
161
- Parallel.new(node.id,node.type)
162
- when :exclusiveGateway
163
- Conditional.new(node.id,:exclusive,node.type)
164
- when :eventBasedGateway
165
- Parallel.new(node.id,node.type,1)
166
- when :inclusiveGateway
167
- Conditional.new(node.id,:inclusive,node.type)
168
- when :endEvent, :startEvent, nil
169
- nil
170
- else
171
- node
172
- end
173
- end #}}}
174
- private :map_node
175
-
176
- def build_ttree(branch,traces,enode=nil,debug=false)
177
- while not traces.finished?
178
- ### if traces exist more than once, make it so they exist only once
179
- ### if somebody creates a modell with an inclusive/exclusive that
180
- ### has identical branches with different conditions, we are fucked
181
- ### but how are the odds? right? right?
182
- traces.uniq!
183
- debug_print debug, traces
184
- if node = traces.same_first
185
- if branch.condition?
186
- li = @graph.link(branch.id,traces.first_node.id)
187
- unless li.nil?
188
- branch.condition << li.condition unless li.condition.nil?
189
- branch.condition_type = "text/javascript"
190
- li.attributes.each do |k,v|
191
- branch.attributes[k] = v
192
- end
193
- end
194
- end
195
- if node == enode
196
- traces.shift_all
197
- elsif node.incoming <= 1
198
- traces.shift_all
199
- n = map_node(node)
200
- if !(n.nil? || (n.container? && (node.outgoing <=1 || traces.finished?)))
201
- (branch << n).compact!
202
- end
203
- else
204
- loops = traces.loops
205
- if node.type == :exclusiveGateway || traces.length == 1
206
- ### as the first is a decision node, just remove and continue
207
- if node.incoming == 2
208
- node.incoming = 1
209
- branch << Loop.new(node.id)
210
- ### remove the gateway itself, as for a single loop it is no longer used.
211
- ### the condition will the loop condition
212
- if traces.length == 1
213
- loops.first.pop
214
- else
215
- traces.shift_all
216
- end
217
- loops.remove_empty
218
- build_ttree branch.last, loops, nil, debug
219
- else
220
- ### dont remove it, treat it as a normal conditional
221
- ### an infinite loop that can only be left by break is created
222
- node.incoming = 1
223
- branch << InfiniteLoop.new(node.id)
224
- ### add the blank conditional to get a break
225
- len = loops.length
226
- loops.add_breaks
227
- build_ttree branch.last, loops, nil, debug
228
- ### set outgoing to number of loops (without the break) so that it can be ignored (should be 1 all the time)
229
- node.outgoing -= len
230
- end
231
- else
232
- node.incoming -= loops.length
233
- ### throw away the loop traces, remove loop traces from front of all other traces
234
- traces.segment_by_loops loops
235
- build_ttree branch, loops, nil, debug
236
- end
237
- traces.remove(loops)
238
- traces.remove_empty
239
- end
240
- else
241
- endnode = traces.find_endnode || enode
242
- tracesgroup, endnode = traces.segment_by endnode
243
- tracesgroup.each do |trcs|
244
- if trcs.finished?
245
- build_ttree branch.last.new_branch, Traces.new([[Break.new(1)]]), endnode, debug
246
- else
247
- build_ttree branch.last.new_branch, trcs, endnode, debug
248
- end
249
- endnode.incoming -= 1 unless endnode.nil?
250
- end
251
- ### all before is reduced to one incoming arrow
252
- ### if now there is still more than one incoming we have a loop situation
253
- ### where the end of a branching statement is also the starting/endpoint
254
- ### of a loop
255
- endnode.incoming += 1 unless endnode.nil?
256
- end
257
- end
258
- end
259
- private :build_ttree
260
-
261
- def debug_print(debug,traces) #{{{
262
- if debug
263
- puts '-' * @hl.output_cols, @tree.to_s
264
- puts traces.to_s
265
- @hl.ask('Continue ... '){ |q| q.echo = false }
266
- end
267
- end #}}}
268
- private :debug_print
269
-
270
- def generate_model(formater) #{{{
271
- formater.new(@tree).generate
272
- end #}}}
273
-
274
- end
275
-
276
- end
277
-
278
- end
279
-
280
- end
data/lib/cpee/cpee.rb DELETED
@@ -1,129 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # This file is part of CPEE.
4
- #
5
- # Apache License, Version 2.0
6
- #
7
- # Copyright (c) 2013 Juergen Mangler
8
- #
9
- # Licensed under the Apache License, Version 2.0 (the "License");
10
- # you may not use this file except in compliance with the License.
11
- # You may obtain a copy of the License at
12
- #
13
- # http://www.apache.org/licenses/LICENSE-2.0
14
- #
15
- # Unless required by applicable law or agreed to in writing, software
16
- # distributed under the License is distributed on an "AS IS" BASIS,
17
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
- # See the License for the specific language governing permissions and
19
- # limitations under the License.
20
-
21
- module CPEE
22
-
23
- module ProcessTransformation
24
-
25
- module Target
26
-
27
- class CPEE
28
- def initialize(tree)
29
- @tree = tree
30
- end
31
- def generate
32
- res = XML::Smart.string("<description xmlns='http://cpee.org/ns/description/1.0'/>")
33
- res.register_namespace 'd', 'http://cpee.org/ns/description/1.0'
34
- generate_for_list(@tree,res.root)
35
- res
36
- end
37
-
38
- def generate_for_list(list,res)
39
- list.each do |e|
40
- nam = e.class.name.gsub(/\w+:+/,'')
41
- send("print_#{nam}".to_sym,e,res)
42
- end
43
- end
44
- private :generate_for_list
45
-
46
- def print_Break(node,res)
47
- res.add('break')
48
- end
49
-
50
- def print_InfiniteLoop(node,res)
51
- s1 = res.add('loop', 'pre_test' => 'true')
52
- generate_for_list(node,s1)
53
- end
54
- def print_Loop_default(node,res)
55
- s1 = res.add('loop', 'pre_test' => node.condition.empty? ? 'true' : node.condition.join(' && '))
56
- s1.attributes['language'] = node.condition_type unless node.condition_type.nil?
57
- generate_for_list(node,s1)
58
- s1
59
- end
60
- private :print_Loop_default
61
- def print_Loop(node,res); print_Loop_default(node,res); end
62
- private :print_Loop
63
-
64
- def print_Node(node,res)
65
- if node.endpoints.empty? && !node.script.nil? && node.script.strip != ''
66
- n = res.add('d:manipulate', 'id' => "a#{node.niceid}")
67
- n.text = node.script
68
- n.attributes['output'] = node.script_var unless node.script_var.nil?
69
- n.attributes['language'] = node.script_type unless node.script_type.nil?
70
- else
71
- n = res.add('d:call', 'id' => "a#{node.niceid}", 'endpoint' => node.endpoints.join(','))
72
- p = n.add('d:parameters')
73
- p.add('d:label',node.label)
74
- p.add('d:method',node.methods.join(','))
75
- p.add('d:type',node.type)
76
- p.add('d:mid',node.id)
77
- par = p.add('d:parameters')
78
- node.parameters.each do |k,v|
79
- par.add(k,v)
80
- end
81
- if !node.script.nil? && node.script.strip != ''
82
- x = n.add('manipulate',node.script)
83
- x.attributes['output'] = node.script_var unless node.script_var.nil?
84
- x.attributes['language'] = node.script_type unless node.script_type.nil?
85
- end
86
- end
87
- end
88
- private :print_Node
89
-
90
- def print_Parallel_default(node,res)
91
- s1 = res.add('parallel','wait' => node.wait)
92
- node.sub.each do |branch|
93
- s2 = s1.add('parallel_branch')
94
- generate_for_list(branch,s2)
95
- end
96
- s1
97
- end
98
- private :print_Parallel_default
99
- def print_Parallel(node,res); print_Parallel_default(node,res); end
100
- private :print_Parallel
101
-
102
- def print_Conditional_default(node,res)
103
- s1 = res.add('d:choose', 'mode' => node.mode)
104
- node.sub.each do |branch|
105
- s2 = if branch.condition.any?
106
- a = s1.add('d:alternative','condition' => branch.condition.join(' or '))
107
- a.attributes['language'] = branch.condition_type unless branch.condition_type.nil?
108
- a
109
- else
110
- s1.add('d:otherwise')
111
- end
112
- generate_for_list(branch,s2)
113
- end
114
- if (x = s1.find('d:otherwise')).any?
115
- s1.add x
116
- end
117
- s1
118
- end
119
- private :print_Conditional_default
120
- def print_Conditional(node,res); print_Conditional_default(node,res); end
121
- private :print_Conditional
122
-
123
- end
124
-
125
- end
126
-
127
- end
128
-
129
- end
@@ -1,437 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # This file is part of CPEE.
4
- #
5
- # Apache License, Version 2.0
6
- #
7
- # Copyright (c) 2013 Juergen Mangler
8
- #
9
- # Licensed under the Apache License, Version 2.0 (the "License");
10
- # you may not use this file except in compliance with the License.
11
- # You may obtain a copy of the License at
12
- #
13
- # http://www.apache.org/licenses/LICENSE-2.0
14
- #
15
- # Unless required by applicable law or agreed to in writing, software
16
- # distributed under the License is distributed on an "AS IS" BASIS,
17
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
- # See the License for the specific language governing permissions and
19
- # limitations under the License.
20
-
21
- module CPEE
22
-
23
- module ProcessTransformation
24
-
25
- class Link #{{{
26
- attr_accessor :from, :to
27
- attr_reader :condition, :attributes
28
- def initialize(from,to,cond=nil)
29
- @from = from
30
- @to = to
31
- @condition = cond
32
- @attributes = {}
33
- end
34
- end #}}}
35
-
36
- module Container
37
- def container?
38
- @container || false
39
- end
40
- end
41
-
42
- class Node #{{{
43
- include Container
44
- @@niceid = -1
45
- attr_reader :id, :label, :niceid
46
- attr_reader :endpoints, :methods, :parameters, :attributes
47
- attr_accessor :script, :script_id, :script_var, :script_type, :incoming, :outgoing, :type
48
- def initialize(id,type,label,incoming,outgoing)
49
- @id = id
50
- @niceid = (@@niceid += 1)
51
- @type = type
52
- @label = label
53
- @endpoints = []
54
- @methods = []
55
- @script = nil
56
- @script_type = nil
57
- @script_id = nil
58
- @script_var = 'result'
59
- @parameters = {}
60
- @incoming = incoming
61
- @outgoing = outgoing
62
- @attributes = {}
63
- end
64
- end # }}}
65
-
66
- module Struct #{{{
67
- def each(&a)
68
- @sub.each{|s| a.call(s)}
69
- end
70
- def length
71
- @sub.length
72
- end
73
- end #}}}
74
-
75
- class Break < Node
76
- def initialize(incoming)
77
- super '-1', :break, 'BREAK', incoming, []
78
- end
79
- end
80
-
81
- class Alternative < Array #{{{
82
- include Container
83
- attr_accessor :condition, :condition_type
84
- attr_reader :id
85
- def condition?; true; end
86
- def initialize(id)
87
- @container = true
88
- @id = id
89
- @condition = []
90
- @condition_type = nil
91
- end
92
- end #}}}
93
- class Branch < Array #{{{
94
- include Container
95
- attr_reader :id
96
- def condition?; false; end
97
- def initialize(id)
98
- @container = true
99
- @id = id
100
- end
101
- end #}}}
102
- class InfiniteLoop < Array #{{{
103
- include Container
104
- def condition?; false; end
105
- attr_accessor :id, :type
106
- def initialize(id)
107
- @container = true
108
- @id = id
109
- @type = :loop
110
- end
111
- end #}}}
112
- class Loop < Array #{{{
113
- include Container
114
- attr_accessor :id, :type, :condition, :condition_type
115
- attr_reader :attributes
116
- def condition?; true; end
117
- def initialize(id)
118
- @container = true
119
- @id = id
120
- @type = :loop
121
- @condition = []
122
- @condition_type = nil
123
- @attributes = {}
124
- end
125
- end #}}}
126
-
127
- class Parallel #{{{
128
- include Container
129
- include Struct
130
- include Enumerable
131
- attr_reader :id, :sub
132
- attr_accessor :type, :wait
133
- def initialize(id,type,wait='-1')
134
- @container = true
135
- @id = id
136
- @type = type
137
- @sub = []
138
- @wait = wait
139
- end
140
- def new_branch
141
- (@sub << Branch.new(@id)).last
142
- end
143
- end #}}}
144
-
145
- class Conditional #{{{
146
- include Container
147
- include Struct
148
- include Enumerable
149
- attr_reader :container
150
- attr_reader :id, :sub, :mode
151
- attr_reader :attributes
152
- attr_accessor :type
153
- def initialize(id,mode,type)
154
- @container = true
155
- @id = id
156
- @sub = []
157
- @mode = mode
158
- @type = type
159
- @attributes = {}
160
- end
161
- def new_branch
162
- (@sub << Alternative.new(@id)).last
163
- end
164
- end #}}}
165
-
166
- class Graph #{{{
167
- attr_reader :flow, :nodes
168
-
169
- def initialize
170
- @nodes = {}
171
- @links = []
172
- end
173
-
174
- def clean_up(&bl)
175
- selnodes = []
176
- @nodes.each do |k,n|
177
- ret = bl.call(n)
178
- selnodes << n if ret
179
- end
180
- selnodes.each do |n|
181
- if n.incoming > 1 || n.outgoing > 1
182
- raise "#{n.inspect} - not a simple node to remove"
183
- end
184
- to,from = nil
185
- @links.each do |f|
186
- to = f if f.to == n.id
187
- from = f if f.from == n.id
188
- end
189
- if to && from
190
- to.to = from.to
191
- @links.delete(from)
192
- @nodes.delete(n.id)
193
- else
194
- raise "#{n.inspect} - could not remove flow"
195
- end
196
- end
197
- end
198
-
199
- def find_script_id(s)
200
- @nodes.find_all{|k,n| n.script_id == s}
201
- end
202
-
203
- def add_node(n)
204
- @nodes[n.id] = n
205
- end
206
-
207
- def link(f,t)
208
- @links.find{ |x| x.from == f && x.to == t }
209
- end
210
-
211
- def add_link(l)
212
- @links << l
213
- end
214
-
215
- def next_nodes(from)
216
- links = @links.find_all { |x| x.from == from.id }
217
- links.map{|x| @nodes[x.to] }
218
- end
219
-
220
- def next_node(from)
221
- if (nodes = next_nodes(from)).length == 1
222
- nodes.first
223
- else
224
- raise "#{from.inspect} - multiple outgoing connections"
225
- end
226
- end
227
- end #}}}
228
-
229
- class Tree < Array #{{{
230
- def condition?; false; end
231
-
232
- def to_s
233
- "TREE:\n" << print_tree(self)
234
- end
235
-
236
- def print_tree(ele,indent=' ')
237
- ret = ''
238
- ele.each_with_index do |e,i|
239
- last = (i == ele.length - 1)
240
- pchar = last ? '└' : '├'
241
- if e.container?
242
- ret << indent + pchar + ' ' + e.class.to_s.gsub(/[^:]*::/,'') + "\n"
243
- ret << print_tree(e,indent + (last ? ' ' : '│ '))
244
- elsif e.is_a?(Break) &&
245
- ret << indent + pchar + ' ' + e.class.to_s.gsub(/[^:]*::/,'') + "\n"
246
- else
247
- ret << indent + pchar + ' ' + e.niceid.to_s + "\n"
248
- end
249
- end
250
- ret
251
- end
252
- private :print_tree
253
- end #}}}
254
-
255
- class Traces < Array #{{{
256
- def initialize_copy(other)
257
- super
258
- self.map!{ |t| t.dup }
259
- end
260
-
261
- def remove(trcs)
262
- trcs.each do |t|
263
- self.delete(t)
264
- end
265
- end
266
-
267
- def remove_empty
268
- self.delete_if{|t| t.empty? }
269
- end
270
-
271
- def first_node
272
- self.first.first
273
- end
274
- def second_nodes
275
- self.map { |t| t[1] }
276
- end
277
-
278
- def shortest
279
- self.min_by{|e|e.length}
280
- end
281
-
282
- def to_s
283
- "TRACES: " + self.collect { |t| t.empty? ? '∅' : t.collect{|n| "%2d" % n.niceid }.join('→ ') }.join("\n ")
284
- end
285
-
286
- def shift_all
287
- self.each{ |tr| tr.shift }
288
- end
289
-
290
- def finished?
291
- self.reduce(0){|sum,t| sum += t.length} == 0
292
- end
293
-
294
- def same_first
295
- (n = self.map{|t| t.first }.uniq).length == 1 ? n.first : nil
296
- end
297
-
298
- def include_in_all?(e)
299
- num = 0
300
- self.each{|n| num += 1 if n.include?(e)}
301
- num == self.length
302
- end
303
-
304
- def infinite_loop_fix
305
- self << self.first.dup
306
- self.last.pop
307
- end
308
-
309
- def add_breaks
310
- trueloops = self.find_all{ |t| t.last == t.first }.length
311
- if trueloops == self.length
312
- self << [self.first_node] ### the blank conditional so that we get a break
313
- else
314
- self.each do |t|
315
- t << Break.new(1) unless t.last == t.first ### an explicit break
316
- end
317
- end
318
- end
319
-
320
- def loops
321
- lo = Traces.new self.find_all{ |t| t.first == t.last }
322
- self.each do |t|
323
- lo << t if lo.second_nodes.include?(t[1])
324
- end
325
- lo.uniq
326
- end
327
-
328
- def eliminate(loops)
329
- ### find nested loops
330
- self.each_with_index do |t,i|
331
- maxcut = 0
332
- ### find out which common parts the traces share with theloops
333
- loops.each do |l|
334
- maxcut.upto(l.length) do |i|
335
- maxcut = i if t[0...i] == l[0...i]
336
- end
337
- end
338
- ### in case of nested loop (common part occurs at end of loop), include the whole
339
- 0.upto (maxcut-1) do |j|
340
- if self[i][j] == self[i].last
341
- loops << self[i].shift(self[i].length)
342
- end
343
- end
344
- end
345
- loops.uniq!
346
- loops.remove_empty
347
- self.remove_empty
348
-
349
- ### cut from non-nested loops
350
- self.each_with_index do |t,i|
351
- maxcut = 0
352
- ### find out which common parts the traces share with theloops
353
- loops.each do |l|
354
- maxcut.upto(l.length) do |i|
355
- maxcut = i if t[0...i] == l[0...i]
356
- end
357
- end
358
- loops << self[i].shift(maxcut)
359
- end
360
- end
361
-
362
- def extend
363
- # find largest common
364
- max = nil
365
- sh = self.shortest
366
- sh = sh[0..-2] if sh.first == sh.last
367
- sh.each do |e,i|
368
- if self.include_in_all?(e)
369
- max = e
370
- else
371
- break
372
- end
373
- end
374
-
375
- # if last is the largest common do nothing
376
- # else append from last to largest common
377
- self.each do |t|
378
- unless t.last == max
379
- last = t.last
380
- t.last.incoming = 1
381
- if t.index(last) && t.index(max)
382
- (t.index(last) + 1).upto(t.index(max)) do |i|
383
- t << t[i]
384
- end
385
- end
386
- end
387
- end
388
-
389
- max.incoming = self.length
390
- max
391
- end
392
-
393
- def segment_by_loops(loops)
394
- # supress loops
395
- self.delete_if { |t| loops.include?(t) }
396
- self.eliminate(loops)
397
- loops.extend
398
- end
399
-
400
- def find_endnode
401
- # supress loops
402
- trcs = self.dup
403
- trcs.delete_if { |t| t.uniq.length < t.length }
404
-
405
- # find common node (except loops)
406
- enode = nil
407
- trcs.first.each do |n|
408
- if trcs.include_in_all?(n)
409
- enode = n
410
- break
411
- end
412
- end
413
- enode
414
- end
415
-
416
- def segment_by(endnode)
417
- # cut shit until common node, return the shit you cut away
418
- tracesgroup = self.group_by{|t| t.first}.map do |k,trace|
419
- coltrace = trace.map do |t|
420
- # slice upto common node, collect the sliced away part
421
- len = t.index(endnode)
422
- if len
423
- cut = t.slice!(0...len)
424
- cut << t.first
425
- else # if endnode is nil, then return the whole
426
- t
427
- end
428
- end.uniq
429
- Traces.new(coltrace)
430
- end
431
- [tracesgroup,endnode]
432
- end
433
- end #}}}
434
-
435
- end
436
-
437
- end