cpee 1.3.129 → 1.3.130

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/cpee.gemspec +1 -1
  3. data/lib/cpee/processtransformation/bpel/Repository/booking.bpel +125 -0
  4. data/lib/cpee/processtransformation/bpel/Repository/booking.wsdl +72 -0
  5. data/lib/cpee/processtransformation/bpel/Repository/booking/airline.wsdl +71 -0
  6. data/lib/cpee/processtransformation/bpel/Repository/booking/hotel.wsdl +64 -0
  7. data/lib/cpee/processtransformation/bpel/Repository/booking/report.wsdl +71 -0
  8. data/lib/cpee/processtransformation/bpel/bpel2wee.rb +34 -0
  9. data/lib/cpee/processtransformation/bpel/bpelserver.ru +64 -0
  10. data/lib/cpee/processtransformation/bpel/bpelserver.xml +70 -0
  11. data/lib/cpee/processtransformation/bpel/lib/BPEL_Transform.rb +367 -0
  12. data/lib/cpee/processtransformation/bpmn2.rb +273 -0
  13. data/lib/cpee/processtransformation/cpee.rb +118 -0
  14. data/lib/cpee/processtransformation/structures.rb +426 -0
  15. data/server/instances/1/properties.xml +101 -69
  16. data/server/instances/10/properties.xml +109 -0
  17. data/server/instances/11/properties.xml +109 -0
  18. data/server/instances/2/properties.xml +44 -191
  19. data/server/instances/3/properties.xml +44 -70
  20. data/server/instances/4/properties.xml +68 -28
  21. data/server/instances/5/properties.xml +70 -10
  22. data/server/instances/6/properties.xml +55 -175
  23. data/server/instances/7/properties.xml +83 -0
  24. data/server/instances/8/properties.xml +83 -0
  25. data/server/instances/9/properties.xml +77 -0
  26. metadata +111 -111
  27. data/server/instances/1/notifications/d12eff1ac812661c05d7090ce7394cf9/consumer-secret +0 -1
  28. data/server/instances/1/notifications/d12eff1ac812661c05d7090ce7394cf9/producer-secret +0 -1
  29. data/server/instances/1/notifications/d12eff1ac812661c05d7090ce7394cf9/subscription.xml +0 -27
  30. data/server/instances/6/notifications/5c8c36c3dfcec8e36c3b25859a71778c/consumer-secret +0 -1
  31. data/server/instances/6/notifications/5c8c36c3dfcec8e36c3b25859a71778c/producer-secret +0 -1
  32. data/server/instances/6/notifications/5c8c36c3dfcec8e36c3b25859a71778c/subscription.xml +0 -27
  33. data/server/server.pid +0 -1
@@ -0,0 +1,273 @@
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
189
+ branch.condition_type = "text/javascript"
190
+ end
191
+ end
192
+ if node == enode
193
+ traces.shift_all
194
+ elsif node.incoming <= 1
195
+ traces.shift_all
196
+ n = map_node(node)
197
+ if !(n.nil? || (n.container? && (node.outgoing <=1 || traces.finished?)))
198
+ (branch << n).compact!
199
+ end
200
+ else
201
+ loops = traces.loops
202
+ if node.type == :exclusiveGateway
203
+ ### as the first is a decision node, just remove and continue
204
+ if node.incoming == 2
205
+ node.incoming = 1
206
+ branch << Loop.new(node.id)
207
+ ### remove the gateway itself, as for a single loop it is no longer used.
208
+ ### the condition will the loop condition
209
+ traces.shift_all
210
+ loops.remove_empty
211
+ build_ttree branch.last, loops, nil, debug
212
+ else
213
+ ### dont remove it, treat it as a normal conditional
214
+ ### an infinite loop that can only be left by break is created
215
+ node.incoming = 1
216
+ branch << InfiniteLoop.new(node.id)
217
+ ### add the blank conditional to get a break
218
+ len = loops.length
219
+ loops.add_breaks
220
+ build_ttree branch.last, loops, nil, debug
221
+ ### set outgoing to number of loops (without the break) so that it can be ignored (should be 1 all the time)
222
+ node.outgoing -= len
223
+ end
224
+ else
225
+ node.incoming -= loops.length
226
+ ### throw away the loop traces, remove loop traces from front of all other traces
227
+ traces.segment_by_loops loops
228
+ build_ttree branch, loops, nil, debug
229
+ end
230
+ traces.remove(loops)
231
+ traces.remove_empty
232
+ end
233
+ else
234
+ endnode = traces.find_endnode || enode
235
+ tracesgroup, endnode = traces.segment_by endnode
236
+ tracesgroup.each do |trcs|
237
+ if trcs.finished?
238
+ build_ttree branch.last.new_branch, Traces.new([[Break.new(1)]]), endnode, debug
239
+ else
240
+ build_ttree branch.last.new_branch, trcs, endnode, debug
241
+ end
242
+ endnode.incoming -= 1 unless endnode.nil?
243
+ end
244
+ ### all before is reduced to one incoming arrow
245
+ ### if now there is still more than one incoming we have a loop situation
246
+ ### where the end of a branching statement is also the starting/endpoint
247
+ ### of a loop
248
+ endnode.incoming += 1 unless endnode.nil?
249
+ end
250
+ end
251
+ end
252
+ private :build_ttree
253
+
254
+ def debug_print(debug,traces) #{{{
255
+ if debug
256
+ puts '-' * @hl.output_cols, @tree.to_s
257
+ puts traces.to_s
258
+ @hl.ask('Continue ... '){ |q| q.echo = false }
259
+ end
260
+ end #}}}
261
+ private :debug_print
262
+
263
+ def generate_model(formater) #{{{
264
+ formater.new(@tree).generate
265
+ end #}}}
266
+
267
+ end
268
+
269
+ end
270
+
271
+ end
272
+
273
+ end
@@ -0,0 +1,118 @@
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(node,res)
55
+ s1 = res.add('loop', 'pre_test' => node.condition.join(' && '))
56
+ s1.attributes['language'] = node.condition_type unless node.condition_type.nil?
57
+ generate_for_list(node,s1)
58
+ end
59
+
60
+ def print_Node(node,res)
61
+ if node.endpoints.empty? && !node.script.nil? && node.script.strip != ''
62
+ n = res.add('d:manipulate', 'id' => "a#{node.niceid}")
63
+ n.text = node.script
64
+ n.attributes['output'] = node.script_var unless node.script_var.nil?
65
+ n.attributes['language'] = node.script_type unless node.script_type.nil?
66
+ else
67
+ n = res.add('d:call', 'id' => "a#{node.niceid}", 'endpoint' => node.endpoints.join(','))
68
+ p = n.add('d:parameters')
69
+ p.add('d:label',node.label)
70
+ p.add('d:method',node.methods.join(','))
71
+ p.add('d:type',node.type)
72
+ p.add('d:mid',node.id)
73
+ par = p.add('d:parameters')
74
+ node.parameters.each do |k,v|
75
+ par.add(k,v)
76
+ end
77
+ if !node.script.nil? && node.script.strip != ''
78
+ x = n.add('manipulate',node.script)
79
+ x.attributes['output'] = node.script_var unless node.script_var.nil?
80
+ x.attributes['language'] = node.script_type unless node.script_type.nil?
81
+ end
82
+ end
83
+ end
84
+ private :print_Node
85
+
86
+ def print_Parallel(node,res)
87
+ s1 = res.add('parallel','wait' => node.wait)
88
+ node.sub.each do |branch|
89
+ s2 = s1.add('parallel_branch')
90
+ generate_for_list(branch,s2)
91
+ end
92
+ end
93
+ private :print_Parallel
94
+
95
+ def print_Conditional(node,res)
96
+ s1 = res.add('d:choose', 'mode' => node.mode)
97
+ node.sub.each do |branch|
98
+ s2 = if branch.condition.any?
99
+ a = s1.add('d:alternative','condition' => branch.condition.join(' or '))
100
+ a.attributes['language'] = branch.condition_type unless branch.condition_type.nil?
101
+ a
102
+ else
103
+ s1.add('d:otherwise')
104
+ end
105
+ generate_for_list(branch,s2)
106
+ end
107
+ if (x = s1.find('d:otherwise')).any?
108
+ s1.add x
109
+ end
110
+ end
111
+ private :print_Conditional
112
+ end
113
+
114
+ end
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,426 @@
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
28
+ def initialize(from,to,cond=nil)
29
+ @from = from
30
+ @to = to
31
+ @condition = cond
32
+ end
33
+ end #}}}
34
+
35
+ module Container
36
+ def container?
37
+ @container || false
38
+ end
39
+ end
40
+
41
+ class Node #{{{
42
+ include Container
43
+ @@niceid = -1
44
+ attr_reader :id, :label, :niceid
45
+ attr_reader :endpoints, :methods, :parameters
46
+ attr_accessor :script, :script_id, :script_var, :script_type, :incoming, :outgoing, :type
47
+ def initialize(id,type,label,incoming,outgoing)
48
+ @id = id
49
+ @niceid = (@@niceid += 1)
50
+ @type = type
51
+ @label = label
52
+ @endpoints = []
53
+ @methods = []
54
+ @script = nil
55
+ @script_type = nil
56
+ @script_id = nil
57
+ @script_var = 'result'
58
+ @parameters = {}
59
+ @incoming = incoming
60
+ @outgoing = outgoing
61
+ end
62
+ end # }}}
63
+
64
+ module Struct #{{{
65
+ def each(&a)
66
+ @sub.each{|s| a.call(s)}
67
+ end
68
+ def length
69
+ @sub.length
70
+ end
71
+ end #}}}
72
+
73
+ class Break < Node
74
+ def initialize(incoming)
75
+ super '-1', :break, 'BREAK', incoming, []
76
+ end
77
+ end
78
+
79
+ class Alternative < Array #{{{
80
+ include Container
81
+ attr_accessor :condition, :condition_type
82
+ attr_reader :id
83
+ def condition?; true; end
84
+ def initialize(id)
85
+ @container = true
86
+ @id = id
87
+ @condition = []
88
+ @condition_type = nil
89
+ end
90
+ end #}}}
91
+ class Branch < Array #{{{
92
+ include Container
93
+ attr_reader :id
94
+ def condition?; false; end
95
+ def initialize(id)
96
+ @container = true
97
+ @id = id
98
+ end
99
+ end #}}}
100
+ class InfiniteLoop < Array #{{{
101
+ include Container
102
+ def condition?; false; end
103
+ attr_accessor :id, :type
104
+ def initialize(id)
105
+ @container = true
106
+ @id = id
107
+ @type = :loop
108
+ end
109
+ end #}}}
110
+ class Loop < Array #{{{
111
+ include Container
112
+ attr_accessor :id, :type, :condition, :condition_type
113
+ def condition?; true; end
114
+ def initialize(id)
115
+ @container = true
116
+ @id = id
117
+ @type = :loop
118
+ @condition = []
119
+ @condition_type = nil
120
+ end
121
+ end #}}}
122
+
123
+ class Parallel #{{{
124
+ include Container
125
+ include Struct
126
+ include Enumerable
127
+ attr_reader :id, :sub
128
+ attr_accessor :type, :wait
129
+ def initialize(id,type,wait='-1')
130
+ @container = true
131
+ @id = id
132
+ @type = type
133
+ @sub = []
134
+ @wait = wait
135
+ end
136
+ def new_branch
137
+ (@sub << Branch.new(@id)).last
138
+ end
139
+ end #}}}
140
+
141
+ class Conditional #{{{
142
+ include Container
143
+ include Struct
144
+ include Enumerable
145
+ attr_reader :container
146
+ attr_reader :id, :sub, :mode
147
+ attr_accessor :type
148
+ def initialize(id,mode,type)
149
+ @container = true
150
+ @id = id
151
+ @sub = []
152
+ @mode = mode
153
+ @type = type
154
+ end
155
+ def new_branch
156
+ (@sub << Alternative.new(@id)).last
157
+ end
158
+ end #}}}
159
+
160
+ class Graph #{{{
161
+ attr_reader :flow, :nodes
162
+
163
+ def initialize
164
+ @nodes = {}
165
+ @links = []
166
+ end
167
+
168
+ def clean_up(&bl)
169
+ selnodes = []
170
+ @nodes.each do |k,n|
171
+ ret = bl.call(n)
172
+ selnodes << n if ret
173
+ end
174
+ selnodes.each do |n|
175
+ if n.incoming > 1 || n.outgoing > 1
176
+ raise "#{n.inspect} - not a simple node to remove"
177
+ end
178
+ to,from = nil
179
+ @links.each do |f|
180
+ to = f if f.to == n.id
181
+ from = f if f.from == n.id
182
+ end
183
+ if to && from
184
+ to.to = from.to
185
+ @links.delete(from)
186
+ @nodes.delete(n.id)
187
+ else
188
+ raise "#{n.inspect} - could not remove flow"
189
+ end
190
+ end
191
+ end
192
+
193
+ def find_script_id(s)
194
+ @nodes.find_all{|k,n| n.script_id == s}
195
+ end
196
+
197
+ def add_node(n)
198
+ @nodes[n.id] = n
199
+ end
200
+
201
+ def link(f,t)
202
+ @links.find{ |x| x.from == f && x.to == t }
203
+ end
204
+
205
+ def add_link(l)
206
+ @links << l
207
+ end
208
+
209
+ def next_nodes(from)
210
+ links = @links.find_all { |x| x.from == from.id }
211
+ links.map{|x| @nodes[x.to] }
212
+ end
213
+
214
+ def next_node(from)
215
+ if (nodes = next_nodes(from)).length == 1
216
+ nodes.first
217
+ else
218
+ raise "#{from.inspect} - multiple outgoing connections"
219
+ end
220
+ end
221
+ end #}}}
222
+
223
+ class Tree < Array #{{{
224
+ def condition?; false; end
225
+
226
+ def to_s
227
+ "TREE:\n" << print_tree(self)
228
+ end
229
+
230
+ def print_tree(ele,indent=' ')
231
+ ret = ''
232
+ ele.each_with_index do |e,i|
233
+ last = (i == ele.length - 1)
234
+ pchar = last ? '└' : '├'
235
+ if e.container?
236
+ ret << indent + pchar + ' ' + e.class.to_s.gsub(/[^:]*::/,'') + "\n"
237
+ ret << print_tree(e,indent + (last ? ' ' : '│ '))
238
+ elsif e.is_a?(Break) &&
239
+ ret << indent + pchar + ' ' + e.class.to_s.gsub(/[^:]*::/,'') + "\n"
240
+ else
241
+ ret << indent + pchar + ' ' + e.niceid.to_s + "\n"
242
+ end
243
+ end
244
+ ret
245
+ end
246
+ private :print_tree
247
+ end #}}}
248
+
249
+ class Traces < Array #{{{
250
+ def initialize_copy(other)
251
+ super
252
+ self.map!{ |t| t.dup }
253
+ end
254
+
255
+ def remove(trcs)
256
+ trcs.each do |t|
257
+ self.delete(t)
258
+ end
259
+ end
260
+
261
+ def remove_empty
262
+ self.delete_if{|t| t.empty? }
263
+ end
264
+
265
+ def first_node
266
+ self.first.first
267
+ end
268
+ def second_nodes
269
+ self.map { |t| t[1] }
270
+ end
271
+
272
+ def shortest
273
+ self.min_by{|e|e.length}
274
+ end
275
+
276
+ def to_s
277
+ "TRACES: " + self.collect { |t| t.empty? ? '∅' : t.collect{|n| "%2d" % n.niceid }.join('→ ') }.join("\n ")
278
+ end
279
+
280
+ def shift_all
281
+ self.each{ |tr| tr.shift }
282
+ end
283
+
284
+ def finished?
285
+ self.reduce(0){|sum,t| sum += t.length} == 0
286
+ end
287
+
288
+ def same_first
289
+ (n = self.map{|t| t.first }.uniq).length == 1 ? n.first : nil
290
+ end
291
+
292
+ def include_in_all?(e)
293
+ num = 0
294
+ self.each{|n| num += 1 if n.include?(e)}
295
+ num == self.length
296
+ end
297
+
298
+ def add_breaks
299
+ trueloops = self.find_all{ |t| t.last == t.first }.length
300
+ if trueloops == self.length
301
+ self << [self.first_node] ### the blank conditional so that we get a break
302
+ else
303
+ self.each do |t|
304
+ t << Break.new(1) unless t.last == t.first ### an explicit break
305
+ end
306
+ end
307
+ end
308
+
309
+ def loops
310
+ lo = Traces.new self.find_all{ |t| t.first == t.last }
311
+ self.each do |t|
312
+ lo << t if lo.second_nodes.include?(t[1])
313
+ end
314
+ lo.uniq
315
+ end
316
+
317
+ def eliminate(loops)
318
+ ### find nested loops
319
+ self.each_with_index do |t,i|
320
+ maxcut = 0
321
+ ### find out which common parts the traces share with theloops
322
+ loops.each do |l|
323
+ maxcut.upto(l.length) do |i|
324
+ maxcut = i if t[0...i] == l[0...i]
325
+ end
326
+ end
327
+ ### in case of nested loop (common part occurs at end of loop), include the whole
328
+ 0.upto (maxcut-1) do |j|
329
+ if self[i][j] == self[i].last
330
+ loops << self[i].shift(self[i].length)
331
+ end
332
+ end
333
+ end
334
+ loops.uniq!
335
+ loops.remove_empty
336
+ self.remove_empty
337
+
338
+ ### cut from non-nested loops
339
+ self.each_with_index do |t,i|
340
+ maxcut = 0
341
+ ### find out which common parts the traces share with theloops
342
+ loops.each do |l|
343
+ maxcut.upto(l.length) do |i|
344
+ maxcut = i if t[0...i] == l[0...i]
345
+ end
346
+ end
347
+ loops << self[i].shift(maxcut)
348
+ end
349
+ end
350
+
351
+ def extend
352
+ # find largest common
353
+ max = nil
354
+ sh = self.shortest
355
+ sh = sh[0..-2] if sh.first == sh.last
356
+ sh.each do |e,i|
357
+ if self.include_in_all?(e)
358
+ max = e
359
+ else
360
+ break
361
+ end
362
+ end
363
+
364
+ # if last is the largest common do nothing
365
+ # else append from last to largest common
366
+ self.each do |t|
367
+ unless t.last == max
368
+ last = t.last
369
+ t.last.incoming = 1
370
+ if t.index(last) && t.index(max)
371
+ (t.index(last) + 1).upto(t.index(max)) do |i|
372
+ t << t[i]
373
+ end
374
+ end
375
+ end
376
+ end
377
+
378
+ max.incoming = self.length
379
+ max
380
+ end
381
+
382
+ def segment_by_loops(loops)
383
+ # supress loops
384
+ self.delete_if { |t| loops.include?(t) }
385
+ self.eliminate(loops)
386
+ loops.extend
387
+ end
388
+
389
+ def find_endnode
390
+ # supress loops
391
+ trcs = self.dup
392
+ trcs.delete_if { |t| t.uniq.length < t.length }
393
+
394
+ # find common node (except loops)
395
+ enode = nil
396
+ trcs.first.each do |n|
397
+ if trcs.include_in_all?(n)
398
+ enode = n
399
+ break
400
+ end
401
+ end
402
+ enode
403
+ end
404
+
405
+ def segment_by(endnode)
406
+ # cut shit until common node, return the shit you cut away
407
+ tracesgroup = self.group_by{|t| t.first}.map do |k,trace|
408
+ coltrace = trace.map do |t|
409
+ # slice upto common node, collect the sliced away part
410
+ len = t.index(endnode)
411
+ if len
412
+ cut = t.slice!(0...len)
413
+ cut << t.first
414
+ else # if endnode is nil, then return the whole
415
+ t
416
+ end
417
+ end.uniq
418
+ Traces.new(coltrace)
419
+ end
420
+ [tracesgroup,endnode]
421
+ end
422
+ end #}}}
423
+
424
+ end
425
+
426
+ end