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.
@@ -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