cpee-transformation 1.0.0

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.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +2 -0
  3. data/LICENSE +165 -0
  4. data/README.md +1 -0
  5. data/Rakefile +21 -0
  6. data/cpee-transformation.gemspec +29 -0
  7. data/lib/cpee/transformation/beautiful.rb +182 -0
  8. data/lib/cpee/transformation/bpmn2.rb +144 -0
  9. data/lib/cpee/transformation/cpee.rb +309 -0
  10. data/lib/cpee/transformation/dataflow.rb +127 -0
  11. data/lib/cpee/transformation/graphviz.rb +100 -0
  12. data/lib/cpee/transformation/implementation.rb +144 -0
  13. data/lib/cpee/transformation/implementation.xml +47 -0
  14. data/lib/cpee/transformation/mermaid.rb +242 -0
  15. data/lib/cpee/transformation/ptml.rb +316 -0
  16. data/lib/cpee/transformation/structures.rb +570 -0
  17. data/lib/cpee/transformation/target.rb +58 -0
  18. data/lib/cpee/transformation/text-bf.rb +201 -0
  19. data/lib/cpee/transformation/text-df-PO-extended.rb +221 -0
  20. data/lib/cpee/transformation/text-df-PO-reduced.rb +211 -0
  21. data/lib/cpee/transformation/transformation_text_cpee.xml +49 -0
  22. data/lib/cpee/transformation/transformation_xml_cpee.xml +49 -0
  23. data/lib/cpee/transformation/transformation_xml_text.xml +49 -0
  24. data/lib/cpee/transformation/transformer.rb +300 -0
  25. data/server/trans +38 -0
  26. data/tools/bpmn2_to_cpee.rb +84 -0
  27. data/tools/bpmn2_to_mermaid.rb +85 -0
  28. data/tools/bpmn2_to_ptml.rb +87 -0
  29. data/tools/cpee-trans +74 -0
  30. data/tools/cpee_to_cpee.rb +83 -0
  31. data/tools/cpee_to_dataflow.rb +83 -0
  32. data/tools/cpee_to_mermaid.rb +85 -0
  33. data/tools/cpee_to_ptml.rb +87 -0
  34. data/tools/cpee_to_text_bf.rb +85 -0
  35. data/tools/cpee_to_text_df-poe.rb +85 -0
  36. data/tools/cpee_to_text_df-por.rb +85 -0
  37. data/tools/mermaid_to_cpee.rb +85 -0
  38. data/tools/ptml_to_cpee.rb +87 -0
  39. metadata +160 -0
@@ -0,0 +1,570 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # This file is part of CPEE-TRANSFORMATION.
4
+ #
5
+ # CPEE-TRANSFORMATION is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # CPEE-TRANSFORMATION is distributed in the hope that it will be useful, but
11
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with CPEE-TRANSFORMATION (file COPYING in the main directory). If not,
17
+ # see <http://www.gnu.org/licenses/>.
18
+
19
+ module CPEE
20
+
21
+ module Transformation
22
+
23
+ module Container #{{{
24
+ def container?
25
+ @container || false
26
+ end
27
+ end #}}}
28
+ module Struct #{{{
29
+ def each(&a)
30
+ @sub.each{|s| a.call(s)}
31
+ end
32
+ def length
33
+ @sub.length
34
+ end
35
+ end #}}}
36
+
37
+ class Node #{{{
38
+ include Container
39
+ @@niceid = {}
40
+ attr_reader :id
41
+ attr_reader :endpoints, :methods, :arguments, :attributes
42
+ attr_accessor :script, :script_id, :script_var, :script_type, :incoming, :outgoing, :type, :label, :niceid
43
+ def initialize(context,id,type,label,incoming,outgoing)
44
+ @@niceid[context] ||= -1
45
+ @niceid = (@@niceid[context] += 1)
46
+ @id = id
47
+ @type = type
48
+ @label = label
49
+ @endpoints = []
50
+ @methods = []
51
+ @script = nil
52
+ @script_type = nil
53
+ @script_id = nil
54
+ @script_var = 'result'
55
+ @arguments = {}
56
+ @incoming = incoming
57
+ @outgoing = outgoing
58
+ @attributes = {}
59
+ end
60
+
61
+ def inc_incoming!
62
+ @incoming += 1
63
+ end
64
+ def inc_outgoing!
65
+ @outgoing += 1
66
+ end
67
+
68
+ def to_s
69
+ "#{@niceid} (#{@label},#{@type})\n"
70
+ end
71
+ end # }}}
72
+ class Link #{{{
73
+ attr_accessor :from, :to
74
+ attr_reader :condition, :attributes, :otherwise
75
+ def initialize(from,to,cond=nil,otherwise=false,id=nil)
76
+ @from = from
77
+ @to = to
78
+ @id = id
79
+ @otherwise = otherwise
80
+ @condition = cond
81
+ @attributes = {}
82
+ end
83
+ end #}}}
84
+ class Break < Node #{{{
85
+ def initialize(context)
86
+ super context, '-1', :break, 'BREAK', 1, []
87
+ end
88
+ end #}}}
89
+
90
+ class Alternative < Array #{{{
91
+ include Container
92
+ attr_accessor :condition, :condition_type, :otherwise
93
+ attr_reader :id, :attributes
94
+ def condition?; true; end
95
+ def initialize(id)
96
+ @container = true
97
+ @id = id
98
+ @otherwise = false
99
+ @condition = []
100
+ @condition_type = nil
101
+ @attributes = {}
102
+ end
103
+ def inspect
104
+ ::Object::inspect()
105
+ end
106
+ end #}}}
107
+ class Branch < Array #{{{
108
+ include Container
109
+ attr_reader :id
110
+ def condition?; false; end
111
+ def initialize(id)
112
+ @container = true
113
+ @id = id
114
+ end
115
+ end #}}}
116
+
117
+ class Loop #{{{
118
+ include Container
119
+ include Struct
120
+ include Enumerable
121
+ attr_reader :id, :sub
122
+ attr_accessor :type, :condition, :condition_type, :mode
123
+ attr_reader :attributes
124
+ def condition?; true; end
125
+ def initialize(id)
126
+ @container = true
127
+ @id = id
128
+ @type = :loop
129
+ @mode = :pre_test
130
+ @condition = []
131
+ @sub = []
132
+ @condition_type = nil
133
+ @attributes = {}
134
+ end
135
+ def new_branch
136
+ (@sub << Alternative.new(@id)).last
137
+ end
138
+ end #}}}
139
+
140
+ class Parallel #{{{
141
+ include Container
142
+ include Struct
143
+ include Enumerable
144
+ attr_reader :id, :sub
145
+ attr_accessor :type, :wait, :cancel
146
+ def initialize(id,type,wait='-1',cancel='last')
147
+ @container = true
148
+ @id = id
149
+ @type = type
150
+ @sub = []
151
+ @wait = wait
152
+ @cancel = cancel
153
+ end
154
+ def new_branch
155
+ (@sub << Branch.new(@id)).last
156
+ end
157
+ end #}}}
158
+
159
+ class Conditional #{{{
160
+ include Container
161
+ include Struct
162
+ include Enumerable
163
+ attr_reader :container
164
+ attr_reader :id, :sub, :mode, :label
165
+ attr_reader :attributes
166
+ attr_accessor :type
167
+ def initialize(id,mode,type,label='')
168
+ @container = true
169
+ @id = id
170
+ @label = label
171
+ @sub = []
172
+ @mode = mode
173
+ @type = type
174
+ @attributes = {}
175
+ end
176
+ def new_branch
177
+ (@sub << Alternative.new(@id)).last
178
+ end
179
+ end #}}}
180
+
181
+ class Graph #{{{
182
+ attr_reader :flow, :nodes
183
+
184
+ def find_node(niceid)
185
+ @nodes.find{|k,v| v.niceid == niceid }
186
+ end
187
+
188
+ def initialize
189
+ @nodes = {}
190
+ @links = []
191
+ end
192
+
193
+ def to_s
194
+ s = ''
195
+ s << "Nodes:\n"
196
+ @nodes.each do |k,v|
197
+ s << " #{v.niceid} -> #{v.id}, #{v.label}\n"
198
+ end
199
+ s << "Links:\n"
200
+ @links.each do |e|
201
+ s << " #{e.from} -> #{e.to} #{e.condition ? "(#{e.condition})" : ''}\n"
202
+ end
203
+ s
204
+ end
205
+
206
+ def clean_up(&bl)
207
+ selnodes = []
208
+ @nodes.each do |k,n|
209
+ ret = bl.call(n)
210
+ selnodes << n if ret
211
+ end
212
+ selnodes.each do |n|
213
+ if n.incoming > 1 || n.outgoing > 1
214
+ raise "#{n.inspect} - not a simple node to remove"
215
+ end
216
+ to,from = nil
217
+ @links.each do |f|
218
+ to = f if f.to == n.id
219
+ from = f if f.from == n.id
220
+ end
221
+ if to && from
222
+ to.to = from.to
223
+ @links.delete(from)
224
+ @nodes.delete(n.id)
225
+ else
226
+ raise "#{n.inspect} - could not remove flow"
227
+ end
228
+ end
229
+ end
230
+
231
+ def find_script_id(s)
232
+ @nodes.find_all{|k,n| n.script_id == s}
233
+ end
234
+
235
+ def add_node(n,ntype=nil)
236
+ if @nodes.include?(n.id)
237
+ case ntype
238
+ when :outgoing
239
+ @nodes[n.id].inc_outgoing!
240
+ when :incoming
241
+ @nodes[n.id].inc_incoming!
242
+ end
243
+ if @nodes[n.id].label.nil? || @nodes[n.id].label.strip == ''
244
+ @nodes[n.id].label = n.label
245
+ end
246
+ @nodes[n.id]
247
+ else
248
+ @nodes[n.id] = n
249
+ end
250
+ end
251
+
252
+ def link(f,t)
253
+ @links.find{ |x| x.from == f && x.to == t }
254
+ end
255
+
256
+ def add_link(l)
257
+ @links << l
258
+ end
259
+
260
+ def next_nodes(from)
261
+ links = @links.find_all { |x| x.from == from.id }
262
+ links.map{|x| @nodes[x.to] }
263
+ end
264
+
265
+ def next_node(from)
266
+ if (nodes = next_nodes(from)).length == 1
267
+ nodes.first
268
+ else
269
+ raise "#{from.inspect} - multiple outgoing connections"
270
+ end
271
+ end
272
+ end #}}}
273
+
274
+ class Tree < Array #{{{
275
+ def condition?; false; end
276
+
277
+ def to_s(verbose=true)
278
+ "TREE:\n" << print_tree(self,' ',verbose)
279
+ end
280
+
281
+ def print_tree(ele,indent=' ',verbose=true)
282
+ ret = ''
283
+ ele.each_with_index do |e,i|
284
+ last = (i == ele.length - 1)
285
+ pchar = last ? '└' : '├'
286
+ if e.container?
287
+ cname = e.class.to_s.gsub(/[^:]*::/,'')
288
+ ret << indent + pchar + ' ' + cname + " #{cname == 'Alternative' ? e.condition : ''}\n"
289
+ ret << print_tree(e,indent + (last ? ' ' : '│ '),verbose)
290
+ elsif e.is_a?(Break)
291
+ ret << indent + pchar + ' ' + e.class.to_s.gsub(/[^:]*::/,'') + "\n"
292
+ else
293
+ ret << indent + pchar + ' ' + e.niceid.to_s + (verbose ? " (#{e.label})" : "") + "\n"
294
+ end
295
+ end
296
+ ret
297
+ end
298
+ private :print_tree
299
+ end #}}}
300
+
301
+ class Traces < Array #{{{
302
+ def initialize_copy(other)
303
+ super
304
+ self.map!{ |t| t.dup }
305
+ end
306
+
307
+ def remove(trcs)
308
+ trcs.each do |t|
309
+ self.delete(t)
310
+ end
311
+ end
312
+ def remove_by_endnode(enode)
313
+ self.delete_if do |t|
314
+ t[0] != enode
315
+ end
316
+ # self.delete_if do |t|
317
+ # t[0] == enode && t.length <= 2
318
+ # end
319
+ end
320
+
321
+ def empty!
322
+ self.delete_if{true}
323
+ end
324
+
325
+ def remove_empty
326
+ self.delete_if{|t| t.empty? }
327
+ end
328
+
329
+ def first_node
330
+ self.first.first
331
+ end
332
+ def second_nodes
333
+ self.map { |t| t.length > 1 ? t[1] : t[0] }
334
+ end
335
+
336
+ def shortest
337
+ self.min_by{|e|e.length}
338
+ end
339
+
340
+ def legend(nid=true)
341
+ ret = "Legend:\n"
342
+ a = self.flatten.uniq
343
+ a.each {|n| ret << " " + (nid ? n.niceid.to_s : n.id.to_s) + ' ' + n.type.to_s + ' ' + n.label.to_s + "\n" }
344
+ ret
345
+ end
346
+
347
+ def to_s(nid = true)
348
+ "TRACES: " + self.collect { |t| t.empty? ? '∅' : t.collect{|n| ("%2d" % (nid ? n.niceid : n.id.to_i)) + "(i#{n.incoming},o#{n.outgoing})" }.join(' → ') }.join("\n ")
349
+ end
350
+
351
+ def shift_all
352
+ self.each{ |tr| tr.shift }
353
+ end
354
+ def pop_all(what=nil)
355
+ if what.nil?
356
+ self.each{ |tr| tr.pop }
357
+ else
358
+ self.each{ |tr| tr.pop if tr.last == what }
359
+ end
360
+ end
361
+
362
+ def finished?
363
+ self.reduce(0){|sum,t| sum += t.length} == 0
364
+ end
365
+
366
+ def same_first
367
+ (n = self.map{|t| t.first }.uniq).length == 1 ? n.first : nil
368
+ end
369
+
370
+ def incoming(node)
371
+ tcount = 1
372
+ self.each do |t|
373
+ break if t.length == 1
374
+ tcount += 1 if t.last == node
375
+ end
376
+ tcount
377
+ end
378
+
379
+ def include_in_all?(e)
380
+ num = 0
381
+ self.each{|n| num += 1 if n.include?(e)}
382
+ num == self.length
383
+ end
384
+
385
+ # first and last the same in all traces
386
+ def all_loops?
387
+ num = 0
388
+ self.each{|n| num += 1 if n.first == n.last }
389
+ num == self.length
390
+ end
391
+ # find all loops. Loops need to have the same second to last
392
+ def all_front?
393
+ lo = Traces.new self.find_all{ |t| t.first == t.last }
394
+ lo.uniq!
395
+ num = 0
396
+ search = lo.first[-2]
397
+ self.each{|n| num += 1 if n.include?(search) }
398
+ num == self.length
399
+ end
400
+
401
+ # second to last the same as in all traces
402
+ # second to last because last must be the same as current
403
+ def all_tail?
404
+ num = 0
405
+ search = self.first[-2]
406
+ self.each{|n| num += 1 if n[-2] == search }
407
+ num == self.length
408
+ end
409
+
410
+ def add_breaks(context,front=true)
411
+ trueloops = self.find_all{ |t| t.last == t.first }.length
412
+ tb = Break.new(context)
413
+ if trueloops == self.length
414
+ self << (front ? [nil,tb] : [tb,nil])
415
+ else
416
+ self.each do |t|
417
+ t << tb unless t.last == t.first ### an explicit break
418
+ end
419
+ end
420
+ end
421
+
422
+ def loops_only
423
+ lo = Traces.new self.find_all{ |t| t.first == t.last }
424
+ lo.uniq!
425
+ lo
426
+ end
427
+ def loops_and_partial_loops
428
+ lo = Traces.new self.find_all{ |t| t.first == t.last }
429
+ self.each do |t|
430
+ lo << t if lo.second_nodes.include?(t[1])
431
+ end
432
+ lo.uniq!
433
+ lo
434
+ end
435
+
436
+ def eliminate_front(loops)
437
+ ### find nested loops
438
+ self.each_with_index do |t,i|
439
+ maxcut = 0
440
+ ### find out which common parts the traces share with theloops
441
+ loops.each do |l|
442
+ maxcut.upto(l.length) do |i|
443
+ maxcut = i if t[0...i] == l[0...i]
444
+ end
445
+ end
446
+ ### in case of nested loop (common part occurs at end of loop), include the whole
447
+ 0.upto (maxcut-1) do |j|
448
+ if self[i][j] == self[i].last
449
+ loops << self[i].shift(self[i].length)
450
+ end
451
+ end
452
+ end
453
+ loops.uniq!
454
+ loops.remove_empty
455
+ self.remove_empty
456
+
457
+ ### cut from non-nested loops
458
+ self.each_with_index do |t,i|
459
+ maxcut = 0
460
+ ### find out which common parts the traces share with theloops
461
+ loops.each do |l|
462
+ maxcut.upto(l.length) do |i|
463
+ maxcut = i if t[0...i] == l[0...i]
464
+ end
465
+ end
466
+ self[i].shift(maxcut)
467
+ end
468
+ end
469
+ def eliminate(loops)
470
+ ### find nested loops
471
+ self.each_with_index do |t,i|
472
+ maxcut = 0
473
+ ### find out which common parts the traces share with theloops
474
+ loops.each do |l|
475
+ maxcut.upto(l.length) do |i|
476
+ maxcut = i if t[0...i] == l[0...i]
477
+ end
478
+ end
479
+ ### in case of nested loop (common part occurs at end of loop), include the whole
480
+ 0.upto (maxcut-1) do |j|
481
+ if self[i][j] == self[i].last
482
+ loops << self[i].shift(self[i].length)
483
+ end
484
+ end
485
+ end
486
+ loops.uniq!
487
+ loops.remove_empty
488
+ self.remove_empty
489
+
490
+ ### cut from non-nested loops
491
+ self.each_with_index do |t,i|
492
+ maxcut = 0
493
+ ### find out which common parts the traces share with theloops
494
+ loops.each do |l|
495
+ maxcut.upto(l.length) do |i|
496
+ maxcut = i if t[0...i] == l[0...i]
497
+ end
498
+ end
499
+ cutted = self[i].shift(maxcut)
500
+ loops << cutted if cutted.length > 1 ### if only the loop node is left, no need to attach
501
+ end
502
+ end
503
+
504
+ def extend
505
+ # find largest common
506
+ max = []
507
+ sh = self.shortest
508
+ sh = sh[0..-2] if sh.first == sh.last
509
+ sh.each_with_index do |e,i|
510
+ max << e if self.include_in_all?(e)
511
+ end
512
+ max = max.last
513
+
514
+ # if last is the largest common do nothing
515
+ # else append from last to largest common
516
+ self.each do |t|
517
+ unless t.last == max
518
+ last = t.last
519
+ if t.index(last) && t.index(max)
520
+ (t.index(last) + 1).upto(t.index(max)) do |i|
521
+ t << t[i]
522
+ end
523
+ end
524
+ end
525
+ end
526
+
527
+ max
528
+ end
529
+
530
+ def find_endnode
531
+ # supress loops
532
+ trcs = self.dup
533
+ # dangerous TODO
534
+ trcs.delete_if { |t| t.uniq.length < t.length }
535
+
536
+ # find common node (except loops)
537
+ enode = nil
538
+ unless trcs.empty?
539
+ trcs.first.each do |n|
540
+ if trcs.include_in_all?(n)
541
+ enode = n
542
+ break
543
+ end
544
+ end
545
+ end
546
+ enode
547
+ end
548
+
549
+ def segment_by(endnode)
550
+ # cut shit until common node, return the shit you cut away
551
+ tracesgroup = self.group_by{|t| t.first}.map do |k,trace|
552
+ coltrace = trace.map do |t|
553
+ # slice upto common node, collect the sliced away part
554
+ len = t.index(endnode)
555
+ if len
556
+ cut = t.slice!(0...len)
557
+ cut << t.first
558
+ else # if endnode is nil, then return the whole
559
+ t
560
+ end
561
+ end.uniq
562
+ Traces.new(coltrace)
563
+ end
564
+ [tracesgroup,endnode]
565
+ end
566
+ end #}}}
567
+
568
+ end
569
+
570
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # This file is part of CPEE-TRANSFORMATION.
4
+ #
5
+ # CPEE-TRANSFORMATION is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # CPEE-TRANSFORMATION is distributed in the hope that it will be useful, but
11
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with CPEE-TRANSFORMATION (file COPYING in the main directory). If not,
17
+ # see <http://www.gnu.org/licenses/>.
18
+
19
+ module CPEE
20
+
21
+ module Transformation
22
+
23
+ module Target
24
+
25
+ class Default
26
+ def initialize(tree)
27
+ @tree = tree
28
+ end
29
+
30
+ def generate_in_list(list,res)
31
+ list.each do |e|
32
+ nam = e.class.name.gsub(/\w+:+/,'')
33
+ res = send("print_#{nam}".to_sym,e,res) # always save last node
34
+ end
35
+ res
36
+ end
37
+
38
+ def generate_after_list(list,res)
39
+ post = []
40
+ list.each do |e|
41
+ nam = e.class.name.gsub(/\w+:+/,'')
42
+ post += send("print_#{nam}".to_sym,e,res)
43
+ end
44
+ post.compact!
45
+ post.each do |pair|
46
+ ltext, node = pair
47
+ res << ltext
48
+ generate_after_list(node,res)
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end