xmimodel 0.1.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.
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