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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +31 -45
- data/README.adoc +0 -15
- data/lib/xmi/custom_profile/abstract.rb +16 -0
- data/lib/xmi/custom_profile/basic_doc.rb +16 -0
- data/lib/xmi/custom_profile/bibliography.rb +16 -0
- data/lib/xmi/custom_profile/edition.rb +18 -0
- data/lib/xmi/custom_profile/enumeration.rb +16 -0
- data/lib/xmi/custom_profile/informative.rb +16 -0
- data/lib/xmi/custom_profile/invariant.rb +16 -0
- data/lib/xmi/custom_profile/number.rb +18 -0
- data/lib/xmi/custom_profile/ocl.rb +16 -0
- data/lib/xmi/custom_profile/persistence.rb +20 -0
- data/lib/xmi/custom_profile/publication_date.rb +18 -0
- data/lib/xmi/custom_profile/year_version.rb +18 -0
- data/lib/xmi/custom_profile.rb +12 -143
- data/lib/xmi/ea_root/code_generation.rb +141 -0
- data/lib/xmi/ea_root/extension_lifecycle.rb +52 -0
- data/lib/xmi/ea_root/namespace_handling.rb +39 -0
- data/lib/xmi/ea_root/xml_parsing.rb +51 -0
- data/lib/xmi/ea_root.rb +16 -403
- data/lib/xmi/extension.rb +4 -12
- data/lib/xmi/parser_pipeline.rb +70 -0
- data/lib/xmi/root.rb +3 -12
- data/lib/xmi/sparx/connector/appearance.rb +27 -0
- data/lib/xmi/sparx/connector/connector.rb +52 -0
- data/lib/xmi/sparx/connector/end_base.rb +56 -0
- data/lib/xmi/sparx/connector/end_constraint.rb +33 -0
- data/lib/xmi/sparx/connector/end_modifiers.rb +19 -0
- data/lib/xmi/sparx/connector/end_role.rb +21 -0
- data/lib/xmi/sparx/connector/end_style.rb +17 -0
- data/lib/xmi/sparx/connector/end_type.rb +21 -0
- data/lib/xmi/sparx/connector/labels.rb +27 -0
- data/lib/xmi/sparx/connector/model.rb +19 -0
- data/lib/xmi/sparx/connector/properties.rb +19 -0
- data/lib/xmi/sparx/connector.rb +15 -233
- data/lib/xmi/sparx/element/association.rb +58 -0
- data/lib/xmi/sparx/element/attribute.rb +58 -0
- data/lib/xmi/sparx/element/bounds.rb +19 -0
- data/lib/xmi/sparx/element/code.rb +19 -0
- data/lib/xmi/sparx/element/containment.rb +19 -0
- data/lib/xmi/sparx/element/coords.rb +19 -0
- data/lib/xmi/sparx/element/documentation.rb +17 -0
- data/lib/xmi/sparx/element/element.rb +62 -0
- data/lib/xmi/sparx/element/extended_properties.rb +21 -0
- data/lib/xmi/sparx/element/flags.rb +29 -0
- data/lib/xmi/sparx/element/links.rb +22 -0
- data/lib/xmi/sparx/element/model.rb +26 -0
- data/lib/xmi/sparx/element/package_properties.rb +21 -0
- data/lib/xmi/sparx/element/paths.rb +17 -0
- data/lib/xmi/sparx/element/project.rb +29 -0
- data/lib/xmi/sparx/element/properties.rb +41 -0
- data/lib/xmi/sparx/element/stereotype.rb +17 -0
- data/lib/xmi/sparx/element/style.rb +17 -0
- data/lib/xmi/sparx/element/styleex.rb +17 -0
- data/lib/xmi/sparx/element/tag.rb +32 -0
- data/lib/xmi/sparx/element/times.rb +23 -0
- data/lib/xmi/sparx/element/xrefs.rb +17 -0
- data/lib/xmi/sparx/element.rb +28 -445
- data/lib/xmi/sparx/extension.rb +4 -12
- data/lib/xmi/sparx/gml/application_schema.rb +26 -0
- data/lib/xmi/sparx/gml/code_list.rb +23 -0
- data/lib/xmi/sparx/gml/data_type.rb +18 -0
- data/lib/xmi/sparx/gml/enumeration.rb +18 -0
- data/lib/xmi/sparx/gml/feature_type.rb +21 -0
- data/lib/xmi/sparx/gml/property.rb +24 -0
- data/lib/xmi/sparx/gml/shared_attributes.rb +39 -0
- data/lib/xmi/sparx/gml/type.rb +18 -0
- data/lib/xmi/sparx/gml/union.rb +18 -0
- data/lib/xmi/sparx/gml.rb +10 -125
- data/lib/xmi/sparx/index.rb +248 -0
- data/lib/xmi/sparx/mappings/base_mapping.rb +13 -137
- data/lib/xmi/sparx/root.rb +10 -11
- data/lib/xmi/sparx.rb +1 -0
- data/lib/xmi/uml/annotated_element.rb +16 -0
- data/lib/xmi/uml/association_generalization.rb +20 -0
- data/lib/xmi/uml/bounds.rb +43 -0
- data/lib/xmi/uml/default_value.rb +42 -0
- data/lib/xmi/uml/diagram.rb +25 -0
- data/lib/xmi/uml/member_end.rb +16 -0
- data/lib/xmi/uml/owned_attribute.rb +31 -0
- data/lib/xmi/uml/owned_comment.rb +29 -0
- data/lib/xmi/uml/owned_element.rb +33 -0
- data/lib/xmi/uml/owned_end.rb +34 -0
- data/lib/xmi/uml/owned_literal.rb +23 -0
- data/lib/xmi/uml/owned_operation.rb +22 -0
- data/lib/xmi/uml/owned_parameter.rb +29 -0
- data/lib/xmi/uml/package_import.rb +30 -0
- data/lib/xmi/uml/packaged_element.rb +49 -0
- data/lib/xmi/uml/precondition.rb +22 -0
- data/lib/xmi/uml/profile.rb +43 -0
- data/lib/xmi/uml/profile_application.rb +34 -0
- data/lib/xmi/uml/specification.rb +20 -0
- data/lib/xmi/uml/type.rb +18 -0
- data/lib/xmi/uml/uml_model.rb +29 -0
- data/lib/xmi/uml.rb +27 -502
- data/lib/xmi/version.rb +1 -1
- data/lib/xmi/xmi_identity.rb +46 -0
- data/lib/xmi.rb +11 -7
- metadata +84 -3
- 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
|