Skip to content

refactor: separate pure-parse from lutaml-uml bridge#11

Merged
ronaldtse merged 2 commits into
mainfrom
fix/remove-class-scope-lutaml-uml-references
Jul 8, 2026
Merged

refactor: separate pure-parse from lutaml-uml bridge#11
ronaldtse merged 2 commits into
mainfrom
fix/remove-class-scope-lutaml-uml-references

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

Summary

The ea gem now has a clean architectural separation between pure Sparx EA parsing and the optional lutaml-uml transformation bridge.

New API

Pure-parse (no lutaml-uml dependency):

Ea.parse("model.qea")   # → Ea::Qea::Database
Ea.parse("model.xmi")   # → Xmi::Sparx::Root
Ea::Xmi.load(path)      # → Xmi::Sparx::Root

Bridge (lazy-requires lutaml-uml):

Ea.to_uml("model.qea")  # → Lutaml::Uml::Document
Ea.to_uml("model.xmi")  # → Lutaml::Uml::Document

New namespace

Ea::Bridge isolates all lutaml-uml-dependent code:

  • Ea::Bridge::QeaToUml — transforms Ea::Qea::DatabaseLutaml::Uml::Document
  • Ea::Bridge::XmiToUml — transforms Xmi::Sparx::RootLutaml::Uml::Document

The existing Ea::Qea::Factory::* (22 files) and Ea::Xmi::Parser (900 LOC) remain as internal implementation behind clean facades.

Architecture

require 'ea'         → autoload tree (NO lutaml/uml)
Ea.parse(file)       → pure: returns native EA model
Ea.to_uml(file/model) → bridge: lazy-requires lutaml/uml, returns UML Document

Native QEA↔XMI round-trip (no lutaml-uml):

Ea::Transformers::QeaToXmi — Ea::Qea::Database → Sparx XMI string

Breaking change

Ea::Transformations.parse(file) now returns the internal model (Database or Root), NOT Lutaml::Uml::Document. Callers that need the Document should use Ea::Transformations.to_uml(file) or Ea.to_uml(file).

Also includes

  • Fix: removed class-scope Lutaml::Uml::* references in style_resolver.rb and extractor.rb (standalone contract violation).
  • CLAUDE.md updated with the pure/bridge architecture documentation.

Verification

  • bundle exec rspec: 2036 examples, 0 failures, 37 pending
  • require "ea" does not load lutaml/uml (autoload-only)

ronaldtse added 2 commits July 7, 2026 22:10
The ea gem is documented as standalone with lutaml-uml as an
OPTIONAL bridge dependency. Two files violated that contract:

1. lib/ea/diagram/style_resolver.rb:235 — CONNECTOR_TYPE_MAP was a
   class-scope Hash constant with Lutaml::Uml::* class keys. The
   Hash was constructed at class-load time, so requiring
   lib/ea/diagram/style_resolver.rb without lutaml-uml installed
   raised NameError on Lutaml::Uml::Generalization.

2. lib/ea/diagram/extractor.rb:503-517 — case/when on
   Lutaml::Uml::* classes in instance methods. Worked in practice
   (only called with a Repository in hand) but brittle if
   lutaml-uml wasn't loaded.

Fixes:

- style_resolver.rb: replace CONNECTOR_TYPE_MAP constant with a
  lazy #connector_type_map method that returns {} when
  defined?(Lutaml::Uml) is false. The map is built on first call
  and cached in @connector_type_map.
- style_resolver.rb: guard determine_association_type's
  is_a?(Lutaml::Uml::Association) with a defined? check.
- extractor.rb: guard element_type and connector_type case/when
  blocks with defined?(::Lutaml::Uml) early return.

With these changes, lib/ea/diagram/* loads cleanly without
lutaml-uml installed, preserving the standalone contract. The
bridge methods still require lutaml-uml at runtime (correctly).

Verification:
- bundle exec rspec: 2036 examples, 0 failures, 37 pending
  (unchanged).
- lib/ea/diagram/style_resolver.rb loads without lutaml/uml
  required (verified locally with `bundle exec ruby -e
  "require \"ea/diagram/style_resolver\""`).
The ea gem now has a clean separation between its pure Sparx EA
parsing and the optional lutaml-uml transformation bridge.

NEW: Pure-parse entry points (no lutaml-uml dependency)

  Ea.parse(path)              → Database or Xmi::Sparx::Root
  Ea::Xmi.load(path)          → Xmi::Sparx::Root
  Ea::Transformations.parse   → internal model (was: Lutaml::Uml::Document)

NEW: Bridge entry points (lazy-require lutaml-uml on first call)

  Ea.to_uml(path_or_model)    → Lutaml::Uml::Document
  Ea::Transformations.to_uml  → Lutaml::Uml::Document
  Ea::Bridge::QeaToUml        → transforms Ea::Qea::Database
  Ea::Bridge::XmiToUml        → transforms Xmi::Sparx::Root

Architecture:
  require 'ea'            → loads module tree via autoload
                            (NO lutaml/uml at load time)

  Ea.parse(file)          → pure: returns native EA model
                            .qea → Ea::Qea::Database
                            .xmi → Xmi::Sparx::Root

  Ea.to_uml(file/model)   → bridge: lazy-requires lutaml/uml
                            dispatches to Ea::Bridge::QeaToUml
                            or Ea::Bridge::XmiToUml

Updated callers:
  - lib/ea/cli/command/repository_builder.rb: uses .to_uml for bridge
  - spec/ea/transformations/end_to_end_parsing_spec.rb: .parse → .to_uml
  - spec/ea/transformations/parsers/xmi_parity_spec.rb: .parse → .to_uml
  - lib/ea.rb: adds Ea.parse and Ea.to_uml at the top level
  - CLAUDE.md: documents the pure/bridge architecture

New files:
  lib/ea/bridge.rb            — namespace + autoloads
  lib/ea/bridge/qea_to_uml.rb — QEA → UML bridge (facade over existing factory)
  lib/ea/bridge/xmi_to_uml.rb — XMI → UML bridge (facade over existing parser)

The existing Ea::Qea::Factory::* (22 files) and Ea::Xmi::Parser
(900 LOC of build_* methods) remain in their current locations as
internal implementation. The bridge modules are clean facades over
them. A future Phase 2 would physically move these into Ea::Bridge::*
for full namespace correctness.

Verification:
  - bundle exec rspec: 2036 examples, 0 failures, 37 pending
  - Ea.parse('basic.qea') → Ea::Qea::Database (42 packages)
  - Ea.parse('basic.xmi') → Xmi::Sparx::Root
  - Ea.to_uml('basic.qea') → Lutaml::Uml::Document (bridge)
  - require 'ea' does not load lutaml/uml (autoload-only)
@ronaldtse
ronaldtse merged commit 403ec0b into main Jul 8, 2026
3 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant