xmimodel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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