xmi 0.3.21 → 0.5.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +13 -6
  3. data/.gitignore +2 -1
  4. data/.rubocop.yml +12 -13
  5. data/.rubocop_todo.yml +150 -13
  6. data/CHANGELOG.md +55 -0
  7. data/CODE_OF_CONDUCT.md +84 -0
  8. data/Gemfile +10 -0
  9. data/README.adoc +319 -6
  10. data/benchmark_parse.rb +60 -0
  11. data/docs/migration.md +141 -0
  12. data/docs/versioning.md +255 -0
  13. data/lib/xmi/add.rb +14 -38
  14. data/lib/xmi/{the_custom_profile.rb → custom_profile.rb} +25 -25
  15. data/lib/xmi/delete.rb +14 -38
  16. data/lib/xmi/difference.rb +14 -38
  17. data/lib/xmi/documentation.rb +16 -101
  18. data/lib/xmi/ea_root.rb +114 -33
  19. data/lib/xmi/extension.rb +6 -6
  20. data/lib/xmi/namespace/dynamic.rb +28 -0
  21. data/lib/xmi/namespace/omg.rb +81 -0
  22. data/lib/xmi/namespace/sparx.rb +39 -0
  23. data/lib/xmi/namespace.rb +9 -0
  24. data/lib/xmi/namespace_detector.rb +138 -0
  25. data/lib/xmi/namespace_registry.rb +119 -0
  26. data/lib/xmi/parsing.rb +113 -0
  27. data/lib/xmi/replace.rb +14 -38
  28. data/lib/xmi/root.rb +49 -213
  29. data/lib/xmi/sparx/connector.rb +241 -0
  30. data/lib/xmi/sparx/custom_profile.rb +19 -0
  31. data/lib/xmi/sparx/diagram.rb +97 -0
  32. data/lib/xmi/sparx/ea_stub.rb +20 -0
  33. data/lib/xmi/{extensions/eauml.rb → sparx/ea_uml.rb} +3 -2
  34. data/lib/xmi/sparx/element.rb +453 -0
  35. data/lib/xmi/sparx/extension.rb +43 -0
  36. data/lib/xmi/{extensions → sparx}/gml.rb +9 -3
  37. data/lib/xmi/sparx/mappings/base_mapping.rb +182 -0
  38. data/lib/xmi/sparx/mappings.rb +10 -0
  39. data/lib/xmi/sparx/primitive_type.rb +18 -0
  40. data/lib/xmi/sparx/root.rb +60 -0
  41. data/lib/xmi/sparx/sys_ph_s.rb +18 -0
  42. data/lib/xmi/sparx.rb +17 -1376
  43. data/lib/xmi/type.rb +37 -0
  44. data/lib/xmi/uml.rb +191 -469
  45. data/lib/xmi/v20110701.rb +81 -0
  46. data/lib/xmi/v20131001.rb +68 -0
  47. data/lib/xmi/v20161101.rb +61 -0
  48. data/lib/xmi/version.rb +1 -1
  49. data/lib/xmi/version_registry.rb +164 -0
  50. data/lib/xmi/versioned.rb +142 -0
  51. data/lib/xmi.rb +83 -11
  52. data/scripts-xmi-profile/profile_xmi_simple.rb +213 -0
  53. data/xmi.gemspec +3 -9
  54. metadata +38 -77
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Simple XMI Performance Profiling Script (no external dependencies)
5
+ #
6
+ # This script helps identify performance bottlenecks using only Ruby's
7
+ # standard library. Run from the xmi repository.
8
+ #
9
+ # Usage:
10
+ # XMI_SAMPLE_FILE=path/to/sample.xmi ruby scripts-xmi-profile/profile_xmi_simple.rb
11
+
12
+ require "bundler/setup"
13
+ require "benchmark"
14
+ require "objspace"
15
+
16
+ begin
17
+ require "xmi"
18
+ rescue LoadError
19
+ puts "ERROR: xmi gem not found. Please run this script from the xmi repository."
20
+ exit 1
21
+ end
22
+
23
+ SAMPLE_FILE = ENV.fetch("XMI_SAMPLE_FILE", nil)
24
+
25
+ unless SAMPLE_FILE && File.exist?(SAMPLE_FILE)
26
+ puts <<~MSG
27
+ ERROR: No sample XMI file specified.
28
+
29
+ Please set the XMI_SAMPLE_FILE environment variable:
30
+ XMI_SAMPLE_FILE=path/to/sample.xmi ruby scripts-xmi-profile/profile_xmi_simple.rb
31
+ MSG
32
+ exit 1
33
+ end
34
+
35
+ puts "=" * 80
36
+ puts "XMI Simple Performance Profile"
37
+ puts "=" * 80
38
+
39
+ xmi_content = File.read(SAMPLE_FILE)
40
+ puts "File: #{SAMPLE_FILE} (#{File.size(SAMPLE_FILE)} bytes)"
41
+ puts
42
+
43
+ # Method call tracing
44
+ puts "-" * 40
45
+ puts "Method Call Tracing (top 30 by calls)"
46
+ puts "-" * 40
47
+
48
+ call_counts = Hash.new(0)
49
+ Hash.new(0.0)
50
+
51
+ trace = TracePoint.new(:call, :c_call) do |tp|
52
+ # Only trace lutaml-model code
53
+ next unless tp.path&.include?("lutaml")
54
+
55
+ method_name = "#{tp.defined_class}##{tp.method_id}"
56
+ call_counts[method_name] += 1
57
+ end
58
+
59
+ # Enable tracing and run
60
+ GC.start
61
+ trace.enable
62
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
63
+
64
+ begin
65
+ Xmi::Sparx::SparxRoot.parse_xml(xmi_content)
66
+ rescue StandardError => e
67
+ puts "Parse error (continuing with profile): #{e.message}"
68
+ end
69
+
70
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
71
+ trace.disable
72
+
73
+ puts "Total parse time: #{(finish - start).round(3)}s"
74
+ puts
75
+
76
+ # Sort by call count
77
+ sorted_by_calls = call_counts.sort_by { |_, count| -count }.first(30)
78
+
79
+ puts "By call count:"
80
+ sorted_by_calls.each do |method, count|
81
+ # Truncate long method names
82
+ display_method = method.length > 70 ? "...#{method[-67..]}" : method
83
+ puts " #{count.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse.rjust(12)}: #{display_method}"
84
+ end
85
+ puts
86
+
87
+ # Look for potential issues
88
+ puts "-" * 40
89
+ puts "Potential Issues"
90
+ puts "-" * 40
91
+
92
+ # Check for methods called excessively
93
+ excessive_threshold = 10_000
94
+ excessive = call_counts.select { |_, count| count > excessive_threshold }
95
+ if excessive.any?
96
+ puts "Methods called more than #{excessive_threshold} times:"
97
+ excessive.sort_by { |_, c| -c }.each do |method, count|
98
+ puts " #{count.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse}: #{method}"
99
+ end
100
+ else
101
+ puts "No methods called more than #{excessive_threshold} times"
102
+ end
103
+ puts
104
+
105
+ # Check for duplicate detection in mapping
106
+ duplicate_checks = call_counts.select { |m, _| m.include?("eql?") || m.include?("==") }
107
+ if duplicate_checks.any?
108
+ puts "Duplicate detection calls:"
109
+ duplicate_checks.sort_by { |_, c| -c }.each do |method, count|
110
+ puts " #{count}: #{method}"
111
+ end
112
+ end
113
+ puts
114
+
115
+ # Memory analysis
116
+ puts "-" * 40
117
+ puts "Memory Analysis"
118
+ puts "-" * 40
119
+
120
+ GC.start
121
+ before = ObjectSpace.count_objects
122
+
123
+ begin
124
+ Xmi::Sparx::SparxRoot.parse_xml(xmi_content)
125
+ rescue StandardError => e
126
+ puts "Parse error (continuing): #{e.message}"
127
+ end
128
+
129
+ GC.start
130
+ after = ObjectSpace.count_objects
131
+
132
+ puts "Object count changes:"
133
+ %i[T_OBJECT T_ARRAY T_HASH T_STRING T_DATA T_SYMBOL].each do |type|
134
+ diff = (after[type] || 0) - (before[type] || 0)
135
+ puts " #{type}: #{diff >= 0 ? '+' : ''}#{diff}"
136
+ end
137
+ puts
138
+
139
+ # Transformation registry analysis
140
+ puts "-" * 40
141
+ puts "Transformation Registry Analysis"
142
+ puts "-" * 40
143
+
144
+ if defined?(Lutaml::Model::TransformationRegistry)
145
+ registry = Lutaml::Model::TransformationRegistry.instance
146
+ begin
147
+ count = begin
148
+ registry.send(:transformations)&.size
149
+ rescue StandardError
150
+ "N/A"
151
+ end
152
+ puts "Registered transformations: #{count}"
153
+ rescue StandardError => e
154
+ puts "Could not access transformation count: #{e.message}"
155
+ end
156
+
157
+ # Try to get cache stats if available
158
+ if registry.respond_to?(:cache_stats)
159
+ puts "Cache stats: #{registry.cache_stats}"
160
+ end
161
+ end
162
+ puts
163
+
164
+ # Check for mapping accumulation
165
+ puts "-" * 40
166
+ puts "Mapping Accumulation Check"
167
+ puts "-" * 40
168
+
169
+ # Look at all loaded classes that include Lutaml::Model::Serialize
170
+ lutaml_classes = ObjectSpace.each_object(Class).select do |klass|
171
+
172
+ klass.include?(Lutaml::Model::Serialize)
173
+ rescue StandardError
174
+ false
175
+
176
+ end
177
+
178
+ puts "Lutaml::Model classes loaded: #{lutaml_classes.size}"
179
+
180
+ # Check for classes with many mappings
181
+ classes_with_many_mappings = lutaml_classes.select do |klass|
182
+ mappings = begin
183
+ klass.mappings_for(:xml)&.elements
184
+ rescue StandardError
185
+ []
186
+ end
187
+ mappings.size > 20
188
+ end
189
+
190
+ if classes_with_many_mappings.any?
191
+ puts "Classes with >20 mappings:"
192
+ classes_with_many_mappings.each do |klass|
193
+ mappings = begin
194
+ klass.mappings_for(:xml)&.elements
195
+ rescue StandardError
196
+ []
197
+ end
198
+ puts " #{klass}: #{mappings.size} mappings"
199
+ end
200
+ else
201
+ puts "No classes with excessive mappings (>20)"
202
+ end
203
+ puts
204
+
205
+ # Summary
206
+ puts "=" * 80
207
+ puts "Summary"
208
+ puts "=" * 80
209
+ puts "Total method calls traced: #{call_counts.values.sum}"
210
+ puts "Unique methods called: #{call_counts.size}"
211
+ puts
212
+ puts "To share this profile with the lutaml-model team:"
213
+ puts " XMI_SAMPLE_FILE=spec/fixtures/full-242.xmi ruby scripts-xmi-profile/profile_xmi_simple.rb > profile_output.txt 2>&1"
data/xmi.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.metadata["homepage_uri"] = spec.homepage
17
17
  spec.metadata["source_code_uri"] = spec.homepage
18
18
  spec.metadata["changelog_uri"] = "https://github.com/lutaml/xmi/releases"
19
+ spec.metadata["rubygems_mfa_required"] = "true"
19
20
 
20
21
  # Specify which files should be added to the gem when it is released.
21
22
  # The `git ls-files -z` loads the files in the RubyGem
@@ -31,13 +32,6 @@ Gem::Specification.new do |spec|
31
32
 
32
33
  spec.required_ruby_version = ">= 3.0.0"
33
34
 
34
- spec.add_runtime_dependency "lutaml-model", "~> 0.7"
35
- spec.add_runtime_dependency "nokogiri"
36
-
37
- spec.add_development_dependency "pry", "~> 0.12.2"
38
- spec.add_development_dependency "rake", "~> 13.0"
39
- spec.add_development_dependency "rspec", "~> 3.11"
40
- spec.add_development_dependency "rspec-xml"
41
- spec.add_development_dependency "rubocop", "~> 1.58"
42
- # spec.add_development_dependency "xml-c14n"
35
+ spec.add_dependency "lutaml-model", "~> 0.8.0"
36
+ spec.add_dependency "nokogiri"
43
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xmi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.21
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-08-12 00:00:00.000000000 Z
11
+ date: 2026-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.7'
19
+ version: 0.8.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.7'
26
+ version: 0.8.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: nokogiri
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,76 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: pry
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 0.12.2
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 0.12.2
55
- - !ruby/object:Gem::Dependency
56
- name: rake
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '13.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '13.0'
69
- - !ruby/object:Gem::Dependency
70
- name: rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '3.11'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '3.11'
83
- - !ruby/object:Gem::Dependency
84
- name: rspec-xml
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '1.58'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '1.58'
111
41
  description: XMI data model parser
112
42
  email:
113
43
  - open.source@ribose.com'
@@ -121,26 +51,56 @@ files:
121
51
  - ".rspec"
122
52
  - ".rubocop.yml"
123
53
  - ".rubocop_todo.yml"
54
+ - CHANGELOG.md
55
+ - CODE_OF_CONDUCT.md
124
56
  - Gemfile
125
57
  - README.adoc
126
58
  - Rakefile
59
+ - benchmark_parse.rb
127
60
  - bin/console
128
61
  - bin/setup
62
+ - docs/migration.md
63
+ - docs/versioning.md
129
64
  - lib/xmi.rb
130
65
  - lib/xmi/add.rb
66
+ - lib/xmi/custom_profile.rb
131
67
  - lib/xmi/delete.rb
132
68
  - lib/xmi/difference.rb
133
69
  - lib/xmi/documentation.rb
134
70
  - lib/xmi/ea_root.rb
135
71
  - lib/xmi/extension.rb
136
- - lib/xmi/extensions/eauml.rb
137
- - lib/xmi/extensions/gml.rb
72
+ - lib/xmi/namespace.rb
73
+ - lib/xmi/namespace/dynamic.rb
74
+ - lib/xmi/namespace/omg.rb
75
+ - lib/xmi/namespace/sparx.rb
76
+ - lib/xmi/namespace_detector.rb
77
+ - lib/xmi/namespace_registry.rb
78
+ - lib/xmi/parsing.rb
138
79
  - lib/xmi/replace.rb
139
80
  - lib/xmi/root.rb
140
81
  - lib/xmi/sparx.rb
141
- - lib/xmi/the_custom_profile.rb
82
+ - lib/xmi/sparx/connector.rb
83
+ - lib/xmi/sparx/custom_profile.rb
84
+ - lib/xmi/sparx/diagram.rb
85
+ - lib/xmi/sparx/ea_stub.rb
86
+ - lib/xmi/sparx/ea_uml.rb
87
+ - lib/xmi/sparx/element.rb
88
+ - lib/xmi/sparx/extension.rb
89
+ - lib/xmi/sparx/gml.rb
90
+ - lib/xmi/sparx/mappings.rb
91
+ - lib/xmi/sparx/mappings/base_mapping.rb
92
+ - lib/xmi/sparx/primitive_type.rb
93
+ - lib/xmi/sparx/root.rb
94
+ - lib/xmi/sparx/sys_ph_s.rb
95
+ - lib/xmi/type.rb
142
96
  - lib/xmi/uml.rb
97
+ - lib/xmi/v20110701.rb
98
+ - lib/xmi/v20131001.rb
99
+ - lib/xmi/v20161101.rb
143
100
  - lib/xmi/version.rb
101
+ - lib/xmi/version_registry.rb
102
+ - lib/xmi/versioned.rb
103
+ - scripts-xmi-profile/profile_xmi_simple.rb
144
104
  - sig/xmi.rbs
145
105
  - xmi.gemspec
146
106
  homepage: https://github.com/lutaml/xmi
@@ -150,6 +110,7 @@ metadata:
150
110
  homepage_uri: https://github.com/lutaml/xmi
151
111
  source_code_uri: https://github.com/lutaml/xmi
152
112
  changelog_uri: https://github.com/lutaml/xmi/releases
113
+ rubygems_mfa_required: 'true'
153
114
  post_install_message:
154
115
  rdoc_options: []
155
116
  require_paths: