xmimodel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/xmimodel.rb ADDED
@@ -0,0 +1,205 @@
1
+ # encoding: utf-8
2
+
3
+ require File.join(File.dirname(__FILE__), 'xmimodel/package.rb')
4
+ require File.join(File.dirname(__FILE__), 'xmimodel/generalization.rb')
5
+ require File.join(File.dirname(__FILE__), 'xmimodel/xmihelper.rb')
6
+
7
+ ##
8
+ # A helper class for working with XMI Models.
9
+ class XmiModel
10
+
11
+ # @return [Nokogiri::XML::Document]
12
+ attr_reader :document
13
+
14
+ # @return [String] The contents of the tag 'XMI.header/XMI.documentation/XMI.exporter'.
15
+ attr_reader :exporter
16
+
17
+ # @return [String] The contents of the tag 'XMI.header/XMI.documentation/XMI.exporterVersion'.
18
+ attr_reader :exporter_version
19
+
20
+ # @return [String] The value of property xmi.version of the tag 'XMI.header/XMI.metamodel'.
21
+ attr_reader :metamodel_version
22
+
23
+ # @return [Array<Generalization>] All model generalizations.
24
+ attr_reader :generalizations
25
+
26
+ # @return [Array<Association>] All model associations.
27
+ attr_reader :associations
28
+
29
+ ##
30
+ # Constructor.
31
+ #
32
+ # @param [String, #read] Path of model.
33
+ def initialize(model_file_name)
34
+
35
+ # Obtem a tag 'XMI.content' que contém todos os objetos que serão tratados
36
+ f = File.open(model_file_name)
37
+ doc = Nokogiri::XML(f)
38
+ @document = doc
39
+ xmi_content = doc.at_xpath("./XMI/XMI.content")
40
+ f.close
41
+
42
+ # Header
43
+ @exporter = XmiHelper.exporter(doc)
44
+ @exporter_version = XmiHelper.exporter_version(doc)
45
+ @metamodel_version = XmiHelper.metamodel_version(doc)
46
+
47
+ # Constrói vetor de pacotes
48
+ @packages = Array.new
49
+ XmiHelper.packages(xmi_content).each do |uml_package|
50
+ if ! (uml_package.attribute('name').nil? ||
51
+ uml_package.attribute('name').to_s.empty? ||
52
+ uml_package.attribute('name').to_s.strip == "Component View" ||
53
+ uml_package.attribute('name').to_s.strip == "Data types")
54
+ p = Package.new(uml_package, nil)
55
+ @packages << p
56
+ end
57
+ end
58
+
59
+ # Constrói vetor de heranças
60
+ @generalizations = Array.new
61
+ XmiHelper.all_generalizations(xmi_content).each do |xml|
62
+ g = Generalization.new(xml, self)
63
+
64
+ g.child_obj.parent = g.parent_obj unless g.child_obj.nil?
65
+ g.parent_obj.children << g.child_obj unless g.parent_obj.nil?
66
+
67
+ #puts "#{g.child_obj.full_name} - #{g.parent_obj.full_name}"
68
+ @generalizations << g
69
+ end
70
+
71
+ @associations = Array.new
72
+ XmiHelper.all_associations(xmi_content).each do |xml|
73
+ @associations << Association.new(xml, self)
74
+ end
75
+
76
+ true
77
+ end
78
+
79
+ ##
80
+ # Get the object of type 'Clazz' by full name of class.
81
+ #
82
+ # @param [String, #read] Name of the class including package name.
83
+ # @return [Clazz]
84
+ def class_by_full_name(full_class_name)
85
+ raise ArgumentError.new("Parameter 'full_class_name' cannot be empty.") if full_class_name.nil? or full_class_name.empty?
86
+ clazz = classes.select{|c| c.full_name == full_class_name}
87
+
88
+ if !clazz.nil? && clazz.size > 0
89
+ clazz[0]
90
+ else
91
+ nil
92
+ end
93
+ end
94
+
95
+ ##
96
+ # Get the object of type 'Clazz' by id.
97
+ #
98
+ # @param [String, #read] Id of the class in model file.
99
+ # @return [Clazz]
100
+ def class_by_id(class_id)
101
+ raise ArgumentError.new("#{__method__}: 'class_id' cannot be empty.") if class_id.nil? or class_id.empty?
102
+ clazz = classes.select{|c| c.id == class_id}
103
+
104
+ if !clazz.nil? && clazz.size > 0
105
+ clazz[0]
106
+ else
107
+ nil
108
+ end
109
+ end
110
+
111
+ ##
112
+ # Get all model classes.
113
+ #
114
+ # @return [Array<Clazz>]
115
+ def classes
116
+ return @classes unless @classes.nil?
117
+ @classes = Array.new
118
+ packages.each do |p|
119
+ @classes.concat p.classes.sort
120
+ end
121
+ @classes
122
+ end
123
+
124
+ ##
125
+ # Get the object of type 'Package' by full name of package.
126
+ #
127
+ # @param [String, #read] Name of the package including sub packages name.
128
+ # @return [Package]
129
+ def package_by_full_name(full_package_name)
130
+ raise ArgumentError.new("Parameter 'full_package_name' cannot be empty.") if full_package_name.nil? or full_package_name.empty?
131
+ package = packages.select{|p| p.full_name == full_package_name}
132
+
133
+ if !package.nil? && package.size > 0
134
+ package[0]
135
+ else
136
+ nil
137
+ end
138
+ end
139
+
140
+ ##
141
+ # Get all model packages.
142
+ #
143
+ # @return [Array<Package>]
144
+ def packages
145
+ return @all_packages unless @all_packages.nil?
146
+ @all_packages = Array.new
147
+
148
+ add_package(@packages)
149
+
150
+ @all_packages.sort!
151
+ @all_packages
152
+ end
153
+
154
+ ##
155
+ # Get the object of type 'State' by id.
156
+ #
157
+ # @param [String, #read] Id of the state in model file.
158
+ # @return [ActionState, FinalState, PseudoState]
159
+ def state_by_id(id)
160
+ raise ArgumentError.new("Parameter 'id' cannot be empty.") if id.nil? or id.empty?
161
+ objs = states.select{|obj| obj.id == id}
162
+ (!objs.nil? && objs.size > 0) ? objs[0] : nil
163
+ end
164
+
165
+
166
+ ##
167
+ # Get all model states.
168
+ #
169
+ # @return [Array<ActionState, FinalState, PseudoState>]
170
+ def states
171
+ return @states unless @states.nil?
172
+
173
+ @states = Array.new
174
+ packages.each do |p|
175
+ p.use_cases.each do |u|
176
+ u.activity_graphs.each do |a|
177
+ @states.concat a.action_states
178
+ @states.concat a.final_states
179
+ @states.concat a.pseudo_states
180
+ end
181
+ end
182
+ p.activity_graphs.each do |a|
183
+ @states.concat a.action_states
184
+ @states.concat a.final_states
185
+ @states.concat a.pseudo_states
186
+ end
187
+ end
188
+ @states
189
+ end
190
+
191
+ def to_s
192
+ "'XmiModel #{exporter} #{exporter_version} [Packages: #{packages.size}, Classes: #{classes.size}]'"
193
+ end
194
+
195
+ private
196
+
197
+ def add_package(packages)
198
+ packages.each do |p|
199
+ #puts p.name
200
+ @all_packages << p
201
+ add_package(p.packages) unless p.packages.nil?
202
+ end
203
+ end
204
+
205
+ end
@@ -0,0 +1,17 @@
1
+ require 'xmimodel/state'
2
+
3
+ class ActionState < State
4
+
5
+ attr_reader :deferrable_event
6
+
7
+ def initialize(xml, activity_graph)
8
+ super(xml, activity_graph)
9
+ @deferrable_event = xml.attribute("deferrableEvent").to_s
10
+ true
11
+ end
12
+
13
+ def to_s
14
+ "ActionState"
15
+ end
16
+
17
+ end
@@ -0,0 +1,81 @@
1
+ require 'xmimodel/action_state'
2
+ require 'xmimodel/final_state'
3
+ require 'xmimodel/pseudo_state'
4
+ require 'xmimodel/transition'
5
+
6
+ ##
7
+ # In umbrelo ActivityGraph is not represented by tag 'UML:ActivityGraph'.
8
+ # It's represented by tag diagram inside of XMI.extension.
9
+ #
10
+ #
11
+ class ActivityGraph
12
+
13
+ attr_reader :xml
14
+
15
+ attr_reader :id
16
+ attr_reader :name
17
+
18
+ attr_reader :pseudo_states
19
+ attr_reader :action_states
20
+ attr_reader :final_states
21
+ attr_reader :transitions
22
+
23
+ def initialize(xml, parent)
24
+ @xml = xml
25
+ @use_case = parent.parent
26
+
27
+ @id = xml.attribute("xmi.id").to_s
28
+ @name = xml.attribute("name").to_s
29
+
30
+ @pseudo_states = Array.new
31
+ XmiHelper.pseudo_states(xml).each do |uml|
32
+ pseudo_state = PseudoState.new(uml, self)
33
+ @pseudo_states << pseudo_state
34
+ end
35
+
36
+ @action_states = Array.new
37
+ XmiHelper.action_states(xml).each do |uml|
38
+ action_state = ActionState.new(uml, self)
39
+ @action_states << action_state
40
+ end
41
+
42
+ @final_states = Array.new
43
+ XmiHelper.final_states(xml).each do |uml|
44
+ final_state = FinalState.new(uml, self)
45
+ @final_states << final_state
46
+ end
47
+
48
+ @transitions = Array.new
49
+ XmiHelper.transitions(xml).each do |uml|
50
+ transition = Transition.new(uml, self)
51
+ @transitions << transition
52
+ end
53
+ end
54
+
55
+ def full_name
56
+ "#{@use_case.full_name}::#{@name}"
57
+ end
58
+
59
+ def to_s
60
+ "ActivityGraph[#{full_name}]"
61
+ end
62
+
63
+ def state_by_name(name_state, state_name)
64
+ case name_state
65
+ when "PseudoState"
66
+ state = @pseudo_states.select{|obj| obj.name == state_name}
67
+ when "ActionState"
68
+ state = @action_states.select{|obj| obj.name == state_name}
69
+ when "FinalState"
70
+ state = @final_states.select{|obj| obj.name == state_name}
71
+ end
72
+ return state[0] if !state.nil? && state.size > 0
73
+ nil
74
+ end
75
+
76
+ def transition_by_source_target_ids(source, target)
77
+ objs = @transitions.select{|obj| obj.source == source && obj.target == target}
78
+ (!objs.nil? && objs.size > 0) ? objs[0] : nil
79
+ end
80
+
81
+ end
@@ -0,0 +1,26 @@
1
+
2
+ class Association
3
+
4
+ attr_reader :xml
5
+ attr_reader :parent
6
+
7
+ attr_reader :id
8
+ attr_reader :name
9
+
10
+ # TODO Build AssociationEnd class
11
+ def initialize(xml, parent)
12
+ @xml = xml
13
+ @parent = parent
14
+
15
+ @id = xml.attribute("xmi.id").to_s
16
+ @name = xml.attribute("name").to_s.strip
17
+
18
+ #association_end_a
19
+ #association_end_b
20
+ end
21
+
22
+ def to_s
23
+ "Association[#{@name}]"
24
+ end
25
+
26
+ end
@@ -0,0 +1,76 @@
1
+ require 'xmimodel/stereotype'
2
+ require 'xmimodel/tagged_value'
3
+
4
+ class Attribute
5
+
6
+ attr_reader :xml
7
+
8
+ attr_reader :id
9
+ attr_reader :name
10
+ attr_reader :type
11
+ attr_reader :visibility
12
+ attr_reader :initial_value
13
+ attr_reader :multiplicity_range
14
+
15
+ attr_reader :clazz
16
+
17
+ attr_reader :stereotypes
18
+ attr_reader :tagged_values
19
+
20
+ def initialize(xml, clazz)
21
+ @xml = xml
22
+ @clazz = clazz
23
+
24
+ @id = xml.attribute("xmi:id").to_s
25
+ @name = xml.attribute("name").to_s.strip
26
+ @visibility = xml.attribute("visibility").to_s
27
+ @visibility = "private" if @visibility == ""
28
+
29
+ @type = XmiHelper.attribute_type_name(xml)
30
+
31
+ @initial_value = XmiHelper.attribute_initial_value(xml)
32
+ @multiplicity_range = XmiHelper.multiplicity_range(xml)
33
+
34
+ @stereotypes = Array.new
35
+ XmiHelper.stereotypes(xml).each do |uml_stereotype|
36
+ stereotype = Stereotype.new(uml_stereotype, self)
37
+ @stereotypes << stereotype
38
+ end
39
+
40
+ @tagged_values = Array.new
41
+ XmiHelper.tagged_values(xml).each do |uml_tagged_value|
42
+ tagged_value = TaggedValue.new(uml_tagged_value, self)
43
+ @tagged_values << tagged_value
44
+ end
45
+ end
46
+
47
+ def full_name
48
+ "#{@clazz.full_name}::#{@name}"
49
+ end
50
+
51
+ def stereotype_by_name(name)
52
+ stereotype = @stereotypes.select{|s| s.name == name}
53
+ return stereotype[0] if !stereotype.nil? && stereotype.size > 0
54
+ nil
55
+ end
56
+
57
+ def tagged_value_by_name(tagged_value_name)
58
+ tagged_value = @tagged_values.select{|t| t.name == tagged_value_name}
59
+ return tagged_value[0] if !tagged_value.nil? && tagged_value.size > 0
60
+ nil
61
+ end
62
+
63
+ def ==(obj)
64
+ return false if obj.nil?
65
+ if String == obj.class
66
+ full_name == obj
67
+ else
68
+ full_name == obj.full_name
69
+ end
70
+ end
71
+
72
+ def to_s
73
+ "Attribute[#{full_name}]"
74
+ end
75
+
76
+ end
@@ -0,0 +1,123 @@
1
+ # encoding: utf-8
2
+
3
+ require 'xmimodel/attribute'
4
+ require 'xmimodel/stereotype'
5
+ require 'xmimodel/tagged_value'
6
+ require 'xmimodel/operation'
7
+
8
+ class Clazz
9
+
10
+ attr_reader :xml
11
+
12
+ attr_reader :id
13
+ attr_reader :name
14
+
15
+ # @return [String] Full Package name of class.
16
+ attr_reader :package
17
+
18
+ # @return [Array<Attribute>] Class attributes.
19
+ attr_reader :attributes
20
+
21
+ # @return [Array<String>] Class associations.
22
+ attr_reader :stereotypes
23
+
24
+ attr_reader :tagged_values
25
+ attr_reader :operations
26
+
27
+ attr_accessor :children
28
+ attr_accessor :parent
29
+
30
+ def initialize(xml, parent)
31
+ @xml = xml
32
+ @package = parent.parent
33
+
34
+ @id = xml.attribute("xmi.id").to_s
35
+ @name = xml.attribute("name").to_s.strip
36
+
37
+ @attributes = Array.new
38
+ XmiHelper.attributes(xml).each do |uml_attribute|
39
+ attribute = Attribute.new(uml_attribute, self)
40
+ @attributes << attribute
41
+ end
42
+
43
+ @stereotypes = Array.new
44
+ stereotype_id = xml.attribute("stereotype").to_s
45
+ if !stereotype_id.empty?
46
+ stereotype = XmiHelper.stereotype_by_id(xml, stereotype_id)
47
+ stereotype = Stereotype.new(stereotype, self)
48
+ @stereotypes << stereotype
49
+ end
50
+ XmiHelper.stereotypes(xml).each do |uml_stereotype|
51
+ stereotype = Stereotype.new(uml_stereotype, self)
52
+ @stereotypes << stereotype
53
+ end
54
+
55
+ @tagged_values = Array.new
56
+ XmiHelper.tagged_values(xml).each do |uml_tagged_value|
57
+ tagged_value = TaggedValue.new(uml_tagged_value, self)
58
+ @tagged_values << tagged_value
59
+ end
60
+
61
+ @operations = Array.new
62
+ XmiHelper.operations(xml).each do |uml_operation|
63
+ tagged_value = Operation.new(uml_operation, self)
64
+ @operations << tagged_value
65
+ end
66
+
67
+ # Será povoado quando tratar dos objetos do tipo Genezalization
68
+ @children = Array.new
69
+
70
+ end
71
+
72
+ def attribute_by_id(attribute_id)
73
+ attribute = @attributes.select{|obj| obj.id == attribute_id}
74
+ return attribute[0] if !attribute.nil? && attribute.size > 0
75
+ nil
76
+ end
77
+
78
+ def attribute_by_name(attribute_name)
79
+ attribute = @attributes.select{|obj| obj.name == attribute_name}
80
+ return attribute[0] if !attribute.nil? && attribute.size > 0
81
+ nil
82
+ end
83
+
84
+ def operation_by_name(operation_name)
85
+ operation = @operations.select{|obj| obj.name == operation_name}
86
+ return operation[0] if !operation.nil? && operation.size > 0
87
+ nil
88
+ end
89
+
90
+ def stereotype_by_name(name)
91
+ stereotype = @stereotypes.select{|obj| obj == name}
92
+ return stereotype[0] if !stereotype.nil? && stereotype.size > 0
93
+ nil
94
+ end
95
+
96
+ def tagged_value_by_name(tagged_value_name)
97
+ tagged_value = @tagged_values.select{|obj| obj.name == tagged_value_name}
98
+ return tagged_value[0] if !tagged_value.nil? && tagged_value.size > 0
99
+ nil
100
+ end
101
+
102
+ def <=>(obj)
103
+ full_name <=> obj.full_name
104
+ end
105
+
106
+ def ==(obj)
107
+ return false if obj.nil?
108
+ if String == obj.class
109
+ full_name == obj
110
+ else
111
+ full_name == obj.full_name
112
+ end
113
+ end
114
+
115
+ def full_name
116
+ "#{package.full_name}.#{name}"
117
+ end
118
+
119
+ def to_s
120
+ "Clazz[#{full_name}]"
121
+ end
122
+
123
+ end