ea 0.1.5 → 0.2.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.
- checksums.yaml +4 -4
- data/CLAUDE.md +30 -2
- data/TODO.release/01-release-lutaml-uml-030.md +30 -0
- data/TODO.release/02-fix-lutaml-meta-gem-requires.md +33 -0
- data/TODO.release/03-release-lutaml-0110.md +20 -0
- data/TODO.release/04-update-ea-gemspec-pin.md +23 -0
- data/TODO.release/05-remove-ea-conditional-requires.md +48 -0
- data/TODO.release/06-release-ea-020.md +20 -0
- data/TODO.release/07-migrate-plateau-model.md +35 -0
- data/TODO.release/README.md +15 -0
- data/lib/ea/bridge/qea_to_uml.rb +39 -0
- data/lib/ea/bridge/xmi_to_uml.rb +35 -0
- data/lib/ea/bridge.rb +28 -0
- data/lib/ea/cli/command/repository_builder.rb +1 -1
- data/lib/ea/cli/command/spa.rb +1 -1
- data/lib/ea/diagram/extractor.rb +15 -9
- data/lib/ea/diagram/style_resolver.rb +24 -9
- data/lib/ea/transformations.rb +50 -1
- data/lib/ea/version.rb +1 -1
- data/lib/ea/xmi.rb +17 -0
- data/lib/ea.rb +31 -0
- metadata +15 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af7f7d010d0ca70a7230803dfd39e5037fda7f983e532ee6e4280ee7f472c16d
|
|
4
|
+
data.tar.gz: badde638cef78b714cc82aa872678b346a6f9ca230784984e5fa3771f040d610
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 62d4940b0196c8e603905a05471c1770d904142b35a203a1303e479e4f2e7425afd8fac143641c20cb3d855ffa05c7393735d891897b3a3cae0be3bdcc1e950e
|
|
7
|
+
data.tar.gz: d0e112129ac798cc9b35f55666d40e594d9fc604bc6768f5de9cc5f9ac2a95a3dcb66b50cffa78145392b9d7c952ce576d9e0373df82e3645c689412f5f10ae3
|
data/CLAUDE.md
CHANGED
|
@@ -16,14 +16,42 @@ usable standalone — `lutaml-uml` is an optional dependency for the UML bridge.
|
|
|
16
16
|
|
|
17
17
|
**Dependency graph**:
|
|
18
18
|
```
|
|
19
|
-
ea (standalone — sqlite3, rubyzip, nokogiri,
|
|
20
|
-
└── [optional] lutaml-uml (for Ea::
|
|
19
|
+
ea (standalone — lutaml-model, lutaml-path, sqlite3, rubyzip, xmi, nokogiri, liquid, thor)
|
|
20
|
+
└── [optional, dev] lutaml-uml (for Ea::Bridge::* → Lutaml::Uml::Document)
|
|
21
21
|
|
|
22
22
|
lutaml-uml (UML metamodel + UmlRepository + SPA — no dependency on ea)
|
|
23
23
|
└── lutaml-lml
|
|
24
24
|
└── lutaml (meta-bundle)
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
**Architecture — pure parse vs bridge**:
|
|
28
|
+
|
|
29
|
+
The ea gem has TWO entry points:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
# PURE — no lutaml-uml dependency. Returns internal EA model.
|
|
33
|
+
Ea.parse("model.qea") # → Ea::Qea::Database (SQLite tables as Ruby models)
|
|
34
|
+
Ea.parse("model.xmi") # → Xmi::Sparx::Root (xmi gem's typed Sparx model)
|
|
35
|
+
|
|
36
|
+
# BRIDGE — requires optional lutaml-uml. Returns tool-agnostic UML.
|
|
37
|
+
Ea.to_uml("model.qea") # → Lutaml::Uml::Document (for cross-vendor output)
|
|
38
|
+
Ea.to_uml("model.xmi") # → Lutaml::Uml::Document
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
All lutaml-uml-dependent code lives under `Ea::Bridge::*`:
|
|
42
|
+
- `Ea::Bridge::QeaToUml` — transforms Ea::Qea::Database → Lutaml::Uml::Document
|
|
43
|
+
- `Ea::Bridge::XmiToUml` — transforms Xmi::Sparx::Root → Lutaml::Uml::Document
|
|
44
|
+
|
|
45
|
+
The bridge is lazy-loaded — `require "ea"` does NOT load lutaml-uml. Only calling
|
|
46
|
+
`Ea.to_uml(...)` (or CLI commands that use it: `ea spa`, `ea diagrams extract`)
|
|
47
|
+
triggers the bridge code path.
|
|
48
|
+
|
|
49
|
+
**Native QEA↔XMI round-trip** (no lutaml-uml):
|
|
50
|
+
```
|
|
51
|
+
Ea::Transformers::QeaToXmi — Ea::Qea::Database → Sparx XMI string
|
|
52
|
+
Ea::Transformers::UmlToXmi — Lutaml::Uml::Document → Sparx XMI (bridge)
|
|
53
|
+
```
|
|
54
|
+
|
|
27
55
|
**XMI parsing**: `Ea::Xmi::Parser` is hard-wired to the Sparx schema
|
|
28
56
|
(`::Xmi::Sparx::Root.parse_xml`). It cannot parse MagicDraw or Papyrus XMI.
|
|
29
57
|
When registering with `UmlRepository`, `ea` registers `.xmi` with content
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# 01 — Release lutaml-uml 0.3.0
|
|
2
|
+
|
|
3
|
+
**Status: PENDING**
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
The local lutaml-uml has 10 unpushed commits (559 files, +354k LOC)
|
|
7
|
+
containing the UmlRepository + StaticSite + Vue frontend infrastructure.
|
|
8
|
+
None of this is on rubygems. The published versions (0.2.12, 1.0.0)
|
|
9
|
+
don't include any of it.
|
|
10
|
+
|
|
11
|
+
This blocks ea CI — `lutaml/uml_repository` is not installable from
|
|
12
|
+
rubygems.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
1. Commit all local changes on `chore/consolidate-todos` branch.
|
|
16
|
+
2. Bump version: `0.2.0` → `0.3.0`.
|
|
17
|
+
3. Verify `bundle exec rspec` passes.
|
|
18
|
+
4. Push branch + open PR.
|
|
19
|
+
5. Merge-rebase.
|
|
20
|
+
6. Trigger GHA release.
|
|
21
|
+
|
|
22
|
+
## Version rationale
|
|
23
|
+
0.3.0 not 0.2.13 because the UmlRepository + StaticSite is a major
|
|
24
|
+
feature surface. 0.3.0 continues the 0.x API line (Lutaml::Uml::UmlClass
|
|
25
|
+
etc.) that ea targets. Published 1.0.0 has a different API (renamed
|
|
26
|
+
classes) and should be ignored / yanked.
|
|
27
|
+
|
|
28
|
+
## Verification
|
|
29
|
+
- `gem list -r --exact lutaml-uml` shows 0.3.0.
|
|
30
|
+
- `gem content lutaml-uml --version 0.3.0 | grep uml_repository` succeeds.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# 02 — Fix lutaml meta-gem broken requires
|
|
2
|
+
|
|
3
|
+
**Status: PENDING**
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
`lib/lutaml.rb` requires 6 files that don't exist:
|
|
7
|
+
|
|
8
|
+
```ruby
|
|
9
|
+
require "lutaml/converter" # MISSING
|
|
10
|
+
require "lutaml/ea" # MISSING (ea uses Ea:: namespace)
|
|
11
|
+
require "lutaml/xmi" # MISSING (xmi uses Xmi:: namespace)
|
|
12
|
+
require "lutaml/qea" # MISSING
|
|
13
|
+
require "lutaml/model_transformations" # MISSING
|
|
14
|
+
require "lutaml/cli" # MISSING
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`require "lutaml"` crashes immediately. The meta-gem is unusable.
|
|
18
|
+
|
|
19
|
+
## Fix
|
|
20
|
+
Remove the 6 broken requires. Keep only the ones that resolve to
|
|
21
|
+
real files in the gem's own `lib/` tree:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require_relative "lutaml/version"
|
|
25
|
+
require "lutaml/lml"
|
|
26
|
+
require "lutaml/uml"
|
|
27
|
+
require "lutaml/uml_repository"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Note
|
|
31
|
+
The meta-gem should NOT try to remap other gems' namespaces. The ea
|
|
32
|
+
gem uses `Ea::*`, the xmi gem uses `Xmi::*`. Users who want both should
|
|
33
|
+
`require "ea"` and `require "xmi"` explicitly.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 03 — Release lutaml 0.11.0
|
|
2
|
+
|
|
3
|
+
**Status: PENDING (depends on 02)**
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
Published 0.10.19 has phantom runtime deps (htmlentities, liquid,
|
|
7
|
+
listen, nokogiri, paint, lutaml-path) that shouldn't be in the
|
|
8
|
+
meta-gem gemspec. Plus the 6 broken requires from TODO 02.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
1. After TODO 02 fix is merged.
|
|
12
|
+
2. Bump version: `0.10.19` → `0.11.0`.
|
|
13
|
+
3. Verify `require "lutaml"` works without LoadError.
|
|
14
|
+
4. Push + merge.
|
|
15
|
+
5. Trigger GHA release.
|
|
16
|
+
|
|
17
|
+
## Verification
|
|
18
|
+
- `require "lutaml"` succeeds.
|
|
19
|
+
- No LoadError from missing requires.
|
|
20
|
+
- Published gemspec deps are clean.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 04 — Update ea gemspec pin to ~> 0.3
|
|
2
|
+
|
|
3
|
+
**Status: PENDING (depends on 01)**
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
ea.gemspec pins `spec.add_development_dependency "lutaml-uml", "~> 0.2.0"`.
|
|
7
|
+
This resolves to 0.2.12 on rubygems, which doesn't have UmlRepository.
|
|
8
|
+
CI fails on every PR.
|
|
9
|
+
|
|
10
|
+
## Fix
|
|
11
|
+
```ruby
|
|
12
|
+
# BEFORE:
|
|
13
|
+
spec.add_development_dependency "lutaml-uml", "~> 0.2.0"
|
|
14
|
+
|
|
15
|
+
# AFTER:
|
|
16
|
+
spec.add_development_dependency "lutaml-uml", "~> 0.3"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`~> 0.3` means `>= 0.3.0, < 1.0.0`, which resolves to 0.3.0 (with
|
|
20
|
+
UmlRepository) and excludes the incompatible 1.0.0.
|
|
21
|
+
|
|
22
|
+
## Verification
|
|
23
|
+
- `bundle exec rspec` passes in CI (rubygems mode) without admin override.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# 05 — Remove ea conditional require workarounds
|
|
2
|
+
|
|
3
|
+
**Status: PENDING (depends on 01)**
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
Multiple spec files use `begin/rescue LoadError` around
|
|
7
|
+
`require "lutaml/uml_repository"` because the published gem didn't
|
|
8
|
+
ship the file. After lutaml-uml 0.3.0 is released, these workarounds
|
|
9
|
+
are unnecessary noise.
|
|
10
|
+
|
|
11
|
+
## Files to simplify
|
|
12
|
+
|
|
13
|
+
### spec/spec_helper.rb
|
|
14
|
+
```ruby
|
|
15
|
+
# BEFORE:
|
|
16
|
+
begin
|
|
17
|
+
require "lutaml/uml"
|
|
18
|
+
rescue LoadError
|
|
19
|
+
end
|
|
20
|
+
begin
|
|
21
|
+
require "lutaml/uml_repository"
|
|
22
|
+
rescue LoadError
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# AFTER:
|
|
26
|
+
require "lutaml/uml"
|
|
27
|
+
require "lutaml/uml_repository"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### spec/ea/diagram/extractor_spec.rb
|
|
31
|
+
```ruby
|
|
32
|
+
# BEFORE:
|
|
33
|
+
begin
|
|
34
|
+
require "lutaml/uml_repository/repository"
|
|
35
|
+
rescue LoadError
|
|
36
|
+
end
|
|
37
|
+
RSpec.configure do ... skip ... end
|
|
38
|
+
|
|
39
|
+
# AFTER:
|
|
40
|
+
require "lutaml/uml_repository/repository"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### spec/ea/qea/verification/comprehensive_equivalence_spec.rb
|
|
44
|
+
Same pattern — remove begin/rescue + skip guard.
|
|
45
|
+
|
|
46
|
+
## Verification
|
|
47
|
+
- Full suite passes without any conditional requires.
|
|
48
|
+
- No `skip "lutaml/uml_repository not available"` messages.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 06 — Release ea 0.2.0
|
|
2
|
+
|
|
3
|
+
**Status: PENDING (depends on 04, 05)**
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
ea is at 0.1.6. The gemspec pin change (`~> 0.2.0` → `~> 0.3`) is a
|
|
7
|
+
breaking change for anyone using ea's dev dependency — they need to
|
|
8
|
+
install lutaml-uml 0.3.0. This warrants a minor version bump.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
1. After TODO 04 and 05 are merged.
|
|
12
|
+
2. Bump version: `0.1.6` → `0.2.0`.
|
|
13
|
+
3. Verify `bundle exec rspec` passes in rubygems mode (CI mode).
|
|
14
|
+
4. Push + merge.
|
|
15
|
+
5. Trigger GHA release.
|
|
16
|
+
|
|
17
|
+
## Verification
|
|
18
|
+
- ea 0.2.0 on rubygems.
|
|
19
|
+
- `gem install ea && ea spa model.qea` works with published lutaml-uml 0.3.0.
|
|
20
|
+
- CI passes WITHOUT admin override (first time ever).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# 07 — Migrate plateau-model to ea gem
|
|
2
|
+
|
|
3
|
+
**Status: PENDING (depends on 06)**
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
The plateau-model project (`/Users/mulgogi/src/mn/plateau-model`)
|
|
7
|
+
currently depends on the broken `lutaml` meta-gem via a local path:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# Gemfile
|
|
11
|
+
gem "lutaml", path: "/Users/mulgogi/src/lutaml/lutaml"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
And generates SPA via:
|
|
15
|
+
```bash
|
|
16
|
+
bundle exec lutaml uml build-spa model.qea -o index.html
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Fix
|
|
20
|
+
Switch to the standalone `ea` gem:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
# Gemfile
|
|
24
|
+
source "https://rubygems.org"
|
|
25
|
+
gem "ea", "~> 0.2"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bundle exec ea spa model.qea -o index.html
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Verification
|
|
33
|
+
- Generated index.html is structurally equivalent to the existing one
|
|
34
|
+
(same packages=58, diagrams=188, classes≈600).
|
|
35
|
+
- No dependency on the lutaml meta-gem.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# TODO.release — Streamlined dependency tree
|
|
2
|
+
|
|
3
|
+
Execute each item in order. Each step depends on the previous.
|
|
4
|
+
|
|
5
|
+
## Index
|
|
6
|
+
|
|
7
|
+
| # | Title | Gem | Priority |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| 01 | [Release lutaml-uml 0.3.0](01-release-lutaml-uml-030.md) | lutaml-uml | BLOCKING — critical path |
|
|
10
|
+
| 02 | [Fix lutaml meta-gem broken requires](02-fix-lutaml-meta-gem-requires.md) | lutaml | high — independent of 01 |
|
|
11
|
+
| 03 | [Release lutaml 0.11.0](03-release-lutaml-0110.md) | lutaml | high — depends on 02 |
|
|
12
|
+
| 04 | [Update ea gemspec pin to ~> 0.3](04-update-ea-gemspec-pin.md) | ea | high — depends on 01 |
|
|
13
|
+
| 05 | [Remove ea conditional require workarounds](05-remove-ea-conditional-requires.md) | ea | high — depends on 01 |
|
|
14
|
+
| 06 | [Release ea 0.2.0](06-release-ea-020.md) | ea | high — depends on 04, 05 |
|
|
15
|
+
| 07 | [Migrate plateau-model to ea gem](07-migrate-plateau-model.md) | plateau-model | medium — depends on 06 |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Bridge
|
|
5
|
+
# Transforms an `Ea::Qea::Database` into a `Lutaml::Uml::Document`.
|
|
6
|
+
#
|
|
7
|
+
# This is the bridge between ea's internal EA-native representation
|
|
8
|
+
# (the SQLite-derived row models) and the tool-agnostic UML
|
|
9
|
+
# metamodel from `lutaml-uml`.
|
|
10
|
+
#
|
|
11
|
+
# The heavy lifting is done by the existing factory classes under
|
|
12
|
+
# `Ea::Qea::Factory::*`. This module is the clean public entry
|
|
13
|
+
# point — consumers should call `Ea::Bridge::QeaToUml.transform(db)`
|
|
14
|
+
# rather than reaching into the factory internals.
|
|
15
|
+
module QeaToUml
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
# @param database [Ea::Qea::Database] loaded QEA database
|
|
19
|
+
# @param options [Hash] transformation options
|
|
20
|
+
# @return [Lutaml::Uml::Document]
|
|
21
|
+
def transform(database, options = {})
|
|
22
|
+
require_lutaml_uml!
|
|
23
|
+
factory(database, options).create_document
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def require_lutaml_uml!
|
|
27
|
+
require "lutaml/uml"
|
|
28
|
+
rescue LoadError => e
|
|
29
|
+
raise Ea::Error,
|
|
30
|
+
"Ea::Bridge requires the `lutaml-uml` gem. " \
|
|
31
|
+
"Install it via `gem install lutaml-uml`. (#{e.message})"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def factory(database, options)
|
|
35
|
+
Ea::Qea::Factory::EaToUmlFactory.new(database, options)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Bridge
|
|
5
|
+
# Transforms an `Xmi::Sparx::Root` (the xmi gem's typed Sparx XMI
|
|
6
|
+
# model) into a `Lutaml::Uml::Document`.
|
|
7
|
+
#
|
|
8
|
+
# This is the bridge between ea's internal XMI representation
|
|
9
|
+
# (the xmi gem's model tree) and the tool-agnostic UML metamodel
|
|
10
|
+
# from `lutaml-uml`.
|
|
11
|
+
#
|
|
12
|
+
# The heavy lifting is done by the existing parser code in
|
|
13
|
+
# `Ea::Xmi::Parser`. This module is the clean public entry point
|
|
14
|
+
# — consumers should call `Ea::Bridge::XmiToUml.transform(root)`
|
|
15
|
+
# rather than reaching into the parser internals.
|
|
16
|
+
module XmiToUml
|
|
17
|
+
module_function
|
|
18
|
+
|
|
19
|
+
# @param xmi_root [Xmi::Sparx::Root] parsed xmi gem model
|
|
20
|
+
# @return [Lutaml::Uml::Document]
|
|
21
|
+
def transform(xmi_root)
|
|
22
|
+
require_lutaml_uml!
|
|
23
|
+
Ea::Xmi::Parser.new.parse(xmi_root)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def require_lutaml_uml!
|
|
27
|
+
require "lutaml/uml"
|
|
28
|
+
rescue LoadError => e
|
|
29
|
+
raise Ea::Error,
|
|
30
|
+
"Ea::Bridge requires the `lutaml-uml` gem. " \
|
|
31
|
+
"Install it via `gem install lutaml-uml`. (#{e.message})"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/ea/bridge.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
# The bridge namespace contains ALL code that depends on the
|
|
5
|
+
# optional `lutaml-uml` gem. The rest of the ea gem is pure
|
|
6
|
+
# Sparx EA parsing (QEA SQLite, Sparx XMI) and does NOT require
|
|
7
|
+
# lutaml-uml.
|
|
8
|
+
#
|
|
9
|
+
# The bridge transforms ea's internal model representations:
|
|
10
|
+
#
|
|
11
|
+
# Ea::Qea::Database ──→ Lutaml::Uml::Document
|
|
12
|
+
# Xmi::Sparx::Root ──→ Lutaml::Uml::Document
|
|
13
|
+
#
|
|
14
|
+
# This is the "transformation" layer for cross-vendor UML output.
|
|
15
|
+
# It is NOT needed for:
|
|
16
|
+
# - Parsing QEA/XMI files
|
|
17
|
+
# - Converting QEA ↔ XMI (native Sparx round-trip)
|
|
18
|
+
# - Listing diagrams, elements, stats
|
|
19
|
+
#
|
|
20
|
+
# It IS needed for:
|
|
21
|
+
# - Generating a SPA (via lutaml-uml's StaticSite::Generator)
|
|
22
|
+
# - Rendering diagrams to SVG (via lutaml-uml's Repository)
|
|
23
|
+
# - Producing tool-agnostic UML output for non-Sparx consumers
|
|
24
|
+
module Bridge
|
|
25
|
+
autoload :QeaToUml, "ea/bridge/qea_to_uml"
|
|
26
|
+
autoload :XmiToUml, "ea/bridge/xmi_to_uml"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -29,7 +29,7 @@ module Ea
|
|
|
29
29
|
return Lutaml::UmlRepository::Repository.from_file(path)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
document = Ea::Transformations.
|
|
32
|
+
document = Ea::Transformations.to_uml(path)
|
|
33
33
|
require_lutaml_uml_repository!
|
|
34
34
|
Lutaml::UmlRepository::Repository.from_document(document)
|
|
35
35
|
end
|
data/lib/ea/cli/command/spa.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Ea
|
|
|
10
10
|
# details, diagram list, and member navigation in a browser.
|
|
11
11
|
#
|
|
12
12
|
# Pipeline:
|
|
13
|
-
# 1. Ea::Transformations.
|
|
13
|
+
# 1. Ea::Transformations.to_uml(file) → Lutaml::Uml::Document
|
|
14
14
|
# 2. Lutaml::UmlRepository::Repository.from_document(document)
|
|
15
15
|
# 3. Lutaml::UmlRepository::StaticSite::Generator.new(repo, ...).generate
|
|
16
16
|
#
|
data/lib/ea/diagram/extractor.rb
CHANGED
|
@@ -497,24 +497,30 @@ module Ea
|
|
|
497
497
|
}
|
|
498
498
|
end
|
|
499
499
|
|
|
500
|
-
# Determine element type from UML element
|
|
500
|
+
# Determine element type from UML element. Lazy-resolves
|
|
501
|
+
# Lutaml::Uml::* classes so the file loads cleanly without
|
|
502
|
+
# lutaml-uml installed.
|
|
501
503
|
def element_type(uml_element)
|
|
504
|
+
return "unknown" unless defined?(::Lutaml::Uml)
|
|
505
|
+
|
|
502
506
|
case uml_element
|
|
503
|
-
when Lutaml::Uml::UmlClass then "class"
|
|
504
|
-
when Lutaml::Uml::Package then "package"
|
|
505
|
-
when Lutaml::Uml::DataType then "datatype"
|
|
506
|
-
when Lutaml::Uml::Enum then "enumeration"
|
|
507
|
-
when Lutaml::Uml::Instance then "instance"
|
|
507
|
+
when ::Lutaml::Uml::UmlClass then "class"
|
|
508
|
+
when ::Lutaml::Uml::Package then "package"
|
|
509
|
+
when ::Lutaml::Uml::DataType then "datatype"
|
|
510
|
+
when ::Lutaml::Uml::Enum then "enumeration"
|
|
511
|
+
when ::Lutaml::Uml::Instance then "instance"
|
|
508
512
|
else "unknown"
|
|
509
513
|
end
|
|
510
514
|
end
|
|
511
515
|
|
|
512
516
|
# Determine connector type
|
|
513
517
|
def connector_type(connector)
|
|
518
|
+
return "connector" unless defined?(::Lutaml::Uml)
|
|
519
|
+
|
|
514
520
|
case connector
|
|
515
|
-
when Lutaml::Uml::Association then "association"
|
|
516
|
-
when Lutaml::Uml::Generalization then "generalization"
|
|
517
|
-
when Lutaml::Uml::Dependency then "dependency"
|
|
521
|
+
when ::Lutaml::Uml::Association then "association"
|
|
522
|
+
when ::Lutaml::Uml::Generalization then "generalization"
|
|
523
|
+
when ::Lutaml::Uml::Dependency then "dependency"
|
|
518
524
|
else "connector"
|
|
519
525
|
end
|
|
520
526
|
end
|
|
@@ -231,13 +231,7 @@ module Ea
|
|
|
231
231
|
end
|
|
232
232
|
|
|
233
233
|
# Maps UML connector classes to their style type names.
|
|
234
|
-
#
|
|
235
|
-
CONNECTOR_TYPE_MAP = {
|
|
236
|
-
Lutaml::Uml::Generalization => "generalization",
|
|
237
|
-
Lutaml::Uml::Association => "association",
|
|
238
|
-
Lutaml::Uml::Dependency => "dependency",
|
|
239
|
-
Lutaml::Uml::Realization => "realization",
|
|
240
|
-
}.freeze
|
|
234
|
+
# Built lazily — see {#connector_type_map}.
|
|
241
235
|
|
|
242
236
|
# Association sub-type precedence for style resolution
|
|
243
237
|
ASSOCIATION_SUBTYPE_MAP = {
|
|
@@ -251,18 +245,39 @@ module Ea
|
|
|
251
245
|
def determine_connector_type(connector)
|
|
252
246
|
return "association" unless connector
|
|
253
247
|
|
|
254
|
-
type_name =
|
|
248
|
+
type_name = connector_type_map[connector.class]
|
|
255
249
|
return type_name if type_name && type_name != "association"
|
|
256
250
|
return determine_association_type(connector) if type_name == "association"
|
|
257
251
|
|
|
258
252
|
"association"
|
|
259
253
|
end
|
|
260
254
|
|
|
255
|
+
# Maps UML connector classes to their style type names.
|
|
256
|
+
# Built lazily on first call so the resolver can be loaded
|
|
257
|
+
# without `lutaml/uml` installed (the ea gem is standalone;
|
|
258
|
+
# lutaml-uml is an optional bridge dependency). Adding a new
|
|
259
|
+
# connector type = adding one entry here.
|
|
260
|
+
def connector_type_map
|
|
261
|
+
@connector_type_map ||= build_connector_type_map
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def build_connector_type_map
|
|
265
|
+
map = {}
|
|
266
|
+
return map unless defined?(::Lutaml::Uml)
|
|
267
|
+
|
|
268
|
+
map[::Lutaml::Uml::Generalization] = "generalization"
|
|
269
|
+
map[::Lutaml::Uml::Association] = "association"
|
|
270
|
+
map[::Lutaml::Uml::Dependency] = "dependency"
|
|
271
|
+
map[::Lutaml::Uml::Realization] = "realization"
|
|
272
|
+
map
|
|
273
|
+
end
|
|
274
|
+
|
|
261
275
|
# Determine specific association type
|
|
262
276
|
# @param connector [Object] Association connector
|
|
263
277
|
# @return [String] Specific association type
|
|
264
278
|
def determine_association_type(connector)
|
|
265
|
-
return "association" unless
|
|
279
|
+
return "association" unless defined?(::Lutaml::Uml::Association)
|
|
280
|
+
return "association" unless connector.is_a?(::Lutaml::Uml::Association)
|
|
266
281
|
|
|
267
282
|
[connector.owner_end_type, connector.member_end_type].each do |type|
|
|
268
283
|
resolved = ASSOCIATION_SUBTYPE_MAP[type&.downcase]
|
data/lib/ea/transformations.rb
CHANGED
|
@@ -33,8 +33,57 @@ module Ea
|
|
|
33
33
|
@engine = engine
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# Parse an EA file into its native representation.
|
|
37
|
+
#
|
|
38
|
+
# Pure entry point — does NOT require `lutaml-uml`. Returns:
|
|
39
|
+
# .qea → Ea::Qea::Database
|
|
40
|
+
# .xmi → Xmi::Sparx::Root
|
|
41
|
+
#
|
|
42
|
+
# To get a Lutaml::Uml::Document instead, use {to_uml}.
|
|
43
|
+
#
|
|
44
|
+
# @param file_path [String] path to a .qea or .xmi file
|
|
45
|
+
# @param options [Hash] parser options (e.g. config: for QEA)
|
|
46
|
+
# @return [Ea::Qea::Database, Xmi::Sparx::Root]
|
|
36
47
|
def parse(file_path, options = {})
|
|
37
|
-
|
|
48
|
+
ext = File.extname(file_path).downcase
|
|
49
|
+
case ext
|
|
50
|
+
when ".qea"
|
|
51
|
+
Ea::Qea.load(file_path, options[:config])
|
|
52
|
+
when ".xmi", ".xml"
|
|
53
|
+
Ea::Xmi.load(file_path)
|
|
54
|
+
else
|
|
55
|
+
raise Ea::Error,
|
|
56
|
+
"Unsupported file extension #{ext.inspect}. " \
|
|
57
|
+
"Supported: .qea, .xmi"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Transform an EA file (or pre-parsed model) into a
|
|
62
|
+
# `Lutaml::Uml::Document`.
|
|
63
|
+
#
|
|
64
|
+
# Bridge entry point — requires the optional `lutaml-uml` gem.
|
|
65
|
+
# Lazy-loads the bridge code on first call.
|
|
66
|
+
#
|
|
67
|
+
# @param path_or_model [String, Ea::Qea::Database, Xmi::Sparx::Root]
|
|
68
|
+
# @param options [Hash] transformation options
|
|
69
|
+
# @return [Lutaml::Uml::Document]
|
|
70
|
+
def to_uml(path_or_model, options = {})
|
|
71
|
+
model = if path_or_model.is_a?(String)
|
|
72
|
+
parse(path_or_model, options)
|
|
73
|
+
else
|
|
74
|
+
path_or_model
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
case model
|
|
78
|
+
when Ea::Qea::Database
|
|
79
|
+
Ea::Bridge::QeaToUml.transform(model, options)
|
|
80
|
+
when ::Xmi::Sparx::Root
|
|
81
|
+
Ea::Bridge::XmiToUml.transform(model)
|
|
82
|
+
else
|
|
83
|
+
raise Ea::Error,
|
|
84
|
+
"Cannot transform #{model.class} to Lutaml::Uml::Document. " \
|
|
85
|
+
"Expected Ea::Qea::Database or Xmi::Sparx::Root."
|
|
86
|
+
end
|
|
38
87
|
end
|
|
39
88
|
|
|
40
89
|
def detect_parser(file_path)
|
data/lib/ea/version.rb
CHANGED
data/lib/ea/xmi.rb
CHANGED
|
@@ -31,5 +31,22 @@ module Ea
|
|
|
31
31
|
autoload :ConnectorDrop, "ea/xmi/liquid_drops/connector_drop"
|
|
32
32
|
autoload :SourceTargetDrop, "ea/xmi/liquid_drops/source_target_drop"
|
|
33
33
|
end
|
|
34
|
+
|
|
35
|
+
module_function
|
|
36
|
+
|
|
37
|
+
# Parse an XMI file into the xmi gem's typed Sparx model.
|
|
38
|
+
#
|
|
39
|
+
# Pure entry point — does NOT require `lutaml-uml`. Returns the
|
|
40
|
+
# `Xmi::Sparx::Root` model tree from the `xmi` gem. This is the
|
|
41
|
+
# internal EA-native representation for XMI files.
|
|
42
|
+
#
|
|
43
|
+
# To get a `Lutaml::Uml::Document` instead (requires the optional
|
|
44
|
+
# `lutaml-uml` gem), use `Ea::Bridge::XmiToUml.transform(root)`.
|
|
45
|
+
#
|
|
46
|
+
# @param path [String] path to a .xmi file
|
|
47
|
+
# @return [Xmi::Sparx::Root]
|
|
48
|
+
def load(path)
|
|
49
|
+
::Xmi::Sparx::Root.parse_xml(File.read(path))
|
|
50
|
+
end
|
|
34
51
|
end
|
|
35
52
|
end
|
data/lib/ea.rb
CHANGED
|
@@ -13,5 +13,36 @@ module Ea
|
|
|
13
13
|
autoload :Transformations, "ea/transformations"
|
|
14
14
|
autoload :Xmi, "ea/xmi"
|
|
15
15
|
autoload :Transformers, "ea/transformers"
|
|
16
|
+
autoload :Bridge, "ea/bridge"
|
|
16
17
|
autoload :Cli, "ea/cli"
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
# Parse an EA file into its native representation.
|
|
21
|
+
#
|
|
22
|
+
# Pure entry point — does NOT require the optional `lutaml-uml`
|
|
23
|
+
# gem. The return type depends on the input format:
|
|
24
|
+
#
|
|
25
|
+
# .qea → Ea::Qea::Database (Sparx SQLite tables as Ruby models)
|
|
26
|
+
# .xmi → Xmi::Sparx::Root (typed Sparx XMI model from the xmi gem)
|
|
27
|
+
#
|
|
28
|
+
# @param path [String] path to a .qea or .xmi file
|
|
29
|
+
# @return [Ea::Qea::Database, Xmi::Sparx::Root]
|
|
30
|
+
def parse(path)
|
|
31
|
+
Transformations.parse(path)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Transform an EA file (or pre-parsed model) into a
|
|
35
|
+
# `Lutaml::Uml::Document`.
|
|
36
|
+
#
|
|
37
|
+
# Bridge entry point — requires the optional `lutaml-uml` gem.
|
|
38
|
+
# Used for cross-vendor UML output (e.g. EA → PlantUML via the
|
|
39
|
+
# tool-agnostic UML metamodel). The lutaml-uml dependency is
|
|
40
|
+
# lazy-required on first call.
|
|
41
|
+
#
|
|
42
|
+
# @param path_or_model [String, Ea::Qea::Database, Xmi::Sparx::Root]
|
|
43
|
+
# @return [Lutaml::Uml::Document]
|
|
44
|
+
def to_uml(path_or_model)
|
|
45
|
+
Transformations.to_uml(path_or_model)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
17
48
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ea
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.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-
|
|
11
|
+
date: 2026-07-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|
|
@@ -134,14 +134,14 @@ dependencies:
|
|
|
134
134
|
requirements:
|
|
135
135
|
- - "~>"
|
|
136
136
|
- !ruby/object:Gem::Version
|
|
137
|
-
version: 0.
|
|
137
|
+
version: '0.5'
|
|
138
138
|
type: :development
|
|
139
139
|
prerelease: false
|
|
140
140
|
version_requirements: !ruby/object:Gem::Requirement
|
|
141
141
|
requirements:
|
|
142
142
|
- - "~>"
|
|
143
143
|
- !ruby/object:Gem::Version
|
|
144
|
-
version: 0.
|
|
144
|
+
version: '0.5'
|
|
145
145
|
- !ruby/object:Gem::Dependency
|
|
146
146
|
name: rubocop
|
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -213,6 +213,14 @@ files:
|
|
|
213
213
|
- TODO.next/38-xmi-parser-feature-parity.md
|
|
214
214
|
- TODO.next/39-ea-spa-cli-command.md
|
|
215
215
|
- TODO.next/40-drop-lur-only-check-in-diagrams-extract.md
|
|
216
|
+
- TODO.release/01-release-lutaml-uml-030.md
|
|
217
|
+
- TODO.release/02-fix-lutaml-meta-gem-requires.md
|
|
218
|
+
- TODO.release/03-release-lutaml-0110.md
|
|
219
|
+
- TODO.release/04-update-ea-gemspec-pin.md
|
|
220
|
+
- TODO.release/05-remove-ea-conditional-requires.md
|
|
221
|
+
- TODO.release/06-release-ea-020.md
|
|
222
|
+
- TODO.release/07-migrate-plateau-model.md
|
|
223
|
+
- TODO.release/README.md
|
|
216
224
|
- config/diagram_styles.yml
|
|
217
225
|
- config/model_transformations.yml
|
|
218
226
|
- config/qea_schema.yml
|
|
@@ -238,6 +246,9 @@ files:
|
|
|
238
246
|
- examples/smoke_test_real_qea.rb
|
|
239
247
|
- exe/ea
|
|
240
248
|
- lib/ea.rb
|
|
249
|
+
- lib/ea/bridge.rb
|
|
250
|
+
- lib/ea/bridge/qea_to_uml.rb
|
|
251
|
+
- lib/ea/bridge/xmi_to_uml.rb
|
|
241
252
|
- lib/ea/cli.rb
|
|
242
253
|
- lib/ea/cli/app.rb
|
|
243
254
|
- lib/ea/cli/command.rb
|