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 +205 -0
- data/lib/xmimodel/action_state.rb +17 -0
- data/lib/xmimodel/activity_graph.rb +81 -0
- data/lib/xmimodel/association.rb +26 -0
- data/lib/xmimodel/attribute.rb +76 -0
- data/lib/xmimodel/clazz.rb +123 -0
- data/lib/xmimodel/data_type.rb +21 -0
- data/lib/xmimodel/final_state.rb +13 -0
- data/lib/xmimodel/generalization.rb +36 -0
- data/lib/xmimodel/namespace.rb +373 -0
- data/lib/xmimodel/operation.rb +51 -0
- data/lib/xmimodel/package.rb +84 -0
- data/lib/xmimodel/parameter.rb +55 -0
- data/lib/xmimodel/pseudo_state.rb +16 -0
- data/lib/xmimodel/signal_event.rb +41 -0
- data/lib/xmimodel/state.rb +66 -0
- data/lib/xmimodel/stereotype.rb +52 -0
- data/lib/xmimodel/tagged_value.rb +41 -0
- data/lib/xmimodel/transition.rb +64 -0
- data/lib/xmimodel/use_case.rb +85 -0
- data/lib/xmimodel/xmihelper.rb +683 -0
- metadata +66 -0
@@ -0,0 +1,683 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
##
|
5
|
+
# A helper for working with XMI files.
|
6
|
+
#
|
7
|
+
# Author:: Marcus Siqueira (mailto:marvinsiq@gmail.com)
|
8
|
+
# License:: Distributes under the same terms as Ruby
|
9
|
+
class XmiHelper
|
10
|
+
|
11
|
+
# Constructor.
|
12
|
+
def initialize
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Get all the Action State in the tag.
|
17
|
+
#
|
18
|
+
# Action State is a representation of an action on a Activity Graph.
|
19
|
+
#
|
20
|
+
# The parameter 'tag' needs be a Nokogiri::XML::Element of type 'UML:ActivityGraph'.
|
21
|
+
#
|
22
|
+
# Returns an array of objects Nokogiri::XML::Element of type 'UML:ActionState'.
|
23
|
+
#
|
24
|
+
# See also:
|
25
|
+
# * call_events
|
26
|
+
def self.action_states(tag)
|
27
|
+
raise ArgumentError.new("Parameter is not a UML:ActivityGraph.") if tag.nil? || tag.name != "ActivityGraph"
|
28
|
+
tag.xpath('./UML:StateMachine.top/UML:CompositeState/UML:CompositeState.subvertex/UML:ActionState')
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Get the Activity Graph by name.
|
33
|
+
#
|
34
|
+
# The parameter 'document' can be any Nokogiri::XML::Element of model.
|
35
|
+
#
|
36
|
+
# The parameter 'name' cannot be empty.
|
37
|
+
#
|
38
|
+
# Returns a object Nokogiri::XML::Element of type 'UML:ActivityGraph'.
|
39
|
+
def self.activity_graph_by_name(document, name)
|
40
|
+
tag_by_name(xmi_content(document), "UML:ActivityGraph", name)
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Get all the Activity Graphs in the tag.
|
45
|
+
#
|
46
|
+
# The parameter 'tag' can be any Nokogiri::XML::Element that contains the tag 'UML:Namespace.ownedElement'.
|
47
|
+
#
|
48
|
+
# Returns a object Nokogiri::XML::Element of type 'UML:ActivityGraph'.
|
49
|
+
def self.activity_graphs(tag)
|
50
|
+
namespace(tag).xpath('./UML:ActivityGraph')
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Get all the Associations in the model.
|
55
|
+
#
|
56
|
+
# The parameter 'tag' can be any Nokogiri::XML::Element of model.
|
57
|
+
#
|
58
|
+
# Returns an array of all objects Nokogiri::XML::Element of type 'UML:Association'.
|
59
|
+
def self.all_associations(tag)
|
60
|
+
xmi_content(tag).xpath("//UML:Association")
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Get all the Generalizations in the model.
|
65
|
+
#
|
66
|
+
# The parameter 'tag' can be any Nokogiri::XML::Element of model.
|
67
|
+
#
|
68
|
+
# Returns an array of all objects 'Nokogiri::XML::Element' of type 'UML:Generalization'.
|
69
|
+
def self.all_generalizations(tag)
|
70
|
+
xmi_content(tag).xpath('//UML:Namespace.ownedElement/UML:Generalization')
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Get all the Packages in the model.
|
75
|
+
#
|
76
|
+
# The parameter 'tag' can be any Nokogiri::XML::Element of model.
|
77
|
+
#
|
78
|
+
# Returns an array of all objects 'Nokogiri::XML::Element' of type 'UML:Package'.
|
79
|
+
def self.all_packages(tag)
|
80
|
+
xmi_content(tag).xpath('//UML:Namespace.ownedElement/UML:Package')
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Get all the Associations in the model.
|
85
|
+
#
|
86
|
+
# The parameter 'tag' can be any Nokogiri::XML::Element that contains the tag 'UML:Namespace.ownedElement'.
|
87
|
+
#
|
88
|
+
# Returns an array of objects 'Nokogiri::XML::Element' of type 'UML:Association'.
|
89
|
+
def self.associations(tag)
|
90
|
+
namespace(tag).xpath("./UML:Association")
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Get the Associations by id of the any participants of relationship.
|
95
|
+
#
|
96
|
+
# The parameter 'tag' can be any Nokogiri::XML::Element of model.
|
97
|
+
#
|
98
|
+
# Returns an array of objects 'Nokogiri::XML::Element' of type 'UML:Association'.
|
99
|
+
def self.associations_by_participant_id(tag, id)
|
100
|
+
|
101
|
+
associations = Array.new
|
102
|
+
|
103
|
+
xmi_content(tag).xpath('//UML:Association').each do |a|
|
104
|
+
|
105
|
+
a.xpath( "./UML:Association.connection/UML:AssociationEnd").each do |ae|
|
106
|
+
participant_id = participant_id_by_association_end(ae)
|
107
|
+
|
108
|
+
if (!participant_id.nil?) && participant_id.to_s.eql?(id.to_s) && !associations.include?(a)
|
109
|
+
associations << a
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
return associations
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Get the attributes of a class.
|
119
|
+
#
|
120
|
+
# Returns an array of objects 'Nokogiri::XML::Element' of type UML:Attribute
|
121
|
+
def self.attributes(uml_class)
|
122
|
+
uml_class.xpath('./UML:Classifier.feature/UML:Attribute')
|
123
|
+
end
|
124
|
+
|
125
|
+
#
|
126
|
+
# Get the attribute of a class by identification
|
127
|
+
#
|
128
|
+
# Returns a object 'Nokogiri::XML::Element' of type UML:Attribute
|
129
|
+
def self.attribute_by_id(document, id)
|
130
|
+
type = tag_by_id(document, 'UML:Attribute', id)
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Get the attribute of a class by name
|
135
|
+
#
|
136
|
+
# Returns a object 'Nokogiri::XML::Element' of type UML:Attribute
|
137
|
+
def self.attribute_by_name(uml_class, name)
|
138
|
+
tag_by_name(uml_class, "UML:Attribute", name)
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# Get the initial value of an attribute
|
143
|
+
#
|
144
|
+
# Returns a String with the value
|
145
|
+
def self.attribute_initial_value(uml_attribute)
|
146
|
+
raise ArgumentError.new("Parameter is not a UML:Attribute tag.") if uml_attribute.name != "Attribute"
|
147
|
+
uml_expression = uml_attribute.at_xpath('./UML:Attribute.initialValue/UML:Expression')
|
148
|
+
|
149
|
+
if uml_expression.nil?
|
150
|
+
return ''
|
151
|
+
else
|
152
|
+
return uml_expression.attribute('body').to_s.strip
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# Return a object 'Nokogiri::XML::Element' of type 'UML:Class' or 'UML:DataType' or a String
|
158
|
+
def self.attribute_type(uml_attribute)
|
159
|
+
raise ArgumentError.new("Parameter is not a 'UML:Attribute' tag.") if uml_attribute.name != "Attribute"
|
160
|
+
type = uml_attribute.attribute('type').to_s
|
161
|
+
# Se não possuir o atributo tipo, verifica se possui a tag abaixo com o tipo primitivo
|
162
|
+
if type.nil? || type.empty?
|
163
|
+
uml_type = uml_attribute.at_xpath('./UML:StructuralFeature.type/UML:Classifier/XMI.extension/referentPath')
|
164
|
+
type = uml_type.attribute('xmi.value').to_s unless uml_type.nil?
|
165
|
+
else
|
166
|
+
id = type
|
167
|
+
xmi_content = xmi_content(uml_attribute)
|
168
|
+
|
169
|
+
clazz = class_by_id(xmi_content, id)
|
170
|
+
return clazz unless clazz.nil?
|
171
|
+
|
172
|
+
enum = enumeration_by_id(xmi_content, id)
|
173
|
+
return enum unless enum.nil?
|
174
|
+
|
175
|
+
data_type = data_type(xmi_content, id)
|
176
|
+
return data_type unless data_type.nil?
|
177
|
+
end
|
178
|
+
type
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.attribute_type_name(uml_attribute)
|
182
|
+
type = attribute_type(uml_attribute)
|
183
|
+
return nil if type.nil?
|
184
|
+
return type if type.class.to_s.eql?("String")
|
185
|
+
if type.class.to_s.eql?("Nokogiri::XML::Element")
|
186
|
+
return type.attribute("name").to_s if type.name == "DataType"
|
187
|
+
return full_class_name(type) if type.name == "Class"
|
188
|
+
return full_enumeration_name(type) if type.name == "Enumeration"
|
189
|
+
end
|
190
|
+
nil
|
191
|
+
end
|
192
|
+
|
193
|
+
#
|
194
|
+
# Call Events are links between ActionStates (by deferrableEvent propertie) and Operations (methods of a class).
|
195
|
+
#
|
196
|
+
# Call Events are actions triggered by a state.
|
197
|
+
#
|
198
|
+
# See:
|
199
|
+
# * action_states
|
200
|
+
# * operations
|
201
|
+
# * signal_events
|
202
|
+
def self.call_events(tag)
|
203
|
+
namespace(tag).xpath("./UML:CallEvent")
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.class_by_full_name(document, full_name)
|
207
|
+
|
208
|
+
class_name = full_name.split(".").last
|
209
|
+
package_name = full_name.clone
|
210
|
+
package_name["." + class_name] = ""
|
211
|
+
|
212
|
+
package_xml = package_by_full_name(xmi_content(document), package_name)
|
213
|
+
package_xml.at_xpath("./UML:Namespace.ownedElement/UML:Class[@name='#{class_name}']")
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.class_by_id(document, id)
|
218
|
+
tag_by_id(document, 'UML:Class', id)
|
219
|
+
end
|
220
|
+
|
221
|
+
def self.class_by_name(document, name)
|
222
|
+
tag_by_name(xmi_content(document), "UML:Class", name)
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.classes(tag)
|
226
|
+
namespace(tag).xpath("./UML:Class")
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.classes_by_association(document, association)
|
230
|
+
raise ArgumentError.new("Parameter is not a UML:Association tag.") if association.name != 'Association'
|
231
|
+
|
232
|
+
classes = Array.new
|
233
|
+
|
234
|
+
association.xpath( "./UML:Association.connection/UML:AssociationEnd").each do |ae|
|
235
|
+
participant_id = participant_id_by_association_end(ae)
|
236
|
+
clazz = class_by_id(xmi_content(document), participant_id) unless participant_id.nil?
|
237
|
+
classes << clazz unless clazz.nil?
|
238
|
+
end
|
239
|
+
|
240
|
+
classes
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.data_type(document, id)
|
244
|
+
tag_by_id(document, 'UML:Enumeration', id)
|
245
|
+
end
|
246
|
+
|
247
|
+
def self.data_types(tag)
|
248
|
+
namespace(tag).xpath("./UML:DataType")
|
249
|
+
end
|
250
|
+
|
251
|
+
def self.enumeratios(tag)
|
252
|
+
namespace(tag).xpath("./UML:Enumeration")
|
253
|
+
end
|
254
|
+
|
255
|
+
def self.enumeration_by_id(document, id)
|
256
|
+
tag_by_id(document, 'UML:DataType', id)
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.exporter(document)
|
260
|
+
@exporter = document.at_xpath("./XMI/XMI.header/XMI.documentation/XMI.exporter").inner_html
|
261
|
+
end
|
262
|
+
|
263
|
+
def self.exporter_version(document)
|
264
|
+
@exporter_version = document.at_xpath("./XMI/XMI.header/XMI.documentation/XMI.exporterVersion").inner_html
|
265
|
+
end
|
266
|
+
|
267
|
+
def self.metamodel_version(document)
|
268
|
+
@metamodel_version = doc.at_xpath("./XMI/XMI.header/XMI.metamodel").attribute("xmi.version").to_s
|
269
|
+
end
|
270
|
+
|
271
|
+
def self.extension_referent_path_value(tag)
|
272
|
+
return "" if tag.nil?
|
273
|
+
|
274
|
+
if tag.name != 'XMI.extension'
|
275
|
+
tag = tag.at_xpath("./XMI.extension")
|
276
|
+
end
|
277
|
+
return "" if tag.nil?
|
278
|
+
|
279
|
+
raise ArgumentError.new("Parameter is not a XMI.extension tag or a tag that contains.") if tag.name != 'XMI.extension'
|
280
|
+
|
281
|
+
referent_path = tag.at_xpath("./referentPath")
|
282
|
+
if referent_path.nil?
|
283
|
+
return ""
|
284
|
+
else
|
285
|
+
return referent_path.attribute("xmi.value").to_s
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def self.has_namespace?(tag)
|
290
|
+
return false if tag.nil?
|
291
|
+
if tag.name != "Namespace.ownedElement"
|
292
|
+
tag = tag.at_xpath("./UML:Namespace.ownedElement")
|
293
|
+
end
|
294
|
+
if tag.nil? or tag.name != "Namespace.ownedElement"
|
295
|
+
return false
|
296
|
+
end
|
297
|
+
return true
|
298
|
+
end
|
299
|
+
|
300
|
+
def self.namespace(tag)
|
301
|
+
raise ArgumentError.new("Parameter cannot be nil..") if tag.nil?
|
302
|
+
if tag.name != "Namespace.ownedElement"
|
303
|
+
tag = tag.at_xpath("./UML:Namespace.ownedElement")
|
304
|
+
end
|
305
|
+
if tag.nil? or tag.name != "Namespace.ownedElement"
|
306
|
+
raise ArgumentError.new("Parameter does not contain a tag 'UML:Namespace.ownedElement'.")
|
307
|
+
end
|
308
|
+
tag
|
309
|
+
end
|
310
|
+
|
311
|
+
def self.full_class_name(clazz)
|
312
|
+
raise ArgumentError.new("Parameter cannot be nil..") if clazz.nil?
|
313
|
+
package = parent_package(clazz)
|
314
|
+
if package.nil?
|
315
|
+
clazz.attribute("name")
|
316
|
+
else
|
317
|
+
full_package_name(package) + "." + clazz.attribute("name")
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def self.full_enumeration_name(enumeration)
|
322
|
+
raise ArgumentError.new("Parameter cannot be nil..") if enumeration.nil?
|
323
|
+
package = parent_package(enumeration)
|
324
|
+
if package.nil?
|
325
|
+
enumeration.attribute("name")
|
326
|
+
else
|
327
|
+
full_package_name(package) + "." + enumeration.attribute("name")
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
def self.full_package_name(package)
|
332
|
+
|
333
|
+
name = package.attribute("name").to_s
|
334
|
+
begin
|
335
|
+
package = parent_package(package)
|
336
|
+
|
337
|
+
name = package.attribute("name").to_s + "." + name unless package.nil?
|
338
|
+
end while !package.nil?
|
339
|
+
|
340
|
+
name
|
341
|
+
end
|
342
|
+
|
343
|
+
def self.generalization_by_child(document, id)
|
344
|
+
|
345
|
+
xmi_content(document).xpath('//UML:Generalization').each do |g|
|
346
|
+
child = g.attribute('child')
|
347
|
+
if child.nil?
|
348
|
+
class_ref = g.at_xpath('./UML:Generalization.child/UML:Class')
|
349
|
+
child = class_ref.attribute('xmi.idref') unless class_ref.nil?
|
350
|
+
end
|
351
|
+
|
352
|
+
return g if !child.nil? && id == child.to_s
|
353
|
+
end
|
354
|
+
|
355
|
+
nil
|
356
|
+
end
|
357
|
+
|
358
|
+
#
|
359
|
+
# Returns the child id from the tag 'UML:Generalization'
|
360
|
+
def self.generalization_child(generalization)
|
361
|
+
child = generalization.attribute("child")
|
362
|
+
if child.nil?
|
363
|
+
class_ref = generalization.at_xpath('./UML:Generalization.child/UML:Class')
|
364
|
+
child = class_ref.attribute('xmi.idref') unless class_ref.nil?
|
365
|
+
end
|
366
|
+
child.to_s
|
367
|
+
end
|
368
|
+
|
369
|
+
#
|
370
|
+
# Returns the parent id from the tag 'UML:Generalization'
|
371
|
+
def self.generalization_parent(generalization)
|
372
|
+
parent = generalization.attribute("parent")
|
373
|
+
if parent.nil?
|
374
|
+
class_ref = generalization.at_xpath('./UML:Generalization.parent/UML:Class')
|
375
|
+
parent = class_ref.attribute('xmi.idref') unless class_ref.nil?
|
376
|
+
end
|
377
|
+
parent.to_s
|
378
|
+
end
|
379
|
+
|
380
|
+
def self.guard_condition(tag)
|
381
|
+
|
382
|
+
return nil if tag.nil?
|
383
|
+
if tag.name == "Transition"
|
384
|
+
tag = tag.at_xpath("./UML:Transition.guard/UML:Guard")
|
385
|
+
end
|
386
|
+
|
387
|
+
return nil if tag.nil?
|
388
|
+
raise ArgumentError.new("Parameter is not a UML:Guard OR UML:Transition tag.") if tag.name != "Guard"
|
389
|
+
tag.at_xpath('./UML:Guard.expression/UML:BooleanExpression')
|
390
|
+
end
|
391
|
+
|
392
|
+
def self.metamodel_version(document)
|
393
|
+
@metamodel_version = document.at_xpath("./XMI/XMI.header/XMI.metamodel").attribute("xmi.version").to_s
|
394
|
+
end
|
395
|
+
|
396
|
+
def self.package_by_name(tag, package_name)
|
397
|
+
|
398
|
+
# se passou um 'UML:Package' navega até o 'UML:Namespace.ownedElement' filho
|
399
|
+
if tag.name == "Package"
|
400
|
+
tag = tag.at_xpath("./UML:Namespace.ownedElement")
|
401
|
+
end
|
402
|
+
|
403
|
+
# deverá ser 'UML:Namespace.ownedElement' ou 'XMI.content'
|
404
|
+
if !(tag.nil?) && (tag.name == "Namespace.ownedElement" || tag.name == "XMI.content")
|
405
|
+
|
406
|
+
# procura pelo pacote
|
407
|
+
tag.xpath('./UML:Package').each do |package|
|
408
|
+
return package if package.attribute('name').to_s == package_name
|
409
|
+
end
|
410
|
+
|
411
|
+
# poderá ter uma tag './UML:Model' com mais 'UML:Namespace.ownedElement'
|
412
|
+
tag.xpath("./UML:Model").each do |model|
|
413
|
+
|
414
|
+
model.xpath('./UML:Namespace.ownedElement').each do |namespace|
|
415
|
+
|
416
|
+
# procura recursivamente dentro do namespace
|
417
|
+
p = package_by_name(namespace, package_name)
|
418
|
+
return p unless p.nil?
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
end
|
423
|
+
nil
|
424
|
+
end
|
425
|
+
|
426
|
+
def self.package_by_full_name(document, full_package_name)
|
427
|
+
package_name = full_package_name.split(".")
|
428
|
+
|
429
|
+
if package_name.length >= 1
|
430
|
+
package = package_by_name(xmi_content(document), package_name[0])
|
431
|
+
|
432
|
+
for i in 1..package_name.length - 1
|
433
|
+
return nil if (package == nil)
|
434
|
+
|
435
|
+
package = package_by_name(package, package_name[i])
|
436
|
+
end
|
437
|
+
return package
|
438
|
+
end
|
439
|
+
|
440
|
+
nil
|
441
|
+
end
|
442
|
+
|
443
|
+
def self.packages(tag)
|
444
|
+
|
445
|
+
packages = Array.new
|
446
|
+
|
447
|
+
if tag.name == "XMI.content"
|
448
|
+
tag = tag.at_xpath('./UML:Model/UML:Namespace.ownedElement')
|
449
|
+
|
450
|
+
# se passou um 'UML:Package' navega até o 'UML:Namespace.ownedElement' filho
|
451
|
+
elsif tag.name == "Package" || tag.name == "Model"
|
452
|
+
tag = tag.at_xpath("./UML:Namespace.ownedElement")
|
453
|
+
end
|
454
|
+
|
455
|
+
# Pacote sem nenhuma classe nem pacotes internos
|
456
|
+
return packages if tag.nil?
|
457
|
+
|
458
|
+
# deverá ser 'UML:Namespace.ownedElement' ou 'XMI.content'
|
459
|
+
if tag.name == "Namespace.ownedElement" || tag.name == "XMI.content"
|
460
|
+
|
461
|
+
tag.xpath('./UML:Package').each do |package|
|
462
|
+
# puts package.attribute "name"
|
463
|
+
packages << package
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
if packages.size == 0
|
468
|
+
tag.xpath('./UML:Model').each do |model|
|
469
|
+
packages = packages + XmiHelper.packages(model)
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
packages
|
474
|
+
end
|
475
|
+
|
476
|
+
def self.parameters(tag)
|
477
|
+
|
478
|
+
if tag.name == "SignalEvent"
|
479
|
+
tag.xpath("./UML:Event.parameter/UML:Parameter")
|
480
|
+
elsif tag.name == "Operation"
|
481
|
+
tag.xpath("./UML:BehavioralFeature.parameter/UML:Parameter")
|
482
|
+
else
|
483
|
+
raise ArgumentError.new("Parameter (#{tag.name}) is not a UML:SignalEvent or UML:Operation tag.")
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
def self.parent_package(tag)
|
488
|
+
|
489
|
+
return nil if tag.nil?
|
490
|
+
|
491
|
+
if tag.name == "Class" || tag.name == "Package" || tag.name == "Enumeration"
|
492
|
+
namespace = tag.parent if !(tag.parent.nil?) && tag.parent.name == "Namespace.ownedElement"
|
493
|
+
end
|
494
|
+
|
495
|
+
if !namespace.nil?
|
496
|
+
return namespace.parent if !(namespace.parent.nil?) && namespace.parent.name == "Package"
|
497
|
+
end
|
498
|
+
nil
|
499
|
+
end
|
500
|
+
|
501
|
+
def self.participant_id_by_association_end(association_end)
|
502
|
+
|
503
|
+
raise ArgumentError.new("Parameter is not a AssociationEnd tag.") if association_end.name != 'AssociationEnd'
|
504
|
+
|
505
|
+
if association_end.attribute("participant").nil?
|
506
|
+
|
507
|
+
if association_end.attribute("type").nil?
|
508
|
+
participant_id = association_end.at_xpath("./UML:AssociationEnd.participant/UML:Class")
|
509
|
+
part = participant_id.attribute('xmi.idref') unless participant_id.nil?
|
510
|
+
else
|
511
|
+
part = association_end.attribute("type")
|
512
|
+
end
|
513
|
+
else
|
514
|
+
part = association_end.attribute("participant")
|
515
|
+
end
|
516
|
+
|
517
|
+
return part
|
518
|
+
end
|
519
|
+
|
520
|
+
def self.stereotypes(document)
|
521
|
+
|
522
|
+
stereotypes = Array.new
|
523
|
+
document.xpath('./UML:ModelElement.stereotype/UML:Stereotype').each do |stereotype|
|
524
|
+
stereotypes << stereotype
|
525
|
+
end
|
526
|
+
stereotypes
|
527
|
+
end
|
528
|
+
|
529
|
+
def self.stereotype_by_href(document, href)
|
530
|
+
stereotype = document.at_xpath("//UML:Stereotype[@href='#{href}']")
|
531
|
+
end
|
532
|
+
|
533
|
+
def self.stereotype_by_id(document, id)
|
534
|
+
tag_by_id(document, 'UML:Stereotype', id)
|
535
|
+
end
|
536
|
+
|
537
|
+
def self.xmi_content(tag)
|
538
|
+
return tag if tag.nil? or tag.name == "XMI.content"
|
539
|
+
xmi_content = tag.document.at_xpath("./XMI/XMI.content")
|
540
|
+
end
|
541
|
+
|
542
|
+
def self.tag_definition_by_id(document, id)
|
543
|
+
tag_by_id(document, 'UML:TagDefinition', id)
|
544
|
+
end
|
545
|
+
|
546
|
+
def self.tagged_values(tag)
|
547
|
+
t = Array.new
|
548
|
+
tag.xpath('./UML:ModelElement.taggedValue/UML:TaggedValue').each do |tagged_value|
|
549
|
+
t << tagged_value
|
550
|
+
end
|
551
|
+
t
|
552
|
+
end
|
553
|
+
|
554
|
+
def self.tagged_value_by_name(tag, name)
|
555
|
+
tag_by_name(tag, "UML:TaggedValue", name)
|
556
|
+
end
|
557
|
+
|
558
|
+
def self.taggeg_value_data_value(tag)
|
559
|
+
return "" if tag.nil?
|
560
|
+
|
561
|
+
if tag.name == 'TaggedValue'
|
562
|
+
#tag_id = tag.attribute("xmi.id").to_s
|
563
|
+
tag = tag.at_xpath("./UML:TaggedValue.dataValue")
|
564
|
+
end
|
565
|
+
|
566
|
+
if tag.nil?
|
567
|
+
#puts "[WARN] - TaggedValue '#{tag_id}' sem tag UML:TaggedValue.dataValue"
|
568
|
+
return ""
|
569
|
+
end
|
570
|
+
|
571
|
+
raise ArgumentError.new("Parameter is not a UML:TaggedValue.dataValue tag or a tag that contains.") if tag.name != 'TaggedValue.dataValue'
|
572
|
+
|
573
|
+
tag.inner_html
|
574
|
+
end
|
575
|
+
|
576
|
+
# TaggedValue
|
577
|
+
def self.taggeg_value_reference_value(tag)
|
578
|
+
return "" if tag.nil?
|
579
|
+
raise ArgumentError.new("Parameter is not a UML:TaggedValue tag.") if tag.name != 'TaggedValue'
|
580
|
+
tag = tag.at_xpath("./UML:TaggedValue.referenceValue/UML:ModelElement/XMI.extension")
|
581
|
+
extension_referent_path_value(tag)
|
582
|
+
end
|
583
|
+
|
584
|
+
def self.taggeg_value_tag_definition(tag)
|
585
|
+
return "" if tag.nil?
|
586
|
+
raise ArgumentError.new("Parameter is not a UML:TaggedValue tag.") if tag.name != 'TaggedValue'
|
587
|
+
tag = tag.at_xpath("./UML:TaggedValue.type/UML:TagDefinition")
|
588
|
+
end
|
589
|
+
|
590
|
+
# Signal events are methods triggered between one state and another
|
591
|
+
def self.signal_events(tag)
|
592
|
+
namespace(tag).xpath("./UML:SignalEvent")
|
593
|
+
end
|
594
|
+
|
595
|
+
def self.use_case_by_name(document, name)
|
596
|
+
tag_by_name(xmi_content(document), "UML:UseCase", name)
|
597
|
+
end
|
598
|
+
|
599
|
+
def self.use_cases(tag)
|
600
|
+
namespace(tag).xpath("./UML:UseCase")
|
601
|
+
end
|
602
|
+
|
603
|
+
def self.multiplicity(tag)
|
604
|
+
return nil if tag.nil?
|
605
|
+
|
606
|
+
case tag.name
|
607
|
+
|
608
|
+
when "Attribute"
|
609
|
+
uml_multiplicity = tag.at_xpath('./UML:StructuralFeature.multiplicity/UML:Multiplicity')
|
610
|
+
|
611
|
+
when "AssociationEnd"
|
612
|
+
uml_multiplicity = tag.at_xpath('./UML:AssociationEnd.multiplicity/UML:Multiplicity')
|
613
|
+
else
|
614
|
+
raise ArgumentError.new("Parameter is not a UML:Attribute or UML:AssociationEnd tag.")
|
615
|
+
end
|
616
|
+
|
617
|
+
uml_multiplicity
|
618
|
+
end
|
619
|
+
|
620
|
+
def self.multiplicity_range(tag)
|
621
|
+
|
622
|
+
return nil if tag.nil?
|
623
|
+
|
624
|
+
tag = multiplicity(tag) if (tag.name == "Attribute" || tag.name == "AssociationEnd")
|
625
|
+
return nil if tag.nil?
|
626
|
+
|
627
|
+
raise ArgumentError.new("Parameter is not a UML:Multiplicity tag.") if tag.name != "Multiplicity"
|
628
|
+
|
629
|
+
uml_multiplicity_range = tag.at_xpath('./UML:Multiplicity.range/UML:MultiplicityRange')
|
630
|
+
|
631
|
+
if uml_multiplicity_range.nil?
|
632
|
+
return nil
|
633
|
+
else
|
634
|
+
return [Integer(uml_multiplicity_range.attribute('lower').to_s), Integer(uml_multiplicity_range.attribute('upper').to_s)]
|
635
|
+
end
|
636
|
+
end
|
637
|
+
|
638
|
+
def self.operations(uml_class)
|
639
|
+
raise ArgumentError.new("Parameter is not a UML:Class tag.") if uml_class.name != "Class"
|
640
|
+
|
641
|
+
uml_class.xpath('./UML:Classifier.feature/UML:Operation')
|
642
|
+
end
|
643
|
+
|
644
|
+
def self.operation_by_id(document, id)
|
645
|
+
tag_by_id(document, 'UML:Operation', id)
|
646
|
+
end
|
647
|
+
|
648
|
+
def self.operation_by_name(tag, name)
|
649
|
+
raise ArgumentError.new("Parameter is not a UML:Class tag.") if tag.nil? || tag.name != "Class"
|
650
|
+
tag.at_xpath("./UML:Classifier.feature/UML:Operation[@name='#{name}']")
|
651
|
+
end
|
652
|
+
|
653
|
+
def self.pseudo_states(tag)
|
654
|
+
raise ArgumentError.new("Parameter is not a UML:ActivityGraph tag.") if tag.nil? || tag.name != "ActivityGraph"
|
655
|
+
tag.xpath('./UML:StateMachine.top/UML:CompositeState/UML:CompositeState.subvertex/UML:Pseudostate')
|
656
|
+
end
|
657
|
+
|
658
|
+
def self.final_states(tag)
|
659
|
+
raise ArgumentError.new("Parameter is not a UML:ActivityGraph tag.") if tag.nil? || tag.name != "ActivityGraph"
|
660
|
+
tag.xpath('./UML:StateMachine.top/UML:CompositeState/UML:CompositeState.subvertex/UML:FinalState')
|
661
|
+
end
|
662
|
+
|
663
|
+
def self.transitions(tag)
|
664
|
+
raise ArgumentError.new("Parameter is not a UML:ActivityGraph tag.") if tag.nil? || tag.name != "ActivityGraph"
|
665
|
+
tag.xpath('./UML:StateMachine.transitions/UML:Transition')
|
666
|
+
end
|
667
|
+
|
668
|
+
def self.version
|
669
|
+
"1.0.0"
|
670
|
+
end
|
671
|
+
|
672
|
+
private
|
673
|
+
|
674
|
+
def self.tag_by_name(document, tag, name)
|
675
|
+
raise ArgumentError.new("Parameter 'name' cannot be empty.") if name.nil? or name.empty?
|
676
|
+
use_case = xmi_content(document).at_xpath("//#{tag}[@name='#{name}']")
|
677
|
+
end
|
678
|
+
|
679
|
+
def self.tag_by_id(document, tag, id)
|
680
|
+
raise ArgumentError.new("Parameter 'id' cannot be empty.") if id.nil? or id.empty?
|
681
|
+
use_case = xmi_content(document).at_xpath("//#{tag}[@xmi.id='#{id}']")
|
682
|
+
end
|
683
|
+
end
|