xmi 0.7.3 → 0.7.4
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/.github/workflows/rake.yml +3 -0
- data/CHANGELOG.md +21 -0
- data/CLAUDE.md +72 -24
- data/lib/xmi/namespace.rb +18 -0
- data/lib/xmi/parser_pipeline.rb +27 -4
- data/lib/xmi/parsing.rb +15 -26
- data/lib/xmi/root.rb +1 -12
- data/lib/xmi/sparx/mappings/base_mapping.rb +1 -12
- data/lib/xmi/sparx/root.rb +0 -16
- data/lib/xmi/uml/owned_attribute.rb +3 -16
- data/lib/xmi/uml/owned_end.rb +1 -14
- data/lib/xmi/uml/owned_parameter.rb +1 -12
- data/lib/xmi/uml/value_specs.rb +31 -0
- data/lib/xmi/uml.rb +1 -0
- data/lib/xmi/v20110701.rb +6 -18
- data/lib/xmi/v20131001.rb +8 -19
- data/lib/xmi/v20161101.rb +8 -18
- data/lib/xmi/version.rb +1 -1
- data/lib/xmi/versioned.rb +39 -9
- data/lib/xmi.rb +4 -4
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 588e344ea2df1c00d5050e7377bad54f7afca96e3925b327250cff8902a5027c
|
|
4
|
+
data.tar.gz: 56c69d3bc8056dffc1931af4c2d112db7b351e9fa39c4061b4073428be9b756a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 802a4c35900a1f3ed32a7d7ee0ad9b41a74686e0d1aedb5db318a1ffaa1bf9ca81f22d94d3672599bde39b56068ef4d5481242340552298bcd148eb479ee440d
|
|
7
|
+
data.tar.gz: '089817e9e7b880db5756a86023541012f5ef7a6e0b0f9161bc0a2e6a140bd915f69b9040d9175aadffd1ce3d0fee3fb2df2f2ed7d86a410d3cedfe64a114caeb'
|
data/.github/workflows/rake.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- All parse entry points (`Xmi.parse`, `Xmi.parse_with_version`,
|
|
13
|
+
`Xmi::Parsing.parse`, `Sparx::Root.parse_xml`) route through
|
|
14
|
+
`ParserPipeline`. Encoding repair no longer depends on which entry
|
|
15
|
+
point you pick — four of the five previously crashed on invalid
|
|
16
|
+
UTF-8. The dead `Sparx::Root.fix_encoding` duplicate is removed
|
|
17
|
+
- The Root-level namespace scope is declared once
|
|
18
|
+
(`Xmi::Namespace::SCOPE`) and shared by `Xmi::Root` and
|
|
19
|
+
`Mappings::BaseMapping`; the two verbatim copies could drift
|
|
20
|
+
silently
|
|
21
|
+
- The version modules (`V20110701`, `V20131001`, `V20161101`) declare
|
|
22
|
+
their table entry via `Versioned.define_version` instead of
|
|
23
|
+
repeating the register_id/namespace_classes/fallback_registers
|
|
24
|
+
boilerplate; each file now carries only its genuine delta
|
|
25
|
+
- `OwnedAttribute`, `OwnedEnd`, and `OwnedParameter` inherit their
|
|
26
|
+
shared value-specification surface (uml_type + upper/lower/default
|
|
27
|
+
values + the four element mappings) from the new
|
|
28
|
+
`Xmi::Uml::ValueSpecs` base; serialized element order is pinned to
|
|
29
|
+
EA parity (type, lowerValue, upperValue)
|
|
30
|
+
|
|
10
31
|
### Fixed
|
|
11
32
|
|
|
12
33
|
- Gemspec: restore the optimistic `~> 0.8.17` constraint on
|
data/CLAUDE.md
CHANGED
|
@@ -26,8 +26,22 @@ bundle exec rake
|
|
|
26
26
|
|
|
27
27
|
# Interactive console for experimentation
|
|
28
28
|
bin/console
|
|
29
|
+
|
|
30
|
+
# Benchmarks (dev tooling under Xmi::Performance)
|
|
31
|
+
bundle exec rake performance:quick # fast, less accurate
|
|
32
|
+
bundle exec rake performance:json # JSON output
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### RuboCop toolchain note
|
|
36
|
+
|
|
37
|
+
`Gemfile.lock` is **gitignored** — each machine resolves its own versions, and CI installs lock-free (typically a newer RuboCop than a stale local lock resolves). If local rubocop disagrees with CI:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
bundle update rubocop rubocop-ast rubocop-performance rubocop-rspec rubocop-rake
|
|
29
41
|
```
|
|
30
42
|
|
|
43
|
+
Use the `rubocop:disable-next Cop` directive form (not `disable-next-line`) — it is the form current RuboCop accepts and requires for single-statement disables.
|
|
44
|
+
|
|
31
45
|
## Architecture Overview
|
|
32
46
|
|
|
33
47
|
This gem converts XMI (XML Metadata Interchange) files into Ruby objects, specifically designed for Enterprise Architect generated XMI files.
|
|
@@ -37,18 +51,29 @@ This gem converts XMI (XML Metadata Interchange) files into Ruby objects, specif
|
|
|
37
51
|
- **lutaml-model**: All serializable models inherit from `Lutaml::Model::Serializable`
|
|
38
52
|
- **nokogiri**: XML parsing backend
|
|
39
53
|
|
|
40
|
-
### Main Entry Point
|
|
54
|
+
### Main Entry Point / Parse Pipeline
|
|
55
|
+
|
|
56
|
+
Every public parse door routes through one module, `Xmi::ParserPipeline`
|
|
57
|
+
(`lib/xmi/parser_pipeline.rb`):
|
|
41
58
|
|
|
42
|
-
`Xmi
|
|
59
|
+
- `Xmi.parse(xml)` — auto version detection
|
|
60
|
+
- `Xmi.parse_with_version(xml, version)`
|
|
61
|
+
- `Xmi::Parsing.parse(xml, options)` — IO coercion, `:version`/`:register`/`:model_class` options
|
|
62
|
+
- `Xmi::Sparx::Root.parse_xml(xml)` — also builds `Sparx::Index`
|
|
43
63
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
64
|
+
Pipeline steps: `FixEncoding` (repairs invalid UTF-8) →
|
|
65
|
+
`RenameEaXmlnsAttribute` (see the EA xmlns quirk below) →
|
|
66
|
+
`InitVersioning` → `ParseXml` (detects the version register, or uses
|
|
67
|
+
`ctx[:register]` when a door resolved one) → `BuildIndex` (Root
|
|
68
|
+
hierarchy only — custom `:model_class` models are skipped). Encoding
|
|
69
|
+
repair runs no matter which door a consumer picks;
|
|
70
|
+
`parser_pipeline_spec.rb` pins this for all doors.
|
|
48
71
|
|
|
49
|
-
|
|
72
|
+
Adding a parse concern = adding a pipeline step, not editing doors.
|
|
50
73
|
|
|
51
|
-
OMG
|
|
74
|
+
### OMG Namespace Version Handling
|
|
75
|
+
|
|
76
|
+
OMG publishes XMI and UML specifications with dated namespace URIs (e.g., `http://www.omg.org/spec/XMI/20110701`, `20131001`, `20161101`). Documents of any version parse via per-version registers: `NamespaceDetector` scans the namespaces, `VersionRegistry.detect_register` picks the register (`V20110701` / `V20131001` / `V20161101`), and mixed-version documents extend the primary register's fallback chain. Model classes stay version-agnostic by using alias namespace classes that inherit from the 20131001 canonical versions.
|
|
52
77
|
|
|
53
78
|
### Enterprise Architect's Misuse of the `xmlns` Attribute
|
|
54
79
|
|
|
@@ -56,17 +81,7 @@ OMG publishes XMI and UML specifications with dated namespace URIs (e.g., `http:
|
|
|
56
81
|
|
|
57
82
|
In standard XML, `xmlns` is a reserved attribute for namespace declarations. However, Enterprise Architect incorrectly uses `xmlns` as a **regular data attribute** on certain stereotype elements (e.g., `GML:ApplicationSchema`, `CityGML:ApplicationSchema`), storing arbitrary URI values unrelated to namespace declarations.
|
|
58
83
|
|
|
59
|
-
This violates XML conventions and creates parsing conflicts—XML libraries treat `xmlns` as reserved. The
|
|
60
|
-
|
|
61
|
-
```xml
|
|
62
|
-
<!-- EA-generated -->
|
|
63
|
-
<GML:ApplicationSchema xmlns="http://some-value" ...>
|
|
64
|
-
|
|
65
|
-
<!-- After preprocessing -->
|
|
66
|
-
<GML:ApplicationSchema altered_xmlns="http://some-value" ...>
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Model classes define `altered_xmlns` attributes to receive these values:
|
|
84
|
+
This violates XML conventions and creates parsing conflicts—XML libraries treat `xmlns` as reserved. The workaround runs in the parse pipeline (`ParserPipeline::Steps::RenameEaXmlnsAttribute`): before parsing, `xmlns` is renamed to `altered_xmlns` on `GML:ApplicationSchema` and `CityGML:ApplicationSchema` tags only — legitimate namespace declarations are untouched. `Xmi::EaRoot` extension code generation applies the same rename when building classes from MDG XML that defines an attribute literally named `xmlns`. Pinned by `parser_pipeline_spec.rb` against the real `xmi-v2-4-2-default-with-gml.xmi` fixture.
|
|
70
85
|
|
|
71
86
|
```ruby
|
|
72
87
|
class ApplicationSchema < Lutaml::Model::Serializable
|
|
@@ -74,13 +89,20 @@ class ApplicationSchema < Lutaml::Model::Serializable
|
|
|
74
89
|
end
|
|
75
90
|
```
|
|
76
91
|
|
|
77
|
-
###
|
|
92
|
+
### EA Writes Attribute Names Verbatim
|
|
93
|
+
|
|
94
|
+
Some EA attributes are written in non-camelCase spellings that must be
|
|
95
|
+
mapped literally — "correcting" them breaks parsing. Examples:
|
|
96
|
+
`package_name` and `associationclass` on `<extendedProperties>` (all
|
|
97
|
+
lowercase, no case conversion), pinned by
|
|
98
|
+
`spec/xmi/sparx/element/extended_properties_spec.rb`.
|
|
78
99
|
|
|
79
|
-
|
|
100
|
+
### Namespace Architecture
|
|
80
101
|
|
|
81
102
|
Namespace classes are defined in:
|
|
82
103
|
- `lib/xmi/namespace/omg.rb` - OMG namespaces (XMI, UML, UmlDi, UmlDc)
|
|
83
104
|
- `lib/xmi/namespace/sparx.rb` - Sparx-specific profiles (SysPhS, GML, EaUml, CustomProfile, CityGML)
|
|
105
|
+
- `lib/xmi/namespace.rb` - `Xmi::Namespace::SCOPE`: the canonical 10-namespace scope shared by `Xmi::Root`'s xml block and `Sparx::Mappings::BaseMapping` (pinned by `spec/xmi/namespace_scope_spec.rb`)
|
|
84
106
|
|
|
85
107
|
Use version-agnostic alias classes that inherit from 20131001 versions:
|
|
86
108
|
```ruby
|
|
@@ -88,6 +110,18 @@ Use version-agnostic alias classes that inherit from 20131001 versions:
|
|
|
88
110
|
::Xmi::Namespace::Omg::Uml # => inherits from Uml20131001
|
|
89
111
|
```
|
|
90
112
|
|
|
113
|
+
### Version Registers
|
|
114
|
+
|
|
115
|
+
`V20110701` / `V20131001` / `V20161101` are table entries: each calls
|
|
116
|
+
`Versioned.define_version(register_id:, namespaces:, fallbacks:)` and
|
|
117
|
+
keeps only its real delta (version-specific `Documentation`/`Extension`
|
|
118
|
+
classes plus a `register_models` table). Adding an XMI version = a new
|
|
119
|
+
table entry, not a new boilerplate file. `Versioned` (`lib/xmi/versioned.rb`)
|
|
120
|
+
creates the `Lutaml::Model::Register`, binds namespaces, and runs
|
|
121
|
+
registration; `VersionRegistry` (`lib/xmi/version_registry.rb`) maps
|
|
122
|
+
version strings → registers and extends fallback chains for
|
|
123
|
+
mixed-namespace documents.
|
|
124
|
+
|
|
91
125
|
### Custom Types with XML Namespace
|
|
92
126
|
|
|
93
127
|
Custom types in `lib/xmi/type.rb` declare their XML namespace using the `xml do ... end` block:
|
|
@@ -113,6 +147,14 @@ UML Diagram Interchange elements (Bounds, Waypoint, Diagram,
|
|
|
113
147
|
OwnedElement) inherit from `Xmi::UmlDi::Base` instead — same
|
|
114
148
|
pattern, different namespace.
|
|
115
149
|
|
|
150
|
+
`OwnedAttribute`, `OwnedEnd`, and `OwnedParameter` inherit from
|
|
151
|
+
`Xmi::Uml::ValueSpecs`, which owns their shared value-specification
|
|
152
|
+
surface: `uml_type` (`<type>` element) plus `upper_value` /
|
|
153
|
+
`lower_value` / `default_value` with their polymorphic mappings.
|
|
154
|
+
Inherited element mappings serialize before subclass mappings, so the
|
|
155
|
+
EA-parity order (type, lowerValue, upperValue) comes from the base —
|
|
156
|
+
subclasses declare only attributes.
|
|
157
|
+
|
|
116
158
|
```ruby
|
|
117
159
|
# lib/xmi/uml/my_element.rb
|
|
118
160
|
module Xmi
|
|
@@ -150,13 +192,14 @@ Two attributes use lutaml-model's polymorphic dispatch on `xmi:type`:
|
|
|
150
192
|
- `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
193
|
- `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
194
|
|
|
153
|
-
**Fallback contract:** unknown or missing `xmi:type` resolves to the abstract base (`PackagedElement` / `ValueSpecification`) via the class_map's Hash default value — no crash. Locked in by `spec/xmi/uml/polymorphic_map_contract_spec.rb` and `spec/xmi/uml/polymorphic_robustness_spec.rb`. Two paths land at the base: a missing discriminator short-circuits upstream (the declared attribute type is used); an unknown discriminator hits the Hash default. Residual upstream gap — modelling `xmi:type` and unprefixed `type` as separate slots on one element — is tracked in lutaml-model#
|
|
195
|
+
**Fallback contract:** unknown or missing `xmi:type` resolves to the abstract base (`PackagedElement` / `ValueSpecification`) via the class_map's Hash default value — no crash. Locked in by `spec/xmi/uml/polymorphic_map_contract_spec.rb` and `spec/xmi/uml/polymorphic_robustness_spec.rb`. Two paths land at the base: a missing discriminator short-circuits upstream (the declared attribute type is used); an unknown discriminator hits the Hash default. Residual upstream gap — modelling `xmi:type` and unprefixed `type` as separate slots on one element — is tracked in lutaml-model#758.
|
|
154
196
|
|
|
155
197
|
### Key Files
|
|
156
198
|
|
|
157
199
|
| File | Purpose |
|
|
158
200
|
|------|---------|
|
|
159
201
|
| `lib/xmi.rb` | Main entry point, loads dependencies and configures XML adapter |
|
|
202
|
+
| `lib/xmi/parser_pipeline.rb` | The parse pipeline — the one module behind every public parse door |
|
|
160
203
|
| `lib/xmi/sparx.rb` | Module with autoload declarations for Sparx components |
|
|
161
204
|
| `lib/xmi/sparx/root.rb` | Main `Root` class with parsing and namespace normalization |
|
|
162
205
|
| `lib/xmi/root.rb` | Base `Root` class with common XMI attributes |
|
|
@@ -166,11 +209,14 @@ Two attributes use lutaml-model's polymorphic dispatch on `xmi:type`:
|
|
|
166
209
|
| `lib/xmi/uml_di/base.rb` | `Xmi::UmlDi::Base` — common boilerplate for UMLDI classes |
|
|
167
210
|
| `lib/xmi/uml/packaged_element.rb` | `PackagedElement` + `PACKAGED_ELEMENT_POLYMORPHIC_MAP` |
|
|
168
211
|
| `lib/xmi/uml/value_specification.rb` | `ValueSpecification` abstract base + `VALUE_SPECIFICATION_POLYMORPHIC_MAP` |
|
|
212
|
+
| `lib/xmi/uml/value_specs.rb` | `Xmi::Uml::ValueSpecs` — shared value surface for OwnedAttribute/OwnedEnd/OwnedParameter |
|
|
169
213
|
| `lib/xmi/ea_root.rb` | Dynamic extension loading from MDG XML |
|
|
170
214
|
| `lib/xmi/type.rb` | Custom types with namespace declarations (XmiId, XmiType, etc.) |
|
|
171
215
|
| `lib/xmi/namespace/omg.rb` | OMG namespace classes (XMI, UML, UmlDi, UmlDc) |
|
|
172
216
|
| `lib/xmi/namespace/sparx.rb` | Sparx-specific profile namespaces |
|
|
173
217
|
| `lib/xmi/namespace_registry.rb` | URI-to-class mapping for namespace lookup |
|
|
218
|
+
| `lib/xmi/versioned.rb` | Version-register DSL: `define_version` table entries + `register_models` helper |
|
|
219
|
+
| `lib/xmi/version_registry.rb` | Version string → register mapping, mixed-namespace fallback chains |
|
|
174
220
|
|
|
175
221
|
### Collection Value Maps
|
|
176
222
|
|
|
@@ -188,8 +234,10 @@ A shared constant is available at `Xmi::Sparx::VALUE_MAP`.
|
|
|
188
234
|
|
|
189
235
|
## Known Issues
|
|
190
236
|
|
|
191
|
-
Attribute deserialization in lutaml-model is not namespace-disjoint: same-local-name attributes in different namespaces collapse into one model slot, document-order dependent. This affects modelling `xmi:type` (the XMI discriminator) and unprefixed `type` (Sparx's classifier reference) as separate attributes on one element
|
|
237
|
+
Attribute deserialization in lutaml-model is not namespace-disjoint under element-level namespaces: same-local-name attributes in different namespaces collapse into one model slot, document-order dependent (last spelling wins). This affects modelling `xmi:type` (the XMI discriminator) and unprefixed `type` (Sparx's classifier reference) as separate attributes on one element — see the class docstring on `OwnedParameter`. Tracked in lutaml-model#758 with a repro; `spec/xmi/uml/owned_parameter_spec.rb` pins the current behavior in both input orders.
|
|
238
|
+
|
|
239
|
+
The `lutaml-model` gemspec constraint is itself pinned by `spec/xmi_gemspec_spec.rb` — changing the dependency range is a deliberate act that updates that spec.
|
|
192
240
|
|
|
193
241
|
## Limitations
|
|
194
242
|
|
|
195
|
-
This gem is designed for Enterprise Architect generated XMI files and may not work with XMI from other tools.
|
|
243
|
+
This gem is designed for Enterprise Architect generated XMI files and may not work with XMI from other tools.
|
data/lib/xmi/namespace.rb
CHANGED
|
@@ -5,5 +5,23 @@ module Xmi
|
|
|
5
5
|
autoload :Omg, "xmi/namespace/omg"
|
|
6
6
|
autoload :Sparx, "xmi/namespace/sparx"
|
|
7
7
|
autoload :Dynamic, "xmi/namespace/dynamic"
|
|
8
|
+
|
|
9
|
+
# Canonical namespace scope for XMI document parsing — every
|
|
10
|
+
# namespace a Root-level mapping may resolve against, in
|
|
11
|
+
# resolution order (OMG core first, then Sparx profiles).
|
|
12
|
+
# Declared once; consumed by both Xmi::Root's xml block and
|
|
13
|
+
# Sparx::Mappings::BaseMapping.
|
|
14
|
+
SCOPE = [
|
|
15
|
+
Omg::Xmi,
|
|
16
|
+
Omg::Uml,
|
|
17
|
+
Omg::UmlDi,
|
|
18
|
+
Omg::UmlDc,
|
|
19
|
+
Sparx::Extension,
|
|
20
|
+
Sparx::Gml,
|
|
21
|
+
Sparx::CustomProfile,
|
|
22
|
+
Sparx::SysPhS,
|
|
23
|
+
Sparx::EaUml,
|
|
24
|
+
Sparx::CityGml,
|
|
25
|
+
].freeze
|
|
8
26
|
end
|
|
9
27
|
end
|
data/lib/xmi/parser_pipeline.rb
CHANGED
|
@@ -26,6 +26,22 @@ module Xmi
|
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
# EA misuses the reserved xmlns attribute as a DATA attribute on
|
|
30
|
+
# GML:/CityGML:ApplicationSchema stereotype elements (values
|
|
31
|
+
# unrelated to real namespace declarations). XML parsers treat
|
|
32
|
+
# xmlns as a namespace declaration, so without renaming, the
|
|
33
|
+
# value is silently dropped. Restored from the original
|
|
34
|
+
# replace_ea_xmlns preprocessing (commit 8da3bfb), which was
|
|
35
|
+
# lost in the lutaml-model 0.8 upgrade.
|
|
36
|
+
module RenameEaXmlnsAttribute
|
|
37
|
+
EA_XMLNS_TAG = %r{(<(?:GML|CityGML):ApplicationSchema[^>]*?)xmlns="([^"]*)"}
|
|
38
|
+
|
|
39
|
+
def self.call(ctx)
|
|
40
|
+
ctx[:xml] = ctx[:xml].gsub(EA_XMLNS_TAG, '\1altered_xmlns="\2"')
|
|
41
|
+
ctx
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
29
45
|
module InitVersioning
|
|
30
46
|
def self.call(ctx)
|
|
31
47
|
Xmi.init_versioning!
|
|
@@ -36,16 +52,22 @@ module Xmi
|
|
|
36
52
|
module ParseXml
|
|
37
53
|
def self.call(ctx)
|
|
38
54
|
root_class = ctx[:root_class]
|
|
39
|
-
ctx[:root] =
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
ctx[:root] = if ctx[:register]
|
|
56
|
+
root_class.from_xml(ctx[:xml], register: ctx[:register])
|
|
57
|
+
else
|
|
58
|
+
VersionRegistry.parse_with_detected_version(
|
|
59
|
+
ctx[:xml], root_class
|
|
60
|
+
)
|
|
61
|
+
end
|
|
42
62
|
ctx
|
|
43
63
|
end
|
|
44
64
|
end
|
|
45
65
|
|
|
46
66
|
module BuildIndex
|
|
47
67
|
def self.call(ctx)
|
|
48
|
-
|
|
68
|
+
# Only the Root hierarchy carries an index; custom model
|
|
69
|
+
# classes parsed through the pipeline are left alone.
|
|
70
|
+
ctx[:root].build_index if ctx[:root].is_a?(::Xmi::Root)
|
|
49
71
|
ctx
|
|
50
72
|
end
|
|
51
73
|
end
|
|
@@ -53,6 +75,7 @@ module Xmi
|
|
|
53
75
|
|
|
54
76
|
DEFAULT_STEPS = [
|
|
55
77
|
Steps::FixEncoding,
|
|
78
|
+
Steps::RenameEaXmlnsAttribute,
|
|
56
79
|
Steps::InitVersioning,
|
|
57
80
|
Steps::ParseXml,
|
|
58
81
|
Steps::BuildIndex,
|
data/lib/xmi/parsing.rb
CHANGED
|
@@ -29,17 +29,14 @@ module Xmi
|
|
|
29
29
|
def parse(xml, options = {})
|
|
30
30
|
xml_content = xml.is_a?(String) ? xml : xml.read
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
ctx = {
|
|
33
|
+
xml: xml_content,
|
|
34
|
+
root_class: options[:model_class] || Root,
|
|
35
|
+
}
|
|
36
|
+
register = explicit_register(options)
|
|
37
|
+
ctx[:register] = register if register
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
model_class.from_xml(xml_content, register: register)
|
|
39
|
-
else
|
|
40
|
-
# Fallback to default parsing (existing behavior)
|
|
41
|
-
model_class.from_xml(xml_content)
|
|
42
|
-
end
|
|
39
|
+
ParserPipeline.run(ctx)[:root]
|
|
43
40
|
end
|
|
44
41
|
|
|
45
42
|
# @api public
|
|
@@ -88,28 +85,20 @@ module Xmi
|
|
|
88
85
|
|
|
89
86
|
private
|
|
90
87
|
|
|
91
|
-
#
|
|
88
|
+
# Resolve an explicitly requested register from options
|
|
89
|
+
#
|
|
90
|
+
# Returns nil when neither :register nor :version is given, leaving
|
|
91
|
+
# version detection to the pipeline.
|
|
92
92
|
#
|
|
93
|
-
# @param xml_content [String] XML content
|
|
94
93
|
# @param options [Hash] Options hash
|
|
95
94
|
# @return [Lutaml::Model::Register, nil]
|
|
96
|
-
def
|
|
97
|
-
# Explicit register takes precedence
|
|
95
|
+
def explicit_register(options)
|
|
98
96
|
return options[:register] if options[:register]
|
|
99
97
|
|
|
100
|
-
|
|
101
|
-
if options[:version]
|
|
102
|
-
reg = VersionRegistry.register_for_version(options[:version])
|
|
103
|
-
unless reg
|
|
104
|
-
raise ArgumentError,
|
|
105
|
-
"Unknown version: #{options[:version]}"
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
return reg
|
|
109
|
-
end
|
|
98
|
+
return unless options[:version]
|
|
110
99
|
|
|
111
|
-
|
|
112
|
-
|
|
100
|
+
VersionRegistry.register_for_version(options[:version]) ||
|
|
101
|
+
raise(ArgumentError, "Unknown version: #{options[:version]}")
|
|
113
102
|
end
|
|
114
103
|
end
|
|
115
104
|
end
|
data/lib/xmi/root.rb
CHANGED
|
@@ -29,18 +29,7 @@ module Xmi
|
|
|
29
29
|
xml do
|
|
30
30
|
root "XMI"
|
|
31
31
|
namespace ::Xmi::Namespace::Omg::Xmi
|
|
32
|
-
namespace_scope
|
|
33
|
-
::Xmi::Namespace::Omg::Xmi,
|
|
34
|
-
::Xmi::Namespace::Omg::Uml,
|
|
35
|
-
::Xmi::Namespace::Omg::UmlDi,
|
|
36
|
-
::Xmi::Namespace::Omg::UmlDc,
|
|
37
|
-
::Xmi::Namespace::Sparx::Extension,
|
|
38
|
-
::Xmi::Namespace::Sparx::Gml,
|
|
39
|
-
::Xmi::Namespace::Sparx::CustomProfile,
|
|
40
|
-
::Xmi::Namespace::Sparx::SysPhS,
|
|
41
|
-
::Xmi::Namespace::Sparx::EaUml,
|
|
42
|
-
::Xmi::Namespace::Sparx::CityGml,
|
|
43
|
-
]
|
|
32
|
+
namespace_scope ::Xmi::Namespace::SCOPE
|
|
44
33
|
|
|
45
34
|
XmiIdentity.apply_xml_mappings(self)
|
|
46
35
|
|
|
@@ -17,18 +17,7 @@ module Xmi
|
|
|
17
17
|
# Set the default namespace for element name resolution
|
|
18
18
|
namespace ::Xmi::Namespace::Omg::Xmi
|
|
19
19
|
|
|
20
|
-
namespace_scope
|
|
21
|
-
::Xmi::Namespace::Omg::Xmi,
|
|
22
|
-
::Xmi::Namespace::Omg::Uml,
|
|
23
|
-
::Xmi::Namespace::Omg::UmlDi,
|
|
24
|
-
::Xmi::Namespace::Omg::UmlDc,
|
|
25
|
-
::Xmi::Namespace::Sparx::Extension,
|
|
26
|
-
::Xmi::Namespace::Sparx::SysPhS,
|
|
27
|
-
::Xmi::Namespace::Sparx::Gml,
|
|
28
|
-
::Xmi::Namespace::Sparx::EaUml,
|
|
29
|
-
::Xmi::Namespace::Sparx::CustomProfile,
|
|
30
|
-
::Xmi::Namespace::Sparx::CityGml,
|
|
31
|
-
]
|
|
20
|
+
namespace_scope ::Xmi::Namespace::SCOPE
|
|
32
21
|
|
|
33
22
|
VM = ::Xmi::VALUE_MAP
|
|
34
23
|
|
data/lib/xmi/sparx/root.rb
CHANGED
|
@@ -37,22 +37,6 @@ module Xmi
|
|
|
37
37
|
)
|
|
38
38
|
ctx[:root]
|
|
39
39
|
end
|
|
40
|
-
|
|
41
|
-
# Fix invalid UTF-8 encoding in the XML content.
|
|
42
|
-
#
|
|
43
|
-
# Some EA-generated XMI files contain invalid UTF-8 byte sequences
|
|
44
|
-
# that would cause parsing failures. This method replaces invalid
|
|
45
|
-
# bytes with placeholder characters.
|
|
46
|
-
#
|
|
47
|
-
# @param xml_content [String] The raw XML content
|
|
48
|
-
# @return [String] The XML content with valid UTF-8 encoding
|
|
49
|
-
def fix_encoding(xml_content)
|
|
50
|
-
return xml_content if xml_content.valid_encoding?
|
|
51
|
-
|
|
52
|
-
xml_content
|
|
53
|
-
.encode("UTF-16be", invalid: :replace, replace: "?")
|
|
54
|
-
.encode("UTF-8")
|
|
55
|
-
end
|
|
56
40
|
end
|
|
57
41
|
|
|
58
42
|
# Use the reusable BaseMapping class instead of eval hack
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Xmi
|
|
4
4
|
module Uml
|
|
5
|
-
class OwnedAttribute <
|
|
5
|
+
class OwnedAttribute < ValueSpecs
|
|
6
6
|
attribute :association, :string
|
|
7
7
|
attribute :name, :string
|
|
8
8
|
attribute :visibility, :string
|
|
@@ -12,14 +12,10 @@ module Xmi
|
|
|
12
12
|
attribute :is_unique, :boolean
|
|
13
13
|
attribute :is_read_only, :boolean
|
|
14
14
|
# `default` is the XMI attribute form (string shortcut);
|
|
15
|
-
# `default_value`
|
|
16
|
-
# (ValueSpecification). UML 2.5 Property carries both shapes.
|
|
15
|
+
# `default_value` (from ValueSpecs) is the child <defaultValue>
|
|
16
|
+
# element (ValueSpecification). UML 2.5 Property carries both shapes.
|
|
17
17
|
attribute :default, :string
|
|
18
18
|
attribute :aggregation, :string
|
|
19
|
-
attribute :uml_type, Uml::Type
|
|
20
|
-
attribute :upper_value, ValueSpecification, polymorphic: true
|
|
21
|
-
attribute :lower_value, ValueSpecification, polymorphic: true
|
|
22
|
-
attribute :default_value, ValueSpecification, polymorphic: true
|
|
23
19
|
|
|
24
20
|
xml do
|
|
25
21
|
root "ownedAttribute"
|
|
@@ -33,15 +29,6 @@ module Xmi
|
|
|
33
29
|
map_attribute "isReadOnly", to: :is_read_only
|
|
34
30
|
map_attribute "default", to: :default
|
|
35
31
|
map_attribute "aggregation", to: :aggregation
|
|
36
|
-
|
|
37
|
-
map_element "type", to: :uml_type
|
|
38
|
-
# Sparx EA emits lowerValue before upperValue.
|
|
39
|
-
map_element "lowerValue", to: :lower_value,
|
|
40
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
41
|
-
map_element "upperValue", to: :upper_value,
|
|
42
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
43
|
-
map_element "defaultValue", to: :default_value,
|
|
44
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
45
32
|
end
|
|
46
33
|
end
|
|
47
34
|
end
|
data/lib/xmi/uml/owned_end.rb
CHANGED
|
@@ -2,16 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
module Xmi
|
|
4
4
|
module Uml
|
|
5
|
-
class OwnedEnd <
|
|
5
|
+
class OwnedEnd < ValueSpecs
|
|
6
6
|
attribute :association, :string
|
|
7
7
|
attribute :name, :string
|
|
8
8
|
attribute :visibility, :string
|
|
9
9
|
attribute :aggregation, :string
|
|
10
|
-
attribute :uml_type, Uml::Type
|
|
11
10
|
attribute :member_end, :string
|
|
12
|
-
attribute :upper_value, ValueSpecification, polymorphic: true
|
|
13
|
-
attribute :lower_value, ValueSpecification, polymorphic: true
|
|
14
|
-
attribute :default_value, ValueSpecification, polymorphic: true
|
|
15
11
|
attribute :is_composite, :boolean
|
|
16
12
|
|
|
17
13
|
xml do
|
|
@@ -22,15 +18,6 @@ module Xmi
|
|
|
22
18
|
map_attribute "aggregation", to: :aggregation
|
|
23
19
|
map_attribute "memberEnd", to: :member_end
|
|
24
20
|
map_attribute "isComposite", to: :is_composite
|
|
25
|
-
|
|
26
|
-
map_element "type", to: :uml_type
|
|
27
|
-
# Sparx EA emits lowerValue before upperValue.
|
|
28
|
-
map_element "lowerValue", to: :lower_value,
|
|
29
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
30
|
-
map_element "upperValue", to: :upper_value,
|
|
31
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
32
|
-
map_element "defaultValue", to: :default_value,
|
|
33
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
34
21
|
end
|
|
35
22
|
end
|
|
36
23
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Xmi
|
|
4
4
|
module Uml
|
|
5
|
-
class OwnedParameter <
|
|
5
|
+
class OwnedParameter < ValueSpecs
|
|
6
6
|
attribute :name, :string
|
|
7
7
|
# These are two DIFFERENT attributes that collide here:
|
|
8
8
|
# xmi:type="uml:Parameter" — the XMI metaclass discriminator
|
|
@@ -27,9 +27,6 @@ module Xmi
|
|
|
27
27
|
attribute :is_ordered, :boolean
|
|
28
28
|
attribute :is_unique, :boolean
|
|
29
29
|
attribute :effect, :string
|
|
30
|
-
attribute :upper_value, ValueSpecification, polymorphic: true
|
|
31
|
-
attribute :lower_value, ValueSpecification, polymorphic: true
|
|
32
|
-
attribute :default_value, ValueSpecification, polymorphic: true
|
|
33
30
|
|
|
34
31
|
xml do
|
|
35
32
|
root "ownedParameter"
|
|
@@ -40,14 +37,6 @@ module Xmi
|
|
|
40
37
|
map_attribute "isOrdered", to: :is_ordered
|
|
41
38
|
map_attribute "isUnique", to: :is_unique
|
|
42
39
|
map_attribute "effect", to: :effect
|
|
43
|
-
|
|
44
|
-
# Sparx EA emits lowerValue before upperValue.
|
|
45
|
-
map_element "lowerValue", to: :lower_value,
|
|
46
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
47
|
-
map_element "upperValue", to: :upper_value,
|
|
48
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
49
|
-
map_element "defaultValue", to: :default_value,
|
|
50
|
-
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
51
40
|
end
|
|
52
41
|
end
|
|
53
42
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Xmi
|
|
4
|
+
module Uml
|
|
5
|
+
# Shared value-specification surface for typed structural features:
|
|
6
|
+
# the classifier reference (<type> element) plus the multiplicity
|
|
7
|
+
# bounds and default value (<lowerValue>/<upperValue>/<defaultValue>).
|
|
8
|
+
#
|
|
9
|
+
# Element order matches Sparx EA output: type first, then values,
|
|
10
|
+
# lowerValue before upperValue. Inherited element mappings
|
|
11
|
+
# serialize before subclass mappings, so subclasses (OwnedAttribute,
|
|
12
|
+
# OwnedEnd, OwnedParameter) declare only attributes and keep this
|
|
13
|
+
# output order.
|
|
14
|
+
class ValueSpecs < Base
|
|
15
|
+
attribute :uml_type, Uml::Type
|
|
16
|
+
attribute :upper_value, ValueSpecification, polymorphic: true
|
|
17
|
+
attribute :lower_value, ValueSpecification, polymorphic: true
|
|
18
|
+
attribute :default_value, ValueSpecification, polymorphic: true
|
|
19
|
+
|
|
20
|
+
xml do
|
|
21
|
+
map_element "type", to: :uml_type
|
|
22
|
+
map_element "lowerValue", to: :lower_value,
|
|
23
|
+
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
24
|
+
map_element "upperValue", to: :upper_value,
|
|
25
|
+
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
26
|
+
map_element "defaultValue", to: :default_value,
|
|
27
|
+
polymorphic: VALUE_SPECIFICATION_POLYMORPHIC_MAP
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/xmi/uml.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Xmi
|
|
|
10
10
|
autoload :UpperValue, "xmi/uml/upper_value"
|
|
11
11
|
autoload :LowerValue, "xmi/uml/lower_value"
|
|
12
12
|
autoload :ValueSpecification, "xmi/uml/value_specification"
|
|
13
|
+
autoload :ValueSpecs, "xmi/uml/value_specs"
|
|
13
14
|
autoload :LiteralString, "xmi/uml/literal_string"
|
|
14
15
|
autoload :LiteralInteger, "xmi/uml/literal_integer"
|
|
15
16
|
autoload :LiteralBoolean, "xmi/uml/literal_boolean"
|
data/lib/xmi/v20110701.rb
CHANGED
|
@@ -8,29 +8,17 @@ module Xmi
|
|
|
8
8
|
module V20110701
|
|
9
9
|
extend Versioned
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
:
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Namespace classes this version binds to
|
|
17
|
-
def self.namespace_classes
|
|
18
|
-
[
|
|
11
|
+
define_version(
|
|
12
|
+
register_id: :xmi_20110701,
|
|
13
|
+
namespaces: [
|
|
19
14
|
Xmi::Namespace::Omg::Xmi20110701,
|
|
20
15
|
Xmi::Namespace::Omg::Uml20110701,
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Fallback chain: common → default
|
|
25
|
-
def self.fallback_registers
|
|
26
|
-
%i[xmi_common default]
|
|
27
|
-
end
|
|
16
|
+
],
|
|
17
|
+
)
|
|
28
18
|
|
|
29
19
|
# Register all models for this version
|
|
30
20
|
def self.register_models!
|
|
31
|
-
|
|
32
|
-
register.register_model(Extension, id: :extension)
|
|
33
|
-
register.register_model(Documentation, id: :documentation)
|
|
21
|
+
register_models extension: Extension, documentation: Documentation
|
|
34
22
|
end
|
|
35
23
|
|
|
36
24
|
# XMI 2.1 Extension element
|
data/lib/xmi/v20131001.rb
CHANGED
|
@@ -8,33 +8,22 @@ module Xmi
|
|
|
8
8
|
module V20131001
|
|
9
9
|
extend Versioned
|
|
10
10
|
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
:xmi_20131001
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# Namespace classes this version binds to
|
|
17
|
-
def self.namespace_classes
|
|
18
|
-
[
|
|
11
|
+
# V20110701 in the chain: V20131001 reuses its Extension (same structure)
|
|
12
|
+
define_version(
|
|
13
|
+
register_id: :xmi_20131001,
|
|
14
|
+
namespaces: [
|
|
19
15
|
Xmi::Namespace::Omg::Xmi20131001,
|
|
20
16
|
Xmi::Namespace::Omg::Uml20131001,
|
|
21
17
|
Xmi::Namespace::Omg::UmlDi20131001,
|
|
22
18
|
Xmi::Namespace::Omg::UmlDc20131001,
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# Fallback chain: V20110701 → common → default
|
|
27
|
-
# This allows V20131001 to use V20110701's Extension (same structure)
|
|
28
|
-
def self.fallback_registers
|
|
29
|
-
%i[xmi_20110701 xmi_common default]
|
|
30
|
-
end
|
|
19
|
+
],
|
|
20
|
+
fallbacks: %i[xmi_20110701 xmi_common default],
|
|
21
|
+
)
|
|
31
22
|
|
|
32
23
|
# Register all models for this version
|
|
33
24
|
def self.register_models!
|
|
34
25
|
# Extension is same as V20110701 - will be found via fallback
|
|
35
|
-
|
|
36
|
-
# Documentation is different - register our version
|
|
37
|
-
register.register_model(Documentation, id: :documentation)
|
|
26
|
+
register_models documentation: Documentation
|
|
38
27
|
end
|
|
39
28
|
|
|
40
29
|
# XMI 2.5.1 Documentation element
|
data/lib/xmi/v20161101.rb
CHANGED
|
@@ -8,32 +8,22 @@ module Xmi
|
|
|
8
8
|
module V20161101
|
|
9
9
|
extend Versioned
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
:
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Namespace classes this version binds to
|
|
17
|
-
def self.namespace_classes
|
|
18
|
-
[
|
|
11
|
+
define_version(
|
|
12
|
+
register_id: :xmi_20161101,
|
|
13
|
+
namespaces: [
|
|
19
14
|
Xmi::Namespace::Omg::Xmi20161101,
|
|
20
15
|
Xmi::Namespace::Omg::Uml20161101,
|
|
21
16
|
Xmi::Namespace::Omg::UmlDi20161101,
|
|
22
17
|
Xmi::Namespace::Omg::UmlDc20161101,
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# Fallback chain: V20131001 → V20110701 → common → default
|
|
27
|
-
def self.fallback_registers
|
|
28
|
-
%i[xmi_20131001 xmi_20110701 xmi_common default]
|
|
29
|
-
end
|
|
18
|
+
],
|
|
19
|
+
fallbacks: %i[xmi_20131001 xmi_20110701 xmi_common default],
|
|
20
|
+
)
|
|
30
21
|
|
|
31
22
|
# Register all models for this version
|
|
32
23
|
def self.register_models!
|
|
33
|
-
# Extension is different in 2.5.2 - register our version
|
|
34
|
-
register.register_model(Extension, id: :extension)
|
|
35
|
-
|
|
24
|
+
# Extension is different in 2.5.2 - register our version.
|
|
36
25
|
# Documentation is same as V20131001 - will be found via fallback
|
|
26
|
+
register_models extension: Extension
|
|
37
27
|
end
|
|
38
28
|
|
|
39
29
|
# XMI 2.5.2 Extension element
|
data/lib/xmi/version.rb
CHANGED
data/lib/xmi/versioned.rb
CHANGED
|
@@ -4,26 +4,30 @@ module Xmi
|
|
|
4
4
|
# Base module for version-specific XMI model trees.
|
|
5
5
|
#
|
|
6
6
|
# Each version module (V20110701, V20131001, V20161101) extends this
|
|
7
|
-
# and
|
|
7
|
+
# and declares its table entry via define_version, keeping only its
|
|
8
|
+
# real delta (version-specific model classes and what to register).
|
|
8
9
|
#
|
|
9
10
|
# @example
|
|
10
11
|
# module Xmi::V20131001
|
|
11
12
|
# extend Xmi::Versioned
|
|
12
13
|
#
|
|
13
|
-
#
|
|
14
|
-
# :xmi_20131001
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# end
|
|
14
|
+
# define_version(
|
|
15
|
+
# register_id: :xmi_20131001,
|
|
16
|
+
# namespaces: [Xmi::Namespace::Omg::Xmi20131001,
|
|
17
|
+
# Xmi::Namespace::Omg::Uml20131001],
|
|
18
|
+
# fallbacks: %i[xmi_20110701 xmi_common default],
|
|
19
|
+
# )
|
|
20
20
|
#
|
|
21
21
|
# def self.register_models!
|
|
22
|
-
#
|
|
22
|
+
# register_models documentation: Documentation
|
|
23
23
|
# end
|
|
24
24
|
# end
|
|
25
25
|
#
|
|
26
26
|
module Versioned
|
|
27
|
+
# Fallback chain used when a version declares none: the common
|
|
28
|
+
# register, then the default register.
|
|
29
|
+
DEFAULT_FALLBACKS = %i[xmi_common default].freeze
|
|
30
|
+
|
|
27
31
|
# @api public
|
|
28
32
|
# Called when a module extends Versioned
|
|
29
33
|
def self.extended(base)
|
|
@@ -33,6 +37,23 @@ module Xmi
|
|
|
33
37
|
end
|
|
34
38
|
end
|
|
35
39
|
|
|
40
|
+
# @api public
|
|
41
|
+
# Declare this version's table entry.
|
|
42
|
+
#
|
|
43
|
+
# Defines register_id, namespace_classes, and fallback_registers on
|
|
44
|
+
# the extending module. Versions that extend Versioned without
|
|
45
|
+
# calling this keep the NotImplementedError contract below.
|
|
46
|
+
#
|
|
47
|
+
# @param register_id [Symbol] Register ID for this version
|
|
48
|
+
# @param namespaces [Array<Class>] XmlNamespace classes to bind
|
|
49
|
+
# @param fallbacks [Array<Symbol>] Fallback register IDs
|
|
50
|
+
# @return [void]
|
|
51
|
+
def define_version(register_id:, namespaces:, fallbacks: DEFAULT_FALLBACKS)
|
|
52
|
+
define_singleton_method(:register_id) { register_id }
|
|
53
|
+
define_singleton_method(:namespace_classes) { namespaces }
|
|
54
|
+
define_singleton_method(:fallback_registers) { fallbacks }
|
|
55
|
+
end
|
|
56
|
+
|
|
36
57
|
# @api public
|
|
37
58
|
# Get the register for this version
|
|
38
59
|
#
|
|
@@ -87,6 +108,15 @@ module Xmi
|
|
|
87
108
|
"Each version must implement #register_models!"
|
|
88
109
|
end
|
|
89
110
|
|
|
111
|
+
# @api public
|
|
112
|
+
# Bulk-register models from a table.
|
|
113
|
+
#
|
|
114
|
+
# @param models [Hash{Symbol => Class}] id → model class
|
|
115
|
+
# @return [void]
|
|
116
|
+
def register_models(models)
|
|
117
|
+
models.each { |id, klass| register.register_model(klass, id: id) }
|
|
118
|
+
end
|
|
119
|
+
|
|
90
120
|
# @api public
|
|
91
121
|
# Get the register ID for this version
|
|
92
122
|
#
|
data/lib/xmi.rb
CHANGED
|
@@ -101,8 +101,7 @@ module Xmi
|
|
|
101
101
|
# @param xml_content [String] XML content
|
|
102
102
|
# @return [Root] Parsed XMI document
|
|
103
103
|
def parse(xml_content)
|
|
104
|
-
|
|
105
|
-
VersionRegistry.parse_with_detected_version(xml_content, Root)
|
|
104
|
+
ParserPipeline.run({ xml: xml_content, root_class: Root })[:root]
|
|
106
105
|
end
|
|
107
106
|
|
|
108
107
|
# @api public
|
|
@@ -112,11 +111,12 @@ module Xmi
|
|
|
112
111
|
# @param version [String] Version string (e.g., "20131001")
|
|
113
112
|
# @return [Root] Parsed XMI document
|
|
114
113
|
def parse_with_version(xml_content, version)
|
|
115
|
-
init_versioning!
|
|
116
114
|
register = VersionRegistry.register_for_version(version)
|
|
117
115
|
raise ArgumentError, "Unknown version: #{version}" unless register
|
|
118
116
|
|
|
119
|
-
|
|
117
|
+
ParserPipeline.run(
|
|
118
|
+
{ xml: xml_content, root_class: Root, register: register },
|
|
119
|
+
)[:root]
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
# @api public
|
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.7.
|
|
4
|
+
version: 0.7.4
|
|
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-08-
|
|
11
|
+
date: 2026-08-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|
|
@@ -211,6 +211,7 @@ files:
|
|
|
211
211
|
- lib/xmi/uml/upper_value.rb
|
|
212
212
|
- lib/xmi/uml/usage.rb
|
|
213
213
|
- lib/xmi/uml/value_specification.rb
|
|
214
|
+
- lib/xmi/uml/value_specs.rb
|
|
214
215
|
- lib/xmi/uml/waypoint.rb
|
|
215
216
|
- lib/xmi/uml_di.rb
|
|
216
217
|
- lib/xmi/uml_di/base.rb
|