xmimerge 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/xmimerge +61 -0
- data/lib/xmimerge.rb +53 -0
- data/lib/xmimerge/app.rb +47 -0
- data/lib/xmimerge/commands_file.rb +46 -0
- data/lib/xmimerge/merge.rb +40 -0
- data/lib/xmimerge/merge_action_states.rb +10 -0
- data/lib/xmimerge/merge_activity_graphs.rb +91 -0
- data/lib/xmimerge/merge_associations.rb +116 -0
- data/lib/xmimerge/merge_associations_end.rb +59 -0
- data/lib/xmimerge/merge_attributes.rb +125 -0
- data/lib/xmimerge/merge_call_events.rb +39 -0
- data/lib/xmimerge/merge_classes.rb +122 -0
- data/lib/xmimerge/merge_final_states.rb +9 -0
- data/lib/xmimerge/merge_multiplicity.rb +35 -0
- data/lib/xmimerge/merge_operations.rb +83 -0
- data/lib/xmimerge/merge_packages.rb +81 -0
- data/lib/xmimerge/merge_parameters.rb +89 -0
- data/lib/xmimerge/merge_pseudo_states.rb +9 -0
- data/lib/xmimerge/merge_signal_events.rb +71 -0
- data/lib/xmimerge/merge_states.rb +81 -0
- data/lib/xmimerge/merge_stereotypes.rb +82 -0
- data/lib/xmimerge/merge_tagged_values.rb +75 -0
- data/lib/xmimerge/merge_transitions.rb +98 -0
- data/lib/xmimerge/merge_use_cases.rb +89 -0
- data/lib/xmimerge/util.rb +48 -0
- metadata +69 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 27825ef03fad6051aca157d64ef00ff1330d9d7d
|
4
|
+
data.tar.gz: c236b9332c2a3363d8bdcc68563a3793caa93bdc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2c5468288a6dacbab623804f219b075d6a760bfa31ae3d9cfc496009084015ef825064e2f3057f029738a2fa660deefb91646384dcaa750d90a1edddf2eea2bb
|
7
|
+
data.tar.gz: d56443396c3804c93741520618ff1ed2281225cdb81e4a5b1c660e5f88fd52429441d46912aa219f4a46f2bcf32b846079558b967d03a08c59f87caa21a90970
|
data/bin/xmimerge
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'xmimerge'
|
5
|
+
require 'thor'
|
6
|
+
require File.join(File.dirname(__FILE__), '../lib/xmimerge/util.rb')
|
7
|
+
|
8
|
+
class XmiMergeRunner < Thor
|
9
|
+
|
10
|
+
desc 'c [OPTIONS]', "check"
|
11
|
+
method_option :from, :type => :string, :required => true, :aliases => '-f', :banner => "Path of the source model."
|
12
|
+
method_option :to, :type => :string, :required => true, :aliases => '-t', :banner => "Path of the target model."
|
13
|
+
def c
|
14
|
+
begin
|
15
|
+
inicio = Time.now
|
16
|
+
@merge = XmiMerge.new(options[:from], options[:to])
|
17
|
+
@merge.check
|
18
|
+
App.logger.info "Total Time: #{diff_time(inicio, Time.now)}"
|
19
|
+
rescue Exception => e
|
20
|
+
App.logger.error e.message
|
21
|
+
puts e.backtrace.join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'm [OPTIONS]', "merge"
|
26
|
+
method_option :from, :type => :string, :required => true, :aliases => '-f', :banner => "Path of the source model."
|
27
|
+
method_option :to, :type => :string, :required => true, :aliases => '-t', :banner => "Path of the target model."
|
28
|
+
method_option :output, :type => :string, :required => false, :aliases => '-o', :banner => "Output path."
|
29
|
+
def m
|
30
|
+
begin
|
31
|
+
inicio = Time.now
|
32
|
+
@merge = XmiMerge.new(options[:from], options[:to])
|
33
|
+
@merge.merge
|
34
|
+
if options[:output].nil?
|
35
|
+
@merge.save
|
36
|
+
else
|
37
|
+
@merge.save(options[:output])
|
38
|
+
end
|
39
|
+
App.logger.info "Total Time: #{diff_time(inicio, Time.now)}"
|
40
|
+
rescue Exception => e
|
41
|
+
App.logger.error e.message
|
42
|
+
puts e.backtrace.join("\n")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def diff_time(start_time, end_time = Time.now)
|
48
|
+
diff = (end_time - start_time)
|
49
|
+
s = (diff % 60).to_i
|
50
|
+
m = (diff / 60).to_i
|
51
|
+
h = (m / 60).to_i
|
52
|
+
|
53
|
+
if s > 0
|
54
|
+
"#{(h < 10) ? '0' + h.to_s : h}:#{(m < 10) ? '0' + m.to_s : m}:#{(s < 10) ? '0' + s.to_s : s}"
|
55
|
+
else
|
56
|
+
format("%.5f", diff) + " miliseconds."
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
App.logger.info App.specification.summary + " " + App.specification.version.to_s
|
61
|
+
XmiMergeRunner.start
|
data/lib/xmimerge.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'xmimodel'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require File.join(File.dirname(__FILE__), 'xmimerge/app.rb')
|
5
|
+
require File.join(File.dirname(__FILE__), 'xmimerge/merge_packages.rb')
|
6
|
+
|
7
|
+
class XmiMerge
|
8
|
+
|
9
|
+
def initialize(file_name_from, file_name_to)
|
10
|
+
|
11
|
+
@log = App.logger
|
12
|
+
|
13
|
+
start = Time.now
|
14
|
+
App.logger.info "Loading source model..."
|
15
|
+
@from = XmiModel.new file_name_from
|
16
|
+
App.logger.info "Source model loaded (#{Util.diff_time(start)})."
|
17
|
+
|
18
|
+
start = Time.now
|
19
|
+
App.logger.info "Loading target model..."
|
20
|
+
@to = XmiModel.new file_name_to
|
21
|
+
App.logger.info "Target model loaded (#{Util.diff_time(start)})."
|
22
|
+
|
23
|
+
@commands = App.instance.commands_file
|
24
|
+
|
25
|
+
App.instance.from = @from
|
26
|
+
App.instance.to = @to
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def check
|
31
|
+
@only_check = true
|
32
|
+
verify
|
33
|
+
@log.info("#{@commands.buffer_size} change(s).");
|
34
|
+
@commands.save_buffer
|
35
|
+
end
|
36
|
+
|
37
|
+
def merge
|
38
|
+
@only_check = false
|
39
|
+
@commands.load_commands
|
40
|
+
verify
|
41
|
+
end
|
42
|
+
|
43
|
+
def verify
|
44
|
+
merge = MergePackages.new
|
45
|
+
@only_check ? merge.check : merge.merge
|
46
|
+
end
|
47
|
+
|
48
|
+
def save(path=@to.model_file_name)
|
49
|
+
@to.save(path)
|
50
|
+
App.logger.info "#{path} saved."
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/lib/xmimerge/app.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'commands_file.rb')
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
class App
|
5
|
+
|
6
|
+
attr_accessor :from
|
7
|
+
attr_accessor :to
|
8
|
+
|
9
|
+
@@instance = App.new
|
10
|
+
def self.instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def commands_file
|
15
|
+
@commands_file = CommandsFile.new if @commands_file.nil?
|
16
|
+
@commands_file
|
17
|
+
end
|
18
|
+
|
19
|
+
@@log = nil
|
20
|
+
def self.logger
|
21
|
+
return @@log unless @@log.nil?
|
22
|
+
@@log = Logger.new($stdout)
|
23
|
+
@@log.level = Logger::INFO
|
24
|
+
@@log.formatter = proc do |severity, datetime, progname, msg|
|
25
|
+
"[#{severity}] - #{msg}\n"
|
26
|
+
end
|
27
|
+
@@log
|
28
|
+
end
|
29
|
+
|
30
|
+
@@spec = nil
|
31
|
+
def self.specification
|
32
|
+
return @@spec unless @@spec.nil?
|
33
|
+
@@spec = Gem::Specification.new do |s|
|
34
|
+
s.name = 'xmimerge'
|
35
|
+
s.version = '0.0.1'
|
36
|
+
s.date = '2013-08-28'
|
37
|
+
s.summary = "Xmi Merge"
|
38
|
+
s.description = "A helper gem for merge XMI files"
|
39
|
+
s.authors = ["Marcus Siqueira"]
|
40
|
+
s.email = 'marvinsiq@gmail.com'
|
41
|
+
s.files = FileList['lib/*.rb', 'lib/**/*.rb'].to_a
|
42
|
+
s.homepage = 'https://github.com/marvinsiq/xmimerge'
|
43
|
+
s.executables << 'xmimerge'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
class CommandsFile
|
3
|
+
|
4
|
+
COMMAND_FILE_NAME = "commands.merge"
|
5
|
+
|
6
|
+
attr_reader :commands
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@buffer = Array.new
|
10
|
+
@log = App.logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_commands
|
14
|
+
@log.info "Loading command file '#{COMMAND_FILE_NAME}'..."
|
15
|
+
@commands = File.readlines(COMMAND_FILE_NAME, :encoding => "UTF-8")
|
16
|
+
@log.info "Command file loaded."
|
17
|
+
#@log.info "#{@commands.size} command(s)."
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_command_to_buffer(command)
|
21
|
+
@log.debug "Command added to the buffer: \"#{command}\"."
|
22
|
+
@buffer << command
|
23
|
+
end
|
24
|
+
|
25
|
+
def has_command?(command)
|
26
|
+
has = @commands.select {|c| c.include? command}
|
27
|
+
!has.empty?
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_if_is_last_command(command)
|
31
|
+
@buffer.delete_at(@buffer.size-1) if @buffer.last == command
|
32
|
+
end
|
33
|
+
|
34
|
+
def buffer_size
|
35
|
+
@buffer.size
|
36
|
+
end
|
37
|
+
|
38
|
+
def save_buffer
|
39
|
+
@log.debug "Buffer saved."
|
40
|
+
f = File.new(COMMAND_FILE_NAME, "w")
|
41
|
+
f.write(@buffer.join("\n"))
|
42
|
+
@buffer = Array.new
|
43
|
+
f.close unless f.closed?
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
class Merge
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@app = App.instance
|
6
|
+
@from = @app.from
|
7
|
+
@to = @app.to
|
8
|
+
@log = App.logger
|
9
|
+
@commands = @app.commands_file
|
10
|
+
end
|
11
|
+
|
12
|
+
def check
|
13
|
+
#@log.debug "Check"
|
14
|
+
@only_check = true
|
15
|
+
verify
|
16
|
+
end
|
17
|
+
|
18
|
+
def merge
|
19
|
+
#@log.debug "Merge"
|
20
|
+
@only_check = false
|
21
|
+
verify
|
22
|
+
end
|
23
|
+
|
24
|
+
def check_change_propertie(method, from, to, name)
|
25
|
+
|
26
|
+
changes = Util.check_change_by_method(method, from, to)
|
27
|
+
|
28
|
+
if !changes.nil?
|
29
|
+
command = "\t* #{name} #{from.full_name} {'#{changes[0]}' --> '#{changes[1]}'}"
|
30
|
+
@commands.add_command_to_buffer(command)
|
31
|
+
unless @only_check
|
32
|
+
if @commands.has_command?(command)
|
33
|
+
@log.info "[OK] #{command}"
|
34
|
+
else
|
35
|
+
#@log.info "[NOT] #{command}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'merge.rb')
|
2
|
+
require File.join(File.dirname(__FILE__), 'merge_states.rb')
|
3
|
+
|
4
|
+
class MergeActionStates < MergeStates
|
5
|
+
|
6
|
+
def initialize(from_activity_graph, to_activity_graph)
|
7
|
+
super("ActionState", "action_states", from_activity_graph, to_activity_graph)
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'merge.rb')
|
2
|
+
require File.join(File.dirname(__FILE__), 'merge_action_states.rb')
|
3
|
+
require File.join(File.dirname(__FILE__), 'merge_final_states.rb')
|
4
|
+
require File.join(File.dirname(__FILE__), 'merge_pseudo_states.rb')
|
5
|
+
require File.join(File.dirname(__FILE__), 'merge_transitions.rb')
|
6
|
+
|
7
|
+
class MergeActivityGraphs < Merge
|
8
|
+
|
9
|
+
def initialize(from_use_case, to_use_case)
|
10
|
+
super()
|
11
|
+
@from_use_case = from_use_case
|
12
|
+
@to_use_case = to_use_case
|
13
|
+
end
|
14
|
+
|
15
|
+
def verify
|
16
|
+
|
17
|
+
@from_use_case.activity_graphs.each do |activity_graphs|
|
18
|
+
check_changes activity_graphs
|
19
|
+
end
|
20
|
+
|
21
|
+
check_removed
|
22
|
+
end
|
23
|
+
|
24
|
+
def check_changes(from_activity_graph)
|
25
|
+
|
26
|
+
@log.info("Checking Activity Graph #{from_activity_graph.full_name}")
|
27
|
+
|
28
|
+
to_activity_graph = @to_use_case.activity_graphs_by_name(from_activity_graph.name)
|
29
|
+
|
30
|
+
if to_activity_graph.nil?
|
31
|
+
new_obj to_activity_graph
|
32
|
+
else
|
33
|
+
check_existing(from_activity_graph, to_activity_graph)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def new_obj(from_activity_graph)
|
38
|
+
command = "+ ActivityGraph #{from_activity_graph.full_name}"
|
39
|
+
@commands.add_command_to_buffer(command)
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_existing(from_activity_graph, to_activity_graph)
|
43
|
+
|
44
|
+
@log.debug("Checking Existing Activity Graph: #{from_activity_graph.full_name}")
|
45
|
+
|
46
|
+
# ActionState
|
47
|
+
merge = MergeActionStates.new(from_activity_graph, to_activity_graph)
|
48
|
+
@only_check ? merge.check : merge.merge
|
49
|
+
|
50
|
+
# FinalState
|
51
|
+
merge = MergeFinalStates.new(from_activity_graph, to_activity_graph)
|
52
|
+
@only_check ? merge.check : merge.merge
|
53
|
+
|
54
|
+
# PseudoState
|
55
|
+
merge = MergePseudoStates.new(from_activity_graph, to_activity_graph)
|
56
|
+
@only_check ? merge.check : merge.merge
|
57
|
+
|
58
|
+
# Transition
|
59
|
+
merge = MergeTransitions.new(from_activity_graph, to_activity_graph)
|
60
|
+
@only_check ? merge.check : merge.merge
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_removed
|
64
|
+
|
65
|
+
@log.debug("Checking removed Activity Graph...")
|
66
|
+
|
67
|
+
@to_use_case.activity_graphs.each do |to_activity_graph|
|
68
|
+
|
69
|
+
ok = false
|
70
|
+
@from_use_case.activity_graphs.each do |from_activity_graph|
|
71
|
+
|
72
|
+
if from_activity_graph.name == to_activity_graph.name
|
73
|
+
ok = true
|
74
|
+
break
|
75
|
+
end
|
76
|
+
end
|
77
|
+
if !ok
|
78
|
+
@log.info("Activity Graph Removed: #{to_activity_graph.full_name}")
|
79
|
+
command = "- ActivityGraph #{to_activity_graph.full_name}"
|
80
|
+
@commands.add_command_to_buffer(command)
|
81
|
+
unless @only_check
|
82
|
+
if @commands.has_command?(command)
|
83
|
+
@log.info "[OK] #{command}"
|
84
|
+
else
|
85
|
+
#@log.info "[NOT] #{command}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'merge.rb')
|
4
|
+
require File.join(File.dirname(__FILE__), 'util.rb')
|
5
|
+
require File.join(File.dirname(__FILE__), 'merge_stereotypes.rb')
|
6
|
+
require File.join(File.dirname(__FILE__), 'merge_tagged_values.rb')
|
7
|
+
require File.join(File.dirname(__FILE__), 'merge_multiplicity.rb')
|
8
|
+
|
9
|
+
class MergeAssociations < Merge
|
10
|
+
|
11
|
+
def initialize(from_class, to_class)
|
12
|
+
super()
|
13
|
+
@from_class = from_class
|
14
|
+
@to_class = to_class
|
15
|
+
end
|
16
|
+
|
17
|
+
def verify
|
18
|
+
|
19
|
+
@from_class.associations.each do |from_association|
|
20
|
+
#check_changes(from_association)
|
21
|
+
end
|
22
|
+
|
23
|
+
#check_removed
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param [Association, #read] from_association.
|
27
|
+
def check_changes(from_association)
|
28
|
+
|
29
|
+
@log.debug("Checking association: #{from_association.full_name}")
|
30
|
+
|
31
|
+
# Localiza a associação no modelo destino
|
32
|
+
to_association = @to_class.xml_root.association_by_id(from_association.id)
|
33
|
+
|
34
|
+
if to_association.nil?
|
35
|
+
# Se não encontrou é poque é um nova associação
|
36
|
+
new_association from_association
|
37
|
+
else
|
38
|
+
# Associação já existe, verifica se houve alterações
|
39
|
+
check_existing_association(from_association, to_association)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def check_removed
|
44
|
+
@to_class.xml_root.associations.each do |to_association|
|
45
|
+
|
46
|
+
ok = false
|
47
|
+
@from_class.xml_root.associations.each do |from_association|
|
48
|
+
|
49
|
+
if from_association == to_association
|
50
|
+
ok = true
|
51
|
+
break
|
52
|
+
end
|
53
|
+
end
|
54
|
+
if !ok
|
55
|
+
command = "\t- Association #{to_association.full_name}"
|
56
|
+
@commands.add_command_to_buffer(command)
|
57
|
+
unless @only_check
|
58
|
+
if @commands.has_command?(command)
|
59
|
+
@log.info "[OK] #{command}"
|
60
|
+
else
|
61
|
+
#@log.info "[NOT] #{command}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param [Association, #read] from_association.
|
69
|
+
def new_association(from_association)
|
70
|
+
@log.debug("New Attribute")
|
71
|
+
|
72
|
+
command = "\t+ Association #{from_association.full_name}"
|
73
|
+
@commands.add_command_to_buffer(command)
|
74
|
+
|
75
|
+
unless @only_check
|
76
|
+
if @commands.has_command?(command)
|
77
|
+
@log.info "[OK] #{command}"
|
78
|
+
else
|
79
|
+
@log.info "[NOT] #{command}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def check_existing_association(from_association, to_association)
|
85
|
+
|
86
|
+
# Visibility
|
87
|
+
check_change_propertie("name", from_association, to_association, "AssociationName")
|
88
|
+
|
89
|
+
# Stereotypes
|
90
|
+
merge = MergeStereotypes.new("Association", from_association, to_association)
|
91
|
+
@only_check ? merge.check : merge.merge
|
92
|
+
|
93
|
+
# TaggedValues
|
94
|
+
t = MergeTaggedValues.new("Association", from_association, to_association)
|
95
|
+
@only_check ? t.check : t.merge
|
96
|
+
|
97
|
+
|
98
|
+
if from_association.end_a != to_association.end_a
|
99
|
+
command = "\t* AssociationEndA #{from_association.end_a.name} {'#{from_association.end_a.participant.full_name}' --> '#{to_association.end_a.participant.full_name}'}"
|
100
|
+
@commands.add_command_to_buffer(command)
|
101
|
+
end
|
102
|
+
|
103
|
+
if from_association.end_b != to_association.end_b
|
104
|
+
command = "\t* AssociationEndB #{from_association.end_b.name} {'#{from_association.end_b.participant.full_name}' --> '#{to_association.end_b.participant.full_name}'}"
|
105
|
+
@commands.add_command_to_buffer(command)
|
106
|
+
end
|
107
|
+
|
108
|
+
# AssociationEnd
|
109
|
+
end_a = MergeAssociationEnd.new("AssociationEndA", from_association.end_a, to_association.end_a)
|
110
|
+
@only_check ? end_a.check : end_a.merge
|
111
|
+
|
112
|
+
end_b = MergeAssociationEnd.new("AssociationEndB", from_association.end_b, to_association.end_b)
|
113
|
+
@only_check ? end_b.check : end_b.merge
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|