Skip to content

[Add] Sirius object model + .aird reading; split Auriga.Core / Auriga.Xmi.Core (closes #52)#64

Open
samatstariongroup wants to merge 5 commits into
developmentfrom
GH52
Open

[Add] Sirius object model + .aird reading; split Auriga.Core / Auriga.Xmi.Core (closes #52)#64
samatstariongroup wants to merge 5 commits into
developmentfrom
GH52

Conversation

@samatstariongroup

@samatstariongroup samatstariongroup commented Jul 11, 2026

Copy link
Copy Markdown
Member

Closes #52 (Phase A of the .aird support epic #50), and adds the first working .aird read
path plus the assembly refactor that keeps the Sirius and Capella stacks independent.

This branch grew past the original #52 scope (which was "generate the Sirius object model"). It now
contains four coherent pieces:

  1. [Add] A2 — Generate the Sirius/GMF object model + XMI readers/writers #52 — generate the Auriga.Sirius object model + Auriga.Sirius.Xmi readers/writers.
  2. Read real .aird files into that object model.
  3. Auriga.Core — extract the shared object-model base types.
  4. Auriga.Xmi.Core — extract the shared, metamodel-agnostic XMI runtime.

1. Generate the Sirius/GMF object model + readers/writers (#52)

Drives the existing metamodel-agnostic Auriga.CodeGenerator at the vendored Sirius/GMF metamodels
(resources/ecore-sirius, from #51) to emit a separate Auriga.Sirius object model and
Auriga.Sirius.Xmi readers/writers.

  • Auriga.Sirius — the Sirius viewpoint/diagram/sequence/table + GMF notation object model:
    454 interfaces, 357 classes, 39 enums.
  • Auriga.Sirius.Xmi — per-type readers + writers, a reader facade + namespace registry, and a
    writer facade.

Generator changes (metamodel-neutral; parameterized by a single thread-scoped rootNamespace knob
via the new NamingContext):

  • Root namespace made configurable (default Auriga; a Sirius run passes Auriga.Sirius).
  • Member/type name collision handling: a feature whose C# member name equals a concrete class
    that declares/inherits it (e.g. GMF View.diagram inherited by Diagram) gets a trailing _;
    the XML name stays the raw Ecore name.
  • Type mapping: the 12 Sirius/GMF EDataTypes and the opaque Ecore system datatypes map to
    string/object; a containment of ecore::EObject is typed as IAurigaElement.
  • Multi-valued docs / enums: multi-line Ecore docs split across /// lines; multi-valued enum
    attributes read/write as whitespace-delimited lists (new WriteEnumListAttribute).
  • Whole-metamodel generation emits all declared enums, not only the reachable closure.

SiriusGeneratorTestFixture mirrors the Capella drift guard: determinism, classifier counts
(454/39 from docs/sirius-metamodel-inventory.md), and a comprehensive regenerate-and-compare guard
over every committed file. Explicit Regenerate_sirius_* tests rewrite the committed code.

2. Read real .aird files

SiriusXmiReaderBuilder.Create().Build().Read(path) reads an .aird into the typed Auriga.Sirius
graph. Making that work drove three genuine, metamodel-neutral fixes to the reader, uncovered by the
first .aird reading test:

  • xmi:XMI multi-root — an .aird wraps ~7 parallel top-level roots (1 viewpoint:DAnalysis +
    N diagram:DSemanticDiagram/sequence:SequenceDDiagram). XmiReader now reads every child of the
    xmi:XMI wrapper into one shared graph and returns the DAnalysis as Root.
  • xmi:type as well as xsi:type — Capella serializes xsi:type, Sirius serializes xmi:type
    (EMF treats them as interchangeable). The facade's ResolveTypeKey now reads either.
  • Identity id / xmi:id / uid — Capella uses a bare id, GMF uses xmi:id, the Sirius
    representation model uses uid. The reader now takes the first present, so every element is cached
    and its cross-references resolve.

coffee-machine-demo.aird reads into 591 typed representation elements (DNodes, DEdges, styles,
filters), rooted at a DAnalysis, with intra-.aird references resolving.

Known follow-ups (documented in the tests as Assert.Ignore, not silently dropped):

3. Auriga.Core — shared object-model base types

Extracts IAurigaElement, AurigaElement, IContainerList<T>, ContainerList<T> into a new
Auriga.Core assembly (namespace Auriga preserved). Auriga.Sirius now references Auriga.Core
instead of Auriga, so it no longer drags in the entire Capella object model.

4. Auriga.Xmi.Core — shared XMI runtime

Extracts the metamodel-agnostic runtime — the two-pass XmiReader, element cache, namespace
resolver, reference resolver, href parsing, and the XmiElementReader<T>/XmiElementWriter base
classes — into Auriga.Xmi.Core (namespaces Auriga.Xmi.* preserved). Auriga.Xmi keeps only the
Capella-specific CapellaModelLoader/CapellaProject/XmiReaderBuilder/XmiWriterBuilder + the
Capella AutoGen*. Auriga.Sirius.Xmi now references Auriga.Xmi.Core.

Result — Auriga.Xmi and Auriga.Sirius.Xmi are independent siblings; verified that
Auriga.Sirius.Xmi's build output contains no Auriga.dll or Auriga.Xmi.dll (Capella):

Auriga.Core ◄─ Auriga (Capella)      ◄─ Auriga.Xmi         (Capella readers/writers)
     ▲                                        │
     └──── Auriga.Xmi.Core ◄──────────────────┤
                 ▲   ▲
Auriga.Core ◄─ Auriga.Sirius         ◄─ Auriga.Sirius.Xmi  (Sirius readers/writers)

Both extractions are zero-regeneration: the types kept their original namespaces and only moved
assembly, so every generated file that references Auriga.AurigaElement /
Auriga.Xmi.Readers.XmiElementReader<T> compiles unchanged.

Impact on Capella

Capella output is no longer byte-for-byte identical (the two reader/facade template fixes in §2
regenerated 276 Capella reader files, the facade, and 7 Expected golden files). It is, however,
behavior-preserving: Capella uses xsi:type + id, so the new xmi:type/uid fallbacks are
never exercised there. Confirmed by the unchanged Capella golden/drift + round-trip suites staying
green.

Verification

  • dotnet build Auriga.sln0 errors.
  • Full suite: 247 passed, 5 skipped (the 5 skips = 3 documented .aird follow-ups above + the 2
    pre-existing add-on-viewpoint round-trip skips).

Packaging

Adds Auriga.Core and Auriga.Xmi.Core as two further packages, and each model/xmi package takes a
package dependency on its core. If you'd rather not publish the new assemblies until the reader work
matures, say so and I'll set IsPackable=false on the additions.

@samatstariongroup samatstariongroup changed the title [Add] Generate Sirius/GMF object model + XMI readers/writers (Auriga.Sirius) (closes #52) [Add] Sirius object model + .aird reading; split Auriga.Core / Auriga.Xmi.Core (closes #52) Jul 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor
Package Line Rate Branch Rate Complexity Health
Auriga 38% 53% 15509
Auriga.CodeGenerator 92% 87% 451
Auriga.Core 97% 98% 65
Auriga.Extensions 97% 88% 48
Auriga.Reporting 0% 0% 12
Auriga.Sirius 5% 2% 5107
Auriga.Sirius.Xmi 6% 5% 24361
Auriga.Xmi 24% 13% 41264
Auriga.Xmi.Core 92% 84% 367
Summary 21% (30176 / 146798) 16% (12243 / 74832) 87184

@sonarqubecloud

Copy link
Copy Markdown

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.

[Add] A2 — Generate the Sirius/GMF object model + XMI readers/writers

1 participant