cpee 1.3.137 → 1.3.138

Sign up to get free protection for your applications and to get access to all the features.
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