xmi 0.5.3 → 0.5.5

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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +31 -45
  3. data/README.adoc +0 -15
  4. data/lib/xmi/custom_profile/abstract.rb +16 -0
  5. data/lib/xmi/custom_profile/basic_doc.rb +16 -0
  6. data/lib/xmi/custom_profile/bibliography.rb +16 -0
  7. data/lib/xmi/custom_profile/edition.rb +18 -0
  8. data/lib/xmi/custom_profile/enumeration.rb +16 -0
  9. data/lib/xmi/custom_profile/informative.rb +16 -0
  10. data/lib/xmi/custom_profile/invariant.rb +16 -0
  11. data/lib/xmi/custom_profile/number.rb +18 -0
  12. data/lib/xmi/custom_profile/ocl.rb +16 -0
  13. data/lib/xmi/custom_profile/persistence.rb +20 -0
  14. data/lib/xmi/custom_profile/publication_date.rb +18 -0
  15. data/lib/xmi/custom_profile/year_version.rb +18 -0
  16. data/lib/xmi/custom_profile.rb +12 -143
  17. data/lib/xmi/ea_root/code_generation.rb +141 -0
  18. data/lib/xmi/ea_root/extension_lifecycle.rb +52 -0
  19. data/lib/xmi/ea_root/namespace_handling.rb +39 -0
  20. data/lib/xmi/ea_root/xml_parsing.rb +51 -0
  21. data/lib/xmi/ea_root.rb +16 -403
  22. data/lib/xmi/extension.rb +4 -12
  23. data/lib/xmi/parser_pipeline.rb +70 -0
  24. data/lib/xmi/root.rb +3 -12
  25. data/lib/xmi/sparx/connector/appearance.rb +27 -0
  26. data/lib/xmi/sparx/connector/connector.rb +52 -0
  27. data/lib/xmi/sparx/connector/end_base.rb +56 -0
  28. data/lib/xmi/sparx/connector/end_constraint.rb +33 -0
  29. data/lib/xmi/sparx/connector/end_modifiers.rb +19 -0
  30. data/lib/xmi/sparx/connector/end_role.rb +21 -0
  31. data/lib/xmi/sparx/connector/end_style.rb +17 -0
  32. data/lib/xmi/sparx/connector/end_type.rb +21 -0
  33. data/lib/xmi/sparx/connector/labels.rb +27 -0
  34. data/lib/xmi/sparx/connector/model.rb +19 -0
  35. data/lib/xmi/sparx/connector/properties.rb +19 -0
  36. data/lib/xmi/sparx/connector.rb +15 -233
  37. data/lib/xmi/sparx/element/association.rb +58 -0
  38. data/lib/xmi/sparx/element/attribute.rb +58 -0
  39. data/lib/xmi/sparx/element/bounds.rb +19 -0
  40. data/lib/xmi/sparx/element/code.rb +19 -0
  41. data/lib/xmi/sparx/element/containment.rb +19 -0
  42. data/lib/xmi/sparx/element/coords.rb +19 -0
  43. data/lib/xmi/sparx/element/documentation.rb +17 -0
  44. data/lib/xmi/sparx/element/element.rb +62 -0
  45. data/lib/xmi/sparx/element/extended_properties.rb +21 -0
  46. data/lib/xmi/sparx/element/flags.rb +29 -0
  47. data/lib/xmi/sparx/element/links.rb +22 -0
  48. data/lib/xmi/sparx/element/model.rb +26 -0
  49. data/lib/xmi/sparx/element/package_properties.rb +21 -0
  50. data/lib/xmi/sparx/element/paths.rb +17 -0
  51. data/lib/xmi/sparx/element/project.rb +29 -0
  52. data/lib/xmi/sparx/element/properties.rb +41 -0
  53. data/lib/xmi/sparx/element/stereotype.rb +17 -0
  54. data/lib/xmi/sparx/element/style.rb +17 -0
  55. data/lib/xmi/sparx/element/styleex.rb +17 -0
  56. data/lib/xmi/sparx/element/tag.rb +32 -0
  57. data/lib/xmi/sparx/element/times.rb +23 -0
  58. data/lib/xmi/sparx/element/xrefs.rb +17 -0
  59. data/lib/xmi/sparx/element.rb +28 -445
  60. data/lib/xmi/sparx/extension.rb +4 -12
  61. data/lib/xmi/sparx/gml/application_schema.rb +26 -0
  62. data/lib/xmi/sparx/gml/code_list.rb +23 -0
  63. data/lib/xmi/sparx/gml/data_type.rb +18 -0
  64. data/lib/xmi/sparx/gml/enumeration.rb +18 -0
  65. data/lib/xmi/sparx/gml/feature_type.rb +21 -0
  66. data/lib/xmi/sparx/gml/property.rb +24 -0
  67. data/lib/xmi/sparx/gml/shared_attributes.rb +39 -0
  68. data/lib/xmi/sparx/gml/type.rb +18 -0
  69. data/lib/xmi/sparx/gml/union.rb +18 -0
  70. data/lib/xmi/sparx/gml.rb +10 -125
  71. data/lib/xmi/sparx/index.rb +248 -0
  72. data/lib/xmi/sparx/mappings/base_mapping.rb +13 -137
  73. data/lib/xmi/sparx/root.rb +10 -11
  74. data/lib/xmi/sparx.rb +1 -0
  75. data/lib/xmi/uml/annotated_element.rb +16 -0
  76. data/lib/xmi/uml/association_generalization.rb +20 -0
  77. data/lib/xmi/uml/bounds.rb +43 -0
  78. data/lib/xmi/uml/default_value.rb +42 -0
  79. data/lib/xmi/uml/diagram.rb +25 -0
  80. data/lib/xmi/uml/member_end.rb +16 -0
  81. data/lib/xmi/uml/owned_attribute.rb +31 -0
  82. data/lib/xmi/uml/owned_comment.rb +29 -0
  83. data/lib/xmi/uml/owned_element.rb +33 -0
  84. data/lib/xmi/uml/owned_end.rb +34 -0
  85. data/lib/xmi/uml/owned_literal.rb +23 -0
  86. data/lib/xmi/uml/owned_operation.rb +22 -0
  87. data/lib/xmi/uml/owned_parameter.rb +29 -0
  88. data/lib/xmi/uml/package_import.rb +30 -0
  89. data/lib/xmi/uml/packaged_element.rb +49 -0
  90. data/lib/xmi/uml/precondition.rb +22 -0
  91. data/lib/xmi/uml/profile.rb +43 -0
  92. data/lib/xmi/uml/profile_application.rb +34 -0
  93. data/lib/xmi/uml/specification.rb +20 -0
  94. data/lib/xmi/uml/type.rb +18 -0
  95. data/lib/xmi/uml/uml_model.rb +29 -0
  96. data/lib/xmi/uml.rb +27 -502
  97. data/lib/xmi/version.rb +1 -1
  98. data/lib/xmi/xmi_identity.rb +46 -0
  99. data/lib/xmi.rb +11 -7
  100. metadata +84 -3
  101. data/lib/xmi/index.rb +0 -243
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Xmi
4
+ class EaRoot
5
+ module CodeGeneration
6
+ # Build extension classes directly via Class.new + const_set.
7
+ def build_extension(xml_path)
8
+ xmi_doc = Nokogiri::XML(File.read(xml_path))
9
+ @module_name = get_module_name(xmi_doc)
10
+ @def_namespace = get_namespace_from_definition(xmi_doc)
11
+
12
+ # Resolve namespace class (returns class object)
13
+ ns_class = resolve_namespace_class
14
+
15
+ # Create the parent module Xmi::EaRoot::ModuleName
16
+ mod = Module.new
17
+ EaRoot.const_set(@module_name.to_sym, mod)
18
+
19
+ # Process abstract class
20
+ @abstract_klass_node = get_abstract_klass_node(xmi_doc)
21
+ @abstract_tags = []
22
+ abstract_klass = nil
23
+ if @abstract_klass_node
24
+ abstract_klass = build_abstract_class(mod, @abstract_klass_node)
25
+ end
26
+
27
+ # Process non-abstract stereotypes
28
+ nodes = xmi_doc.xpath(
29
+ "//UMLProfiles//Stereotypes//Stereotype[not(contains(@isAbstract, 'true'))]",
30
+ )
31
+
32
+ # Without baseStereotypes
33
+ nodes.select { |n| n.attributes["baseStereotypes"].nil? }.each do |node|
34
+ build_stereotype_class(mod, node, abstract_klass, ns_class)
35
+ end
36
+
37
+ # With baseStereotypes
38
+ nodes.reject { |n| n.attributes["baseStereotypes"].nil? }.each do |node|
39
+ base_name = node.attributes["baseStereotypes"].value
40
+ build_stereotype_class(mod, node, abstract_klass, ns_class,
41
+ parent_name: base_name)
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def build_abstract_class(parent_mod, abstract_node)
48
+ klass_name = Lutaml::Model::Utils.classify(
49
+ get_klass_name_from_node(abstract_node),
50
+ )
51
+
52
+ klass = Class.new(Lutaml::Model::Serializable)
53
+
54
+ # Add tag attributes (NO xml mapping for abstract classes)
55
+ tags = abstract_node.search("Tag")
56
+ @abstract_tags = tags
57
+ tags.each do |tag|
58
+ tag_name = get_tag_name(tag)
59
+ attr_name = Lutaml::Model::Utils.snake_case(tag_name)
60
+ klass.attribute attr_name.to_sym, :string
61
+ end
62
+
63
+ parent_mod.const_set(klass_name.to_sym, klass)
64
+ klass
65
+ end
66
+
67
+ def build_stereotype_class(parent_mod, node, abstract_klass, ns_class,
68
+ parent_name: nil)
69
+ node_name = get_klass_name_from_node(node)
70
+ klass_name = Lutaml::Model::Utils.classify(node_name)
71
+
72
+ # Determine parent class
73
+ parent_klass = if parent_name
74
+ parent_mod.const_get(Lutaml::Model::Utils.classify(parent_name).to_sym)
75
+ elsif abstract_klass
76
+ abstract_klass
77
+ else
78
+ Lutaml::Model::Serializable
79
+ end
80
+
81
+ # Collect tags and apply types
82
+ tags = node.search("Tag")
83
+ apply_nodes = node.search("Apply")
84
+
85
+ # Build the class
86
+ klass = Class.new(parent_klass) do
87
+ define_singleton_method(:root_tag) { node_name }
88
+ end
89
+
90
+ # Add tag attributes
91
+ tags.each do |tag|
92
+ tag_name = get_tag_name(tag)
93
+ attr_name = Lutaml::Model::Utils.snake_case(tag_name)
94
+ klass.attribute attr_name.to_sym, :string
95
+ end
96
+
97
+ # Add apply type attributes
98
+ apply_nodes.each do |n|
99
+ apply_types = n.attribute_nodes.map(&:value)
100
+ apply_types.each do |apply_type|
101
+ attr_name = Lutaml::Model::Utils.snake_case("base_#{apply_type}")
102
+ klass.attribute attr_name.to_sym, :string
103
+ end
104
+ end
105
+
106
+ # Add XML mapping
107
+ # Pre-compute tag mapping pairs (xml block runs in Mapping context, not EaRoot)
108
+ all_tag_pairs = (@abstract_tags + tags).map do |tag|
109
+ tag_name = get_tag_name(tag)
110
+ [tag_name, Lutaml::Model::Utils.snake_case(tag_name).to_sym]
111
+ end
112
+
113
+ apply_pairs = []
114
+ apply_nodes.each do |n|
115
+ n.attribute_nodes.map(&:value).each do |apply_type|
116
+ apply_pairs << [
117
+ "base_#{apply_type}",
118
+ Lutaml::Model::Utils.snake_case("base_#{apply_type}").to_sym,
119
+ ]
120
+ end
121
+ end
122
+
123
+ klass.xml do
124
+ root node_name
125
+ namespace ns_class
126
+
127
+ all_tag_pairs.each do |xml_name, attr_sym|
128
+ map_attribute xml_name, to: attr_sym
129
+ end
130
+
131
+ apply_pairs.each do |xml_name, attr_sym|
132
+ map_attribute xml_name, to: attr_sym
133
+ end
134
+ end
135
+
136
+ parent_mod.const_set(klass_name.to_sym, klass)
137
+ klass
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Xmi
4
+ class EaRoot
5
+ module ExtensionLifecycle
6
+ def update_mappings(module_name)
7
+ new_klasses = all_new_klasses(module_name)
8
+ inject_model_attributes(new_klasses, module_name)
9
+ inject_model_xml_mappings(new_klasses, module_name)
10
+ end
11
+
12
+ private
13
+
14
+ def inject_model_attributes(new_klasses, module_name)
15
+ sparx_root = Xmi::Sparx::SparxRoot
16
+ new_klasses.each do |klass_name|
17
+ method_name = Lutaml::Model::Utils.snake_case(klass_name)
18
+ full_klass = EaRoot.const_get(module_name).const_get(klass_name)
19
+ sparx_root.attribute method_name.to_sym, full_klass, collection: true
20
+ end
21
+ end
22
+
23
+ def inject_model_xml_mappings(new_klasses, module_name)
24
+ map_entries = []
25
+ new_klasses.each do |klass_name|
26
+ klass = EaRoot.const_get(module_name).const_get(klass_name)
27
+ next unless klass.respond_to?(:root_tag)
28
+
29
+ method_name = Lutaml::Model::Utils.snake_case(klass_name)
30
+ map_entries << [klass.root_tag, method_name.to_sym]
31
+ end
32
+
33
+ return if map_entries.empty?
34
+
35
+ Xmi::Sparx::SparxRoot.class_eval do
36
+ xml do
37
+ map_entries.each do |element_name, method_sym|
38
+ map_element element_name, to: method_sym,
39
+ value_map: Xmi::VALUE_MAP
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ def all_new_klasses(module_name)
46
+ EaRoot.const_get(module_name).constants.select do |c|
47
+ EaRoot.const_get(module_name).const_get(c).is_a? Class
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Xmi
4
+ class EaRoot
5
+ module NamespaceHandling
6
+ # Resolve the namespace class for the current extension.
7
+ # Returns the class object (not a name string) for direct use with
8
+ # the xml DSL's +namespace+ directive.
9
+ def resolve_namespace_class
10
+ uri = @def_namespace[:uri]
11
+ prefix = @def_namespace[:name]
12
+
13
+ existing = NamespaceRegistry.resolve(uri)
14
+ return existing if existing
15
+
16
+ module_name = @module_name
17
+ ns_class_name = "Xmi::Namespace::Dynamic::#{module_name}"
18
+ return Object.const_get(ns_class_name) if Object.const_defined?(ns_class_name)
19
+
20
+ Namespace.ensure_dynamic_namespace_module_exists!
21
+ ns_class = Class.new(Lutaml::Xml::Namespace) do
22
+ define_singleton_method(:uri) { uri }
23
+ define_singleton_method(:prefix_default) { prefix }
24
+ end
25
+ Namespace::Dynamic.const_set(module_name, ns_class)
26
+
27
+ NamespaceRegistry.register(uri, ns_class)
28
+
29
+ ns_class
30
+ end
31
+
32
+ # Returns the namespace class _name_ as a string.
33
+ def find_or_create_namespace_class
34
+ klass = resolve_namespace_class
35
+ klass.is_a?(String) ? klass : klass.name
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Xmi
4
+ class EaRoot
5
+ module XmlParsing
6
+ def get_abstract_klass_node(xmi_doc)
7
+ xmi_doc.at_xpath(
8
+ "//UMLProfiles//Stereotypes//Stereotype[@isAbstract='true']",
9
+ )
10
+ end
11
+
12
+ def get_klass_name_from_node(node)
13
+ return Lutaml::Model::Serializable.to_s unless node
14
+
15
+ node.attribute_nodes.find { |attr| attr.name == "name" }.value
16
+ end
17
+
18
+ def get_module_name(xmi_doc)
19
+ get_module_name_from_definition(xmi_doc).capitalize
20
+ end
21
+
22
+ def get_module_name_from_definition(xmi_doc)
23
+ node = xmi_doc.at_xpath("//UMLProfile/Documentation")
24
+ node.attribute_nodes.find { |attr| attr.name == "name" }&.value
25
+ end
26
+
27
+ def get_module_uri(xmi_doc)
28
+ node = xmi_doc.at_xpath("//UMLProfile/Documentation")
29
+ uri = node.attribute_nodes.find { |attr| attr.name == "URI" }&.value
30
+ return uri if uri
31
+
32
+ name = get_module_name_from_definition(xmi_doc)
33
+ ver = node.attribute_nodes.find { |attr| attr.name == "version" }&.value
34
+
35
+ "http://www.sparxsystems.com/profiles/#{name}/#{ver}"
36
+ end
37
+
38
+ def get_namespace_from_definition(xmi_doc)
39
+ namespace_key = get_module_name_from_definition(xmi_doc)
40
+ namespace_uri = get_module_uri(xmi_doc)
41
+
42
+ { name: namespace_key, uri: namespace_uri }
43
+ end
44
+
45
+ def get_tag_name(tag)
46
+ tag_name = tag.attribute_nodes.find { |attr| attr.name == "name" }.value
47
+ tag_name == "xmlns" ? "altered_xmlns" : tag_name
48
+ end
49
+ end
50
+ end
51
+ end