xmi 0.5.12 → 0.6.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/CLAUDE.md +43 -14
  4. data/lib/xmi/add.rb +0 -3
  5. data/lib/xmi/delete.rb +0 -3
  6. data/lib/xmi/difference.rb +0 -2
  7. data/lib/xmi/documentation.rb +0 -2
  8. data/lib/xmi/ea_root.rb +5 -4
  9. data/lib/xmi/namespace.rb +3 -3
  10. data/lib/xmi/replace.rb +0 -3
  11. data/lib/xmi/root.rb +0 -3
  12. data/lib/xmi/type.rb +0 -2
  13. data/lib/xmi/uml/association.rb +0 -2
  14. data/lib/xmi/uml/association_class.rb +0 -2
  15. data/lib/xmi/uml/bounds.rb +2 -8
  16. data/lib/xmi/uml/data_type.rb +0 -2
  17. data/lib/xmi/uml/default_value.rb +0 -2
  18. data/lib/xmi/uml/dependency.rb +0 -2
  19. data/lib/xmi/uml/diagram.rb +2 -8
  20. data/lib/xmi/uml/enumeration.rb +0 -2
  21. data/lib/xmi/uml/extension.rb +0 -2
  22. data/lib/xmi/uml/instance_specification.rb +0 -2
  23. data/lib/xmi/uml/interface.rb +0 -2
  24. data/lib/xmi/uml/lower_value.rb +0 -2
  25. data/lib/xmi/uml/owned_element.rb +4 -8
  26. data/lib/xmi/uml/package.rb +0 -2
  27. data/lib/xmi/uml/package_import.rb +0 -2
  28. data/lib/xmi/uml/primitive_type.rb +0 -2
  29. data/lib/xmi/uml/profile.rb +11 -10
  30. data/lib/xmi/uml/profile_application.rb +4 -10
  31. data/lib/xmi/uml/realization.rb +0 -2
  32. data/lib/xmi/uml/signal.rb +0 -2
  33. data/lib/xmi/uml/stereotype.rb +0 -2
  34. data/lib/xmi/uml/uml_class.rb +0 -2
  35. data/lib/xmi/uml/uml_model.rb +0 -2
  36. data/lib/xmi/uml/upper_value.rb +0 -2
  37. data/lib/xmi/uml/usage.rb +0 -2
  38. data/lib/xmi/uml/waypoint.rb +2 -8
  39. data/lib/xmi/uml.rb +0 -1
  40. data/lib/xmi/uml_di/base.rb +22 -0
  41. data/lib/xmi/uml_di.rb +10 -0
  42. data/lib/xmi/version.rb +1 -1
  43. data/lib/xmi.rb +21 -24
  44. metadata +4 -6
  45. data/TODO.next/01-packaged-element-typed-subclasses.md +0 -94
  46. data/TODO.next/03-real-sparx-instancespec-fixture.md +0 -56
  47. data/TODO.next/README.md +0 -17
  48. data/lib/xmi/uml/profile_attributes.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4268a73b32cabe65fa9a63dc4e87588941df98e4480697e704e19d33be0d4d2f
4
- data.tar.gz: b92789685eee2191f08b81537f1a4c6740ae5bdba96a48060992174ee7a2b58a
3
+ metadata.gz: db371f76bfe7fa3b6f16392f150e7bdd4a70b390053317de58ae11ea4d469fa8
4
+ data.tar.gz: b5d0ac779b25967ba94abaa37ec726414a296680c313d451dbc7f3ec230ab4f1
5
5
  SHA512:
6
- metadata.gz: abcee32a264c8519d7e7a5110cc89e6327e20dce2ded8999266aa928c67e59daf0f993f3b8577d6c628137345b10367e9fbb23b8d832c1d49bafbbeda83ec43d
7
- data.tar.gz: 2d46d5677820d183a9d33418ead0ff9cf4ffe8d887aa16e629c27d782e282baa4a94ca08d8bc1cb531728e781d4613e09f371e7454b3fc94bb306271807ddadf
6
+ metadata.gz: 6caff8c35f558fb0394b45cea65f04094ffc546b69844f2a7d8ce1fa946a1e961ece15e5569ae170a82e33b57dd007ea313e0f3d6c966251ef18d4dcefe8d94b
7
+ data.tar.gz: e3f580a640f314257ecd3a0c8d387dbb4e2136c7845b17dbaa99e79ab3b3bda00eb4291c77dcb3e9089bdb3bafdd8396a501b64c5b1faab291eb0f703bc1aa46
data/.gitignore CHANGED
@@ -14,3 +14,11 @@
14
14
  Gemfile.lock
15
15
  .DS_Store
16
16
  /old-docs
17
+
18
+ # Editor / sed transient files
19
+ *.bak
20
+ *.swp
21
+ *~
22
+
23
+ # Local TODO scratchpads (track work in issues/PRs instead)
24
+ TODO*
data/CLAUDE.md CHANGED
@@ -102,24 +102,39 @@ end
102
102
 
103
103
  ### Model Definition Pattern
104
104
 
105
- Models use lutaml-model syntax with explicit namespace declarations:
106
- ```ruby
107
- class MyModel < Lutaml::Model::Serializable
108
- attribute :id, ::Xmi::Type::XmiId
105
+ Concrete UML classes inherit from `Xmi::Uml::Base`, which carries
106
+ the shared boilerplate (`skip_reference_registration`, `type` and
107
+ `id` attrs, UML namespace, and their `map_attribute` lines).
108
+ Subclasses declare only their unique attributes and the `root`
109
+ element name. Verified via spike: lutaml-model inherits `xml do`
110
+ block contents (namespace + map_attribute) from the parent class.
109
111
 
110
- xml do
111
- root "Model"
112
- namespace ::Xmi::Namespace::Omg::Uml
113
- namespace_scope [::Xmi::Namespace::Omg::Xmi, ::Xmi::Namespace::Omg::Uml]
114
-
115
- # Attributes with XMI namespace require explicit declaration
116
- map_attribute "id", to: :id,
117
- namespace: "http://www.omg.org/spec/XMI/20131001",
118
- prefix: "xmi"
112
+ UML Diagram Interchange elements (Bounds, Waypoint, Diagram,
113
+ OwnedElement) inherit from `Xmi::UmlDi::Base` instead — same
114
+ pattern, different namespace.
115
+
116
+ ```ruby
117
+ # lib/xmi/uml/my_element.rb
118
+ module Xmi
119
+ module Uml
120
+ class MyElement < Base
121
+ attribute :name, :string
122
+
123
+ xml do
124
+ root "myElement"
125
+ map_attribute "name", to: :name
126
+ end
127
+ end
119
128
  end
120
129
  end
121
130
  ```
122
131
 
132
+ For backward compatibility, raw `Lutaml::Model::Serializable`
133
+ inheritance still works but is discouraged for new UML classes.
134
+ The small reference-holder classes (AnnotatedElement, MemberEnd,
135
+ Type, ImportedPackage) intentionally stay direct from Serializable
136
+ because they don't carry the type+id pair that Base provides.
137
+
123
138
  ### Dynamic Extension Loading
124
139
 
125
140
  `Xmi::EaRoot.load_extension(xml_path)` dynamically generates Ruby classes from EA MDG extension XML files. This creates stereotype classes under `Xmi::EaRoot::{ModuleName}::{ClassName}` and updates `Root` mappings.
@@ -128,6 +143,15 @@ Extensions use `NamespaceRegistry` to look up or create namespace classes dynami
128
143
  - Existing namespace URIs resolve to predefined classes
129
144
  - New URIs create dynamic classes under `Xmi::Namespace::Dynamic::{ModuleName}`
130
145
 
146
+ ### Polymorphic Dispatch
147
+
148
+ Two attributes use lutaml-model's polymorphic dispatch on `xmi:type`:
149
+
150
+ - `PackagedElement.packaged_element` (and `UmlModel.packaged_element`) — dispatches to typed subclasses (`UmlClass`, `Association`, `Interface`, `InstanceSpecification`, etc.). Map: `Xmi::Uml::PACKAGED_ELEMENT_POLYMORPHIC_MAP` in `lib/xmi/uml/packaged_element.rb`.
151
+ - `Slot.value`, `OwnedAttribute.upper_value`/`lower_value`/`default_value`, `OwnedEnd.upper_value`/`lower_value`/`default_value`, `OwnedParameter.upper_value`/`lower_value`/`default_value` — dispatch to ValueSpecification subclasses (`OpaqueExpression`, `LiteralString`, `LiteralInteger`, etc.). Map: `Xmi::Uml::VALUE_SPECIFICATION_POLYMORPHIC_MAP` in `lib/xmi/uml/value_specification.rb`.
152
+
153
+ **Known limitation:** polymorphic dispatch crashes with `TypeError` if the discriminator is missing or unrecognized. This is a lutaml-model upstream issue (it calls `Object.const_get(nil)`); the failure mode is locked in by `spec/xmi/uml/polymorphic_robustness_spec.rb`. Fix lives upstream, not here.
154
+
131
155
  ### Key Files
132
156
 
133
157
  | File | Purpose |
@@ -136,7 +160,12 @@ Extensions use `NamespaceRegistry` to look up or create namespace classes dynami
136
160
  | `lib/xmi/sparx.rb` | Module with autoload declarations for Sparx components |
137
161
  | `lib/xmi/sparx/root.rb` | Main `Root` class with parsing and namespace normalization |
138
162
  | `lib/xmi/root.rb` | Base `Root` class with common XMI attributes |
139
- | `lib/xmi/uml.rb` | UML model classes (UmlModel, PackagedElement, etc.) |
163
+ | `lib/xmi/uml.rb` | UML model autoload entries |
164
+ | `lib/xmi/uml/base.rb` | `Xmi::Uml::Base` — common boilerplate for UML classes |
165
+ | `lib/xmi/uml_di.rb` | UML Diagram Interchange autoload entries |
166
+ | `lib/xmi/uml_di/base.rb` | `Xmi::UmlDi::Base` — common boilerplate for UMLDI classes |
167
+ | `lib/xmi/uml/packaged_element.rb` | `PackagedElement` + `PACKAGED_ELEMENT_POLYMORPHIC_MAP` |
168
+ | `lib/xmi/uml/value_specification.rb` | `ValueSpecification` abstract base + `VALUE_SPECIFICATION_POLYMORPHIC_MAP` |
140
169
  | `lib/xmi/ea_root.rb` | Dynamic extension loading from MDG XML |
141
170
  | `lib/xmi/type.rb` | Custom types with namespace declarations (XmiId, XmiType, etc.) |
142
171
  | `lib/xmi/namespace/omg.rb` | OMG namespace classes (XMI, UML, UmlDi, UmlDc) |
data/lib/xmi/add.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "difference"
4
- require_relative "extension"
5
-
6
3
  module Xmi
7
4
  class Add < Lutaml::Model::Serializable
8
5
  skip_reference_registration
data/lib/xmi/delete.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "difference"
4
- require_relative "extension"
5
-
6
3
  module Xmi
7
4
  class Delete < Lutaml::Model::Serializable
8
5
  skip_reference_registration
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "extension"
4
-
5
3
  module Xmi
6
4
  class Difference < Lutaml::Model::Serializable
7
5
  skip_reference_registration
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "extension"
4
-
5
3
  module Xmi
6
4
  class Documentation < Lutaml::Model::Serializable
7
5
  skip_reference_registration
data/lib/xmi/ea_root.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "nokogiri"
4
- require_relative "ea_root/xml_parsing"
5
- require_relative "ea_root/code_generation"
6
- require_relative "ea_root/extension_lifecycle"
7
- require_relative "ea_root/namespace_handling"
8
4
 
9
5
  module Xmi
10
6
  class EaRoot
7
+ autoload :XmlParsing, "xmi/ea_root/xml_parsing"
8
+ autoload :CodeGeneration, "xmi/ea_root/code_generation"
9
+ autoload :ExtensionLifecycle, "xmi/ea_root/extension_lifecycle"
10
+ autoload :NamespaceHandling, "xmi/ea_root/namespace_handling"
11
+
11
12
  extend XmlParsing
12
13
  extend CodeGeneration
13
14
  extend ExtensionLifecycle
data/lib/xmi/namespace.rb CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Xmi
4
4
  module Namespace
5
+ autoload :Omg, "xmi/namespace/omg"
6
+ autoload :Sparx, "xmi/namespace/sparx"
7
+ autoload :Dynamic, "xmi/namespace/dynamic"
5
8
  end
6
9
  end
7
-
8
- require_relative "namespace/omg"
9
- require_relative "namespace/sparx"
data/lib/xmi/replace.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "difference"
4
- require_relative "extension"
5
-
6
3
  module Xmi
7
4
  class Replace < Lutaml::Model::Serializable
8
5
  skip_reference_registration
data/lib/xmi/root.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "documentation"
4
- require_relative "uml"
5
-
6
3
  module Xmi
7
4
  class Root < Lutaml::Model::Serializable
8
5
  skip_reference_registration
data/lib/xmi/type.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "namespace"
4
-
5
3
  module Xmi
6
4
  module Type
7
5
  class XmiIdRef < Lutaml::Model::Type::String
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Association">`. Binary
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:AssociationClass">`. An
@@ -2,10 +2,8 @@
2
2
 
3
3
  module Xmi
4
4
  module Uml
5
- class Bounds < Lutaml::Model::Serializable
6
- skip_reference_registration
7
- attribute :type, ::Xmi::Type::XmiType
8
- attribute :id, ::Xmi::Type::XmiId
5
+ # UMLDI `<bounds>` element — a rectangle in diagram coordinates.
6
+ class Bounds < ::Xmi::UmlDi::Base
9
7
  attribute :x, :integer
10
8
  attribute :y, :integer
11
9
  attribute :height, :integer
@@ -13,10 +11,6 @@ module Xmi
13
11
 
14
12
  xml do
15
13
  root "bounds"
16
- namespace ::Xmi::Namespace::Omg::UmlDi
17
-
18
- map_attribute "type", to: :type
19
- map_attribute "id", to: :id
20
14
  map_attribute "x", to: :x
21
15
  map_attribute "y", to: :y
22
16
  map_attribute "height", to: :height
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:DataType">`. Classifier
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "value_specification"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # Default value wrapper. Semantically a ValueSpecification
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Dependency">`. A relationship
@@ -2,20 +2,14 @@
2
2
 
3
3
  module Xmi
4
4
  module Uml
5
- class Diagram < Lutaml::Model::Serializable
6
- skip_reference_registration
7
- attribute :type, ::Xmi::Type::XmiType
8
- attribute :id, ::Xmi::Type::XmiId
5
+ # UMLDI `<Diagram>` element — root of a diagram's interchange view.
6
+ class Diagram < ::Xmi::UmlDi::Base
9
7
  attribute :is_frame, :boolean
10
8
  attribute :model_element, :string
11
9
  attribute :owned_element, OwnedElement, collection: true
12
10
 
13
11
  xml do
14
12
  root "Diagram"
15
- namespace ::Xmi::Namespace::Omg::UmlDi
16
-
17
- map_attribute "type", to: :type
18
- map_attribute "id", to: :id
19
13
  map_attribute "isFrame", to: :is_frame
20
14
  map_attribute "modelElement", to: :model_element
21
15
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Enumeration">`. Named
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Extension">`. An extension
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:InstanceSpecification">`.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Interface">`. Contract
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "default_value"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  class LowerValue < DefaultValue
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Xmi
4
4
  module Uml
5
- class OwnedElement < Lutaml::Model::Serializable
6
- skip_reference_registration
7
- attribute :type, ::Xmi::Type::XmiType
8
- attribute :id, ::Xmi::Type::XmiId
5
+ # UMLDI `<ownedElement>` — a diagram element (shape, label, etc.).
6
+ # Carries text, optional nested ownedElement children, bounds,
7
+ # and source/target/waypoint for connectors.
8
+ class OwnedElement < ::Xmi::UmlDi::Base
9
9
  attribute :text, :string
10
10
  attribute :model_element, :string
11
11
  attribute :owned_element, OwnedElement, collection: true
@@ -16,10 +16,6 @@ module Xmi
16
16
 
17
17
  xml do
18
18
  root "ownedElement"
19
- namespace ::Xmi::Namespace::Omg::UmlDi
20
-
21
- map_attribute "type", to: :type
22
- map_attribute "id", to: :id
23
19
  map_attribute "text", to: :text
24
20
  map_attribute "modelElement", to: :model_element
25
21
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Package">`. Container for
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "imported_package"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  class PackageImport < Lutaml::Model::Serializable
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:PrimitiveType">`.
@@ -1,23 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "profile_attributes"
4
-
5
3
  module Xmi
6
4
  module Uml
7
- class Profile < Lutaml::Model::Serializable
8
- skip_reference_registration
9
- include ProfileAttributes
10
-
5
+ # UML `<Profile>` element (UML 2.5 §22.3). A stereotyped package
6
+ # that extends the UML metamodel. Carries owned comments, package
7
+ # imports, nested packaged elements, and profile-specific metadata
8
+ # (nsPrefix, metamodelReference).
9
+ class Profile < Base
10
+ attribute :name, :string
11
+ attribute :ns_prefix, :string
12
+ attribute :metamodel_reference, :string
13
+ attribute :packaged_element, PackagedElement, collection: true
14
+ attribute :package_import, PackageImport, collection: true
11
15
  attribute :owned_comment, OwnedComment, collection: true
12
16
 
13
17
  xml do
14
18
  root "Profile"
15
- namespace ::Xmi::Namespace::Omg::Uml
16
-
17
- map_attribute "id", to: :id
18
19
  map_attribute "name", to: :name
19
- map_attribute "metamodelReference", to: :metamodel_reference
20
20
  map_attribute "nsPrefix", to: :ns_prefix
21
+ map_attribute "metamodelReference", to: :metamodel_reference
21
22
 
22
23
  map_element "ownedComment", to: :owned_comment, value_map: VALUE_MAP
23
24
  map_element "packageImport", to: :package_import, value_map: VALUE_MAP
@@ -1,21 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "profile_application_applied_profile"
4
-
5
3
  module Xmi
6
4
  module Uml
7
- class ProfileApplication < Lutaml::Model::Serializable
8
- attribute :type, ::Xmi::Type::XmiType
9
- attribute :id, ::Xmi::Type::XmiId
5
+ # UML `<profileApplication>` element — records that a Profile has
6
+ # been applied to the containing Package. Carries a single
7
+ # `<appliedProfile>` child holding the href reference.
8
+ class ProfileApplication < Base
10
9
  attribute :applied_profile, ProfileApplicationAppliedProfile
11
10
 
12
11
  xml do
13
12
  root "profileApplication"
14
- namespace ::Xmi::Namespace::Omg::Uml
15
-
16
- map_attribute "type", to: :type
17
- map_attribute "id", to: :id
18
-
19
13
  map_element "appliedProfile", to: :applied_profile
20
14
  end
21
15
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Realization">`. Generic
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Signal">`. A signal is a
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Stereotype">. A stereotype
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Class">`. Classifier with
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  class UmlModel < Base
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "default_value"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  class UpperValue < DefaultValue
data/lib/xmi/uml/usage.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "packaged_element"
4
-
5
3
  module Xmi
6
4
  module Uml
7
5
  # UML `<packagedElement xmi:type="uml:Usage">. A Dependency
@@ -2,19 +2,13 @@
2
2
 
3
3
  module Xmi
4
4
  module Uml
5
- class Waypoint < Lutaml::Model::Serializable
6
- skip_reference_registration
7
- attribute :type, ::Xmi::Type::XmiType
8
- attribute :id, ::Xmi::Type::XmiId
5
+ # UMLDI `<waypoint>` element — a point on a connector path.
6
+ class Waypoint < ::Xmi::UmlDi::Base
9
7
  attribute :x, :integer
10
8
  attribute :y, :integer
11
9
 
12
10
  xml do
13
11
  root "waypoint"
14
- namespace ::Xmi::Namespace::Omg::UmlDi
15
-
16
- map_attribute "type", to: :type
17
- map_attribute "id", to: :id
18
12
  map_attribute "x", to: :x
19
13
  map_attribute "y", to: :y
20
14
  end
data/lib/xmi/uml.rb CHANGED
@@ -53,7 +53,6 @@ module Xmi
53
53
  autoload :ImportedPackage, "xmi/uml/imported_package"
54
54
  autoload :PackageImport, "xmi/uml/package_import"
55
55
  autoload :UmlModel, "xmi/uml/uml_model"
56
- autoload :ProfileAttributes, "xmi/uml/profile_attributes"
57
56
  autoload :Profile, "xmi/uml/profile"
58
57
  end
59
58
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Xmi
4
+ module UmlDi
5
+ # Common base for concrete UMLDI element classes. Parallel to
6
+ # Xmi::Uml::Base but in the UMLDI namespace (diagram interchange).
7
+ #
8
+ # Subclasses declare only their unique attributes + root element.
9
+ class Base < Lutaml::Model::Serializable
10
+ skip_reference_registration
11
+ attribute :type, ::Xmi::Type::XmiType
12
+ attribute :id, ::Xmi::Type::XmiId
13
+
14
+ xml do
15
+ namespace ::Xmi::Namespace::Omg::UmlDi
16
+
17
+ map_attribute "type", to: :type
18
+ map_attribute "id", to: :id
19
+ end
20
+ end
21
+ end
22
+ end
data/lib/xmi/uml_di.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Xmi
4
+ # UML Diagram Interchange (UMLDI) classes. Parallel to Xmi::Uml
5
+ # but in the UMLDI namespace (http://www.omg.org/spec/UML/20131001/UMLDI).
6
+ # Used for diagram elements: Bounds, Waypoint, Diagram, OwnedElement.
7
+ module UmlDi
8
+ autoload :Base, "xmi/uml_di/base"
9
+ end
10
+ end
data/lib/xmi/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Xmi
4
- VERSION = "0.5.12"
4
+ VERSION = "0.6.0"
5
5
  end
data/lib/xmi.rb CHANGED
@@ -16,15 +16,28 @@ module Lutaml
16
16
  end
17
17
  end
18
18
 
19
- require_relative "xmi/version"
20
- require_relative "xmi/namespace"
21
- require_relative "xmi/namespace/dynamic"
22
- require_relative "xmi/type"
23
- require_relative "xmi/namespace_detector"
24
- require_relative "xmi/namespace_registry"
25
- require_relative "xmi/xmi_identity"
26
-
27
19
  module Xmi
20
+ autoload :VERSION, "xmi/version"
21
+ autoload :Namespace, "xmi/namespace"
22
+ autoload :Type, "xmi/type"
23
+ autoload :NamespaceDetector, "xmi/namespace_detector"
24
+ autoload :NamespaceRegistry, "xmi/namespace_registry"
25
+ autoload :XmiIdentity, "xmi/xmi_identity"
26
+ autoload :Versioned, "xmi/versioned"
27
+ autoload :VersionRegistry, "xmi/version_registry"
28
+ autoload :V20110701, "xmi/v20110701"
29
+ autoload :V20131001, "xmi/v20131001"
30
+ autoload :V20161101, "xmi/v20161101"
31
+ autoload :Add, "xmi/add"
32
+ autoload :Delete, "xmi/delete"
33
+ autoload :Difference, "xmi/difference"
34
+ autoload :Documentation, "xmi/documentation"
35
+ autoload :Extension, "xmi/extension"
36
+ autoload :Replace, "xmi/replace"
37
+ autoload :EaRoot, "xmi/ea_root"
38
+ autoload :Uml, "xmi/uml"
39
+ autoload :UmlDi, "xmi/uml_di"
40
+
28
41
  class Error < StandardError; end
29
42
 
30
43
  # Shared value_map for XMI elements.
@@ -52,22 +65,6 @@ end
52
65
  # Bootstrap the namespace registry
53
66
  Xmi::NamespaceRegistry.bootstrap!
54
67
 
55
- # Version infrastructure
56
- require_relative "xmi/versioned"
57
- require_relative "xmi/version_registry"
58
- require_relative "xmi/v20110701"
59
- require_relative "xmi/v20131001"
60
- require_relative "xmi/v20161101"
61
-
62
- require_relative "xmi/add"
63
- require_relative "xmi/delete"
64
- require_relative "xmi/difference"
65
- require_relative "xmi/documentation"
66
- require_relative "xmi/extension"
67
- require_relative "xmi/replace"
68
- require_relative "xmi/ea_root"
69
- require_relative "xmi/uml"
70
-
71
68
  module Xmi
72
69
  # Lazy-loaded top-level modules — autoload avoids loading these
73
70
  # until their constants are actually referenced at runtime.
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.5.12
4
+ version: 0.6.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: 2026-07-02 00:00:00.000000000 Z
11
+ date: 2026-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -57,9 +57,6 @@ files:
57
57
  - Gemfile
58
58
  - README.adoc
59
59
  - Rakefile
60
- - TODO.next/01-packaged-element-typed-subclasses.md
61
- - TODO.next/03-real-sparx-instancespec-fixture.md
62
- - TODO.next/README.md
63
60
  - bin/console
64
61
  - bin/setup
65
62
  - docs/migration.md
@@ -200,7 +197,6 @@ files:
200
197
  - lib/xmi/uml/profile.rb
201
198
  - lib/xmi/uml/profile_application.rb
202
199
  - lib/xmi/uml/profile_application_applied_profile.rb
203
- - lib/xmi/uml/profile_attributes.rb
204
200
  - lib/xmi/uml/realization.rb
205
201
  - lib/xmi/uml/signal.rb
206
202
  - lib/xmi/uml/slot.rb
@@ -213,6 +209,8 @@ files:
213
209
  - lib/xmi/uml/usage.rb
214
210
  - lib/xmi/uml/value_specification.rb
215
211
  - lib/xmi/uml/waypoint.rb
212
+ - lib/xmi/uml_di.rb
213
+ - lib/xmi/uml_di/base.rb
216
214
  - lib/xmi/v20110701.rb
217
215
  - lib/xmi/v20131001.rb
218
216
  - lib/xmi/v20161101.rb
@@ -1,94 +0,0 @@
1
- # 01 — PackagedElement typed subclasses (Phase B remaining)
2
-
3
- **Status: PARTIAL — Phase A landed (2026-07-03); Phase B (narrowing
4
- attrs to subclasses) deferred.**
5
-
6
- ## What landed (Phase A)
7
-
8
- Polymorphic dispatch on `PackagedElement.packaged_element` and
9
- `UmlModel.packaged_element`. Each `<packagedElement xmi:type="uml:X">`
10
- now parses to a corresponding `Xmi::Uml::X` subclass:
11
-
12
- | xmi:type | Ruby class |
13
- |---|---|
14
- | uml:Class | `Xmi::Uml::UmlClass` |
15
- | uml:Association | `Xmi::Uml::Association` |
16
- | uml:Interface | `Xmi::Uml::Interface` |
17
- | uml:InstanceSpecification | `Xmi::Uml::InstanceSpecification` |
18
- | uml:DataType | `Xmi::Uml::DataType` |
19
- | uml:PrimitiveType | `Xmi::Uml::PrimitiveType` |
20
- | uml:Enumeration | `Xmi::Uml::Enumeration` |
21
- | uml:Package | `Xmi::Uml::Package` |
22
- | uml:Realization | `Xmi::Uml::Realization` |
23
-
24
- Dispatch map: `Xmi::Uml::PACKAGED_ELEMENT_POLYMORPHIC_MAP` in
25
- `lib/xmi/uml/packaged_element.rb`. Spec coverage:
26
- `spec/xmi/uml/packaged_element_dispatch_spec.rb` (17 examples).
27
-
28
- Subclasses currently inherit the **full union-bag attribute set**
29
- from `PackagedElement`. Consumers can dispatch on `is_a?(Xmi::Uml::X)`
30
- for type-specific behavior, but accessing the wrong attr on the wrong
31
- type still returns nil/empty rather than raising.
32
-
33
- ## What's deferred (Phase B)
34
-
35
- Narrow each subclass's attribute set to its UML-2.5-conformant subset.
36
- Examples:
37
-
38
- | Class | Valid attrs (today, all inherited) |
39
- |---|---|
40
- | UmlClass | owned_attribute, owned_operation, owned_comment, generalization, interface_realization, nested packaged_element |
41
- | Association | owned_end, member_end, member_ends |
42
- | InstanceSpecification | classifier, slot, specification |
43
- | Interface | owned_operation, generalization |
44
- | Enumeration | owned_literal |
45
- | DataType | owned_attribute, owned_operation |
46
- | PrimitiveType | (none) |
47
- | Realization | supplier, client |
48
- | Package | nested packaged_element |
49
-
50
- After Phase B, `instance.owned_attribute` raises NoMethodError on an
51
- InstanceSpecification — the type system catches the misuse at runtime.
52
-
53
- ## Why Phase B is deferred
54
-
55
- - **Breaking change.** Every consumer that accesses attrs via the
56
- base `PackagedElement` type breaks. The `lutaml/ea` transformer
57
- walks packaged_element generically; it would need type-specific
58
- dispatch added.
59
- - **Test churn.** Every Sparx fixture regression test that accesses
60
- `pe.owned_attribute` (etc.) on a generic PackagedElement needs
61
- updating.
62
- - **Limited semantic gain.** Phase A already gives consumers the
63
- type tag. Phase B catches programming errors but doesn't enable
64
- new functionality.
65
- - The original TODO.next/01 design doc proposed Phase A as
66
- "risk-free" and Phase B as the "breaking change." That framing
67
- holds.
68
-
69
- ## Rollout strategy for Phase B
70
-
71
- 1. Survey every consumer of `PackagedElement` attrs in `lutaml/ea`,
72
- `lutaml/lutaml-uml`, and downstream.
73
- 2. For each consumer, change to type-specific dispatch:
74
- ```ruby
75
- case pe
76
- when Xmi::Uml::UmlClass then pe.owned_attribute ...
77
- when Xmi::Uml::Association then pe.owned_end ...
78
- end
79
- ```
80
- 3. Once consumers are type-aware, narrow subclass attrs.
81
- 4. Remove the narrowed attrs from `PackagedElement`.
82
-
83
- This is a multi-PR change. Each step should land separately so
84
- bisect works.
85
-
86
- ## Open questions
87
-
88
- - Should `Generalization` move from `packagedElement` to its own
89
- child element shape to match OMG XMI? Sparx uses both. Defer.
90
- - How to handle EA's `uml:ExtensionEnd` and other Sparx-isms? Treat
91
- as subclasses of the closest OMG type.
92
- - The polymorphic dispatch failure mode (unknown xmi:type raises
93
- TypeError) is locked in by `polymorphic_robustness_spec.rb`. Phase B
94
- doesn't fix this; it's a separate concern.
@@ -1,56 +0,0 @@
1
- # 03 — Real Sparx InstanceSpecification fixture (FUTURE)
2
-
3
- **Status: FUTURE — requires Sparx EA access to acquire the fixture.
4
- Migrated from `TODO.refactor/16` (2026-07-02).**
5
-
6
- ## Problem
7
-
8
- The fixture added in TODO.refactor/08
9
- (`spec/fixtures/sparx-instance-specification.xmi`) is hand-authored
10
- to match Sparx EA's mixed-prefix style. It is structurally faithful
11
- but not byte-identical to real EA output.
12
-
13
- Several details can drift between synthetic and real:
14
-
15
- - Whitespace and indentation (tabs vs spaces, blank lines).
16
- - Attribute ordering within an element.
17
- - Presence of EA-specific boilerplate (`xmi:Documentation exporter="Enterprise Architect" exporterVersion="..."`).
18
- - Sparx's `EAID_` GUID format (uppercase hex with underscores, vs.
19
- the synthetic lowercase).
20
- - Inclusion of `<xrefs>` elements on slot values (Sparx adds
21
- cross-references for tracked links).
22
- - The `<extensions>` element with EA-specific `<elements>` and
23
- `<connectors>` sections.
24
-
25
- ## Goal
26
-
27
- Acquire a real Sparx EA export that contains at least one:
28
-
29
- - `<packagedElement xmi:type="uml:InstanceSpecification">` with
30
- `<slot>` children carrying `<value>` of various `xmi:type`.
31
- - `<interfaceRealization>` (strict OMG form, even though current
32
- Sparx collapses to `uml:Realization`).
33
-
34
- Replace `sparx-instance-specification.xmi` with the real fixture,
35
- or add it as a sibling file. Update parity specs to use the real
36
- fixture.
37
-
38
- ## Acquisition
39
-
40
- Requires Sparx EA access. Suggested steps:
41
-
42
- 1. In EA, create a small model with one Class, one
43
- InstanceSpecification, and one InterfaceRealization.
44
- 2. Publish to XMI (EA's "Publish to File" or "Export to XMI").
45
- 3. Trim sensitive content if any.
46
- 4. Commit the fixture with a `<!-- Exported from Sparx EA vX.Y on
47
- YYYY-MM-DD, trimmed for the lutaml/xmi test suite. -->` header.
48
-
49
- ## Verification
50
-
51
- - Real fixture parses without error.
52
- - All existing parity specs continue to pass (or are updated to
53
- match real content).
54
- - Coverage of `<value>` `xmi:type` variants matches what real EA
55
- emits (OpaqueExpression is the common case; LiteralString for
56
- default values).
data/TODO.next/README.md DELETED
@@ -1,17 +0,0 @@
1
- # TODO.next — xmi gem follow-ups
2
-
3
- Open design items after the OwnedEnd schema migration and
4
- ValueSpecification polymorphic dispatch landed. Each file has a
5
- Status header:
6
-
7
- - **DONE** — completed; kept for context
8
- - **DESIGN-ONLY** — design document, not implemented; awaiting user direction
9
- - **FUTURE** — needs resources (real Sparx EA access, etc.) to unblock
10
- - **PARTIAL** — some paths landed, others deferred; see file for breakdown
11
-
12
- ## Index
13
-
14
- | # | Title | Status |
15
- |---|---|---|
16
- | 01 | [PackagedElement typed subclasses](01-packaged-element-typed-subclasses.md) | PARTIAL (Phase A done, Phase B deferred) |
17
- | 03 | [Real Sparx InstanceSpecification fixture](03-real-sparx-instancespec-fixture.md) | FUTURE |
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Shared attribute declarations for Profile-like classes.
4
- # Mixed into Profile via `include ProfileAttributes`.
5
- module Xmi
6
- module Uml
7
- module ProfileAttributes
8
- def self.included(klass)
9
- klass.class_eval do
10
- attribute :packaged_element, PackagedElement, collection: true
11
- attribute :package_import, PackageImport, collection: true
12
- attribute :id, ::Xmi::Type::XmiId
13
- attribute :name, :string
14
- attribute :ns_prefix, :string
15
- attribute :metamodel_reference, :string
16
- end
17
- end
18
- end
19
- end
20
- end