ea 0.5.0 → 0.5.2
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/CHANGELOG.md +128 -1
- data/TODO.complete/51-remove-respond-to.md +25 -0
- data/TODO.complete/52-xsd-decouple-fixtures.md +23 -0
- data/TODO.complete/53-xmi-public-send-cleanup.md +26 -0
- data/TODO.complete/54-wire-stereotype-icon-renderer.md +20 -0
- data/TODO.complete/55-wire-shapescript.md +20 -0
- data/TODO.complete/56-wire-emf-renderer.md +27 -0
- data/TODO.complete/57-wire-ocl-evaluator.md +23 -0
- data/TODO.complete/58-diff-modifications.md +21 -0
- data/TODO.complete/59-delete-toy-xmi-export.md +30 -0
- data/TODO.complete/60-curate-json-export.md +20 -0
- data/TODO.complete/61-plantuml-relationships.md +22 -0
- data/TODO.complete/62-changelog.md +17 -0
- data/TODO.complete/63-dependabot-fix.md +18 -0
- data/TODO.complete/64-qeatoxmi-connectors.md +30 -0
- data/TODO.complete/65-qeatoxmi-diagrams.md +29 -0
- data/TODO.complete/66-qeatoxmi-style-tags-docs.md +28 -0
- data/TODO.complete/67-ocl-collection-ops.md +20 -0
- data/TODO.complete/68-ocl-comparison-ops.md +19 -0
- data/TODO.complete/69-spec-new-models.md +25 -0
- data/TODO.complete/STATUS.md +40 -64
- data/lib/ea/cli/command/convert.rb +1 -1
- data/lib/ea/cli/command/export.rb +23 -2
- data/lib/ea/diff/comparator.rb +28 -1
- data/lib/ea/export/json/generator.rb +84 -8
- data/lib/ea/export/plantuml/generator.rb +95 -28
- data/lib/ea/export/xsd/generator.rb +10 -15
- data/lib/ea/export.rb +0 -1
- data/lib/ea/lint/rules/missing_stereotype.rb +16 -11
- data/lib/ea/ocl/evaluator.rb +39 -2
- data/lib/ea/ocl/nodes.rb +9 -0
- data/lib/ea/ocl/parser.rb +60 -6
- data/lib/ea/qea/models/ea_implement.rb +2 -2
- data/lib/ea/qea/models/ea_object_effort.rb +2 -2
- data/lib/ea/qea/models/ea_object_problem.rb +2 -2
- data/lib/ea/qea/models/ea_object_require.rb +2 -2
- data/lib/ea/qea/models/ea_object_resource.rb +2 -2
- data/lib/ea/qea/models/ea_object_risk.rb +2 -2
- data/lib/ea/qea/models/ea_object_scenario.rb +2 -2
- data/lib/ea/qea/models/ea_object_test.rb +2 -2
- data/lib/ea/qea/models/ea_object_trx.rb +2 -2
- data/lib/ea/qea/models/ea_palette_item.rb +2 -2
- data/lib/ea/qea/models/ea_role_constraint.rb +2 -2
- data/lib/ea/qea/models/ea_secrypt.rb +2 -2
- data/lib/ea/qea/validation/database/ocl_constraint_validator.rb +65 -0
- data/lib/ea/qea/validation/database.rb +2 -0
- data/lib/ea/qea/validation/validation_engine.rb +2 -0
- data/lib/ea/qea/validation.rb +2 -0
- data/lib/ea/query/builder.rb +22 -3
- data/lib/ea/svg/ea_emitter/compartment/stereotype_icon.rb +32 -0
- data/lib/ea/svg/ea_emitter/compartment.rb +2 -0
- data/lib/ea/svg/ea_emitter/document.rb +33 -0
- data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +49 -12
- data/lib/ea/transformers/qea_to_xmi/transformer.rb +138 -2
- data/lib/ea/transformers.rb +3 -2
- data/lib/ea/validation/xmi_parity.rb +80 -0
- data/lib/ea/validation.rb +12 -0
- data/lib/ea/version.rb +1 -1
- data/lib/ea.rb +1 -0
- metadata +24 -3
- data/lib/ea/export/xmi/generator.rb +0 -77
- data/lib/ea/export/xmi.rb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: feec20be82e181c35e21063e8faaefc697c466aeb96ea462a1e1911e20656863
|
|
4
|
+
data.tar.gz: a15bbc9f5d6f078d712f436584175ad4901bad1b2918c9d6f163de1be64b0c21
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c0ea25f28a1e8dfe0b7d923deb5340f3da3d3aefd8f95b284e80b3de6126756dba1dc96563113b3c64a918c7962fd351361a84f3afc066f304479847625ac7e
|
|
7
|
+
data.tar.gz: 0d68e3d7eea42bcc0d8008c84d5a69d58f94702981659174aa18f6ad7f67bcb07554e054e795aa7fde3716d63597ec71ee1e6148f187935d5c141c9cb2e94835
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,132 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `ea` gem are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
1
8
|
## [Unreleased]
|
|
2
9
|
|
|
3
|
-
## [0.1
|
|
10
|
+
## [0.5.1] — 2026-08-03
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Stereotype decorator icons now render inside element bodies via the
|
|
14
|
+
new `Compartment::StereotypeIcon` module. Falls back to hardcoded
|
|
15
|
+
polygons for FeatureType/Type; uses MDG-provided ShapeScript when
|
|
16
|
+
available.
|
|
17
|
+
- OCL constraint evaluation wired into `ea validate`. Invariants from
|
|
18
|
+
`t_objectconstraint` are parsed and evaluated against owning
|
|
19
|
+
objects' attribute values.
|
|
20
|
+
- Image rendering infrastructure: `Document#emit_images` walks the
|
|
21
|
+
`:images` collection and inlines `EmfRenderer` output. Gracefully
|
|
22
|
+
skips when `emfsvg` returns nil (current state — upstream parser
|
|
23
|
+
can't decode EA's EMF variant yet).
|
|
24
|
+
- Diff comparator detects `:modified` changes via `to_hash`
|
|
25
|
+
comparison (was: add/remove/rename only).
|
|
26
|
+
- PlantUML export now emits package nesting, generalizations
|
|
27
|
+
(`<\|--`), and composition arrows (`o--`, `*--`).
|
|
28
|
+
- JSON export uses a per-class projection schema (no more raw
|
|
29
|
+
`to_hash` dumping Lutaml::Model internals).
|
|
30
|
+
- CHANGELOG.md with full release history.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- `ea export xmi` now routes to the full `Ea::Transformers::QeaToXmi`
|
|
34
|
+
(142 KB Sparx XMI) instead of the toy hand-rolled generator. The
|
|
35
|
+
toy `Ea::Export::Xmi` namespace is deleted.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
- Removed all `respond_to?` calls from lib code (5 sites) — replaced
|
|
39
|
+
with `is_a?` type checks per the typing rule.
|
|
40
|
+
- Renamed `object_id` attribute to `ea_object_id` in 12 new QEA
|
|
41
|
+
models to avoid collision with Ruby's `Object#object_id`.
|
|
42
|
+
- XSD Generator no longer hardcodes `spec/fixtures/` paths; the CLI
|
|
43
|
+
layer loads fixtures and passes parsed data.
|
|
44
|
+
- Bumped `lycheeverse/lychee-action` v1 → v2 (dependabot alert).
|
|
45
|
+
|
|
46
|
+
## [0.5.0] — 2026-08-03
|
|
47
|
+
|
|
48
|
+
### Added — CLI commands (13 new)
|
|
49
|
+
- `ea diff OLD NEW` — structural comparison of two QEA files
|
|
50
|
+
(`--format=html` produces a color-coded HTML report).
|
|
51
|
+
- `ea render NAME FILE` — unified rendering (SVG/PNG/PDF via
|
|
52
|
+
rsvg-convert or ImageMagick).
|
|
53
|
+
- `ea export SUB FILE` — exports: `xmi`, `json`, `json-schema`,
|
|
54
|
+
`plantuml`, `xsd`.
|
|
55
|
+
- `ea mdg ACTION` — list registered MDG technologies, show
|
|
56
|
+
stereotype details, list all stereotypes.
|
|
57
|
+
- `ea lint FILE` — model quality checks (naming convention,
|
|
58
|
+
orphan elements, duplicate names, cyclic generalizations,
|
|
59
|
+
missing stereotypes).
|
|
60
|
+
- `ea query FILE` — filter elements via a chainable DSL
|
|
61
|
+
(by type, package, stereotype, name).
|
|
62
|
+
- `ea info NAME FILE` — show details of a single element.
|
|
63
|
+
|
|
64
|
+
### Added — Subsystems
|
|
65
|
+
- `Ea::Sources::Qea::Xref` — parser for `t_xref.Description`
|
|
66
|
+
(stereotype applications, tagged-value specs, legend definitions).
|
|
67
|
+
- `Ea::Mdg::StereotypeAliasRegistry` — canonicalizes variant
|
|
68
|
+
stereotype spellings via GMLStereotypes.xml.
|
|
69
|
+
- `Ea::Export::Xsd::Generator` — GMLClassMapping-driven XSD
|
|
70
|
+
schema generation.
|
|
71
|
+
- `Ea::Export::JsonSchema::Generator` — JSON Schema (draft
|
|
72
|
+
2020-12) export.
|
|
73
|
+
- `Ea::Export::Json::Generator`, `Ea::Export::PlantUml::Generator`
|
|
74
|
+
— JSON and PlantUML exports.
|
|
75
|
+
- `Ea::Image::EmfRenderer` — lazy emfsvg adapter for EMF→SVG.
|
|
76
|
+
- `Ea::Render::ImageConverter` — SVG → PNG / PDF via system tools.
|
|
77
|
+
- `Ea::Lint` — engine + 5 rules (OCP: new rule = new class).
|
|
78
|
+
- `Ea::Ocl` — OCL invariant parser + evaluator (subset: exists,
|
|
79
|
+
forAll, matches, and/or/not, attribute access).
|
|
80
|
+
- `Ea::Shapescript` — ShapeScript parser + renderer with
|
|
81
|
+
variables, arithmetic, conditionals, subshapes, labels.
|
|
82
|
+
- `Ea::Svg::EaEmitter::Element::HeaderLinePipeline` — OCP-friendly
|
|
83
|
+
provider chain replacing the monolithic HeaderLines module.
|
|
84
|
+
- `Ea::Svg::EaEmitter::Element::StereotypeIconRenderer` — emits
|
|
85
|
+
stereotype decorator icons inside element bodies.
|
|
86
|
+
|
|
87
|
+
### Added — QEA table coverage (24 → 43 tables)
|
|
88
|
+
- `t_image`, `t_glossary`, `t_lists`, `t_versions`, `t_phase`,
|
|
89
|
+
`t_authors`, `t_secrypt`, `t_palette`, `t_paletteitem`,
|
|
90
|
+
`t_implement`, `t_roleconstraint`, `t_objectproblems`,
|
|
91
|
+
`t_objectrisks`, `t_objecttests`, `t_objecteffort`,
|
|
92
|
+
`t_objectresource`, `t_objectscenarios`, `t_objectrequires`,
|
|
93
|
+
`t_objecttrx`.
|
|
94
|
+
|
|
95
|
+
### Changed
|
|
96
|
+
- `Ea::Svg::EaEmitter::Element::HeaderLines` is now a thin alias
|
|
97
|
+
to the new `HeaderLinePipeline` (OCP provider chain).
|
|
98
|
+
- Per-label styling fields (`BLD`, `ITA`, `UND`, `CLR`, `ALN`,
|
|
99
|
+
`DIR`, `ROT`) parsed from `t_diagramlinks.Geometry`.
|
|
100
|
+
- Six new PDATA flag accessors on `Ea::Diagram::DisplayConfig`:
|
|
101
|
+
`ShowEStereo`, `ShowSN`, `OpParams`, `UseAlias`, `SuppCN`,
|
|
102
|
+
`ShowCons`, `ScalePI`.
|
|
103
|
+
- `TableReader#table_exists?` — DatabaseLoader skips missing
|
|
104
|
+
tables gracefully instead of raising.
|
|
105
|
+
- `Ea::Export::Xmi` removed — `ea export xmi` now routes through
|
|
106
|
+
the established `Ea::Transformers::QeaToXmi` (full-fidelity
|
|
107
|
+
Sparx round-trip) instead of a toy generator.
|
|
108
|
+
|
|
109
|
+
### Removed
|
|
110
|
+
- `Ea::Codegen` — speculative. We don't know what EA's actual
|
|
111
|
+
codegen does, so building our own was wrong.
|
|
112
|
+
- Plugin system TODO — not needed.
|
|
113
|
+
- Liquid template integration TODO — `lutaml-model` already
|
|
114
|
+
supports liquid drops natively.
|
|
115
|
+
|
|
116
|
+
### Fixed
|
|
117
|
+
- Replaced all `respond_to?` calls in lib code with `is_a?`
|
|
118
|
+
type checks.
|
|
119
|
+
- Renamed `object_id` attribute to `ea_object_id` in 12 new
|
|
120
|
+
QEA models to avoid collision with Ruby's `Object#object_id`.
|
|
121
|
+
|
|
122
|
+
### Spec coverage
|
|
123
|
+
- 1974 examples, 0 failures, 55 pending.
|
|
124
|
+
|
|
125
|
+
## [0.4.0] — 2026-07-21
|
|
126
|
+
|
|
127
|
+
Initial public release of the standalone parser (QEA + Sparx XMI),
|
|
128
|
+
diagram SVG rendering, and UML bridge.
|
|
129
|
+
|
|
130
|
+
## [0.1.0] — 2026-05-23
|
|
4
131
|
|
|
5
132
|
- Initial release
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# TODO.complete/51: Remove `respond_to?` from lib code
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
The user's rule: "never use respond_to (poor typing)". Five call
|
|
6
|
+
sites violate it, all added in recent sessions:
|
|
7
|
+
|
|
8
|
+
- lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb:61
|
|
9
|
+
- lib/ea/lint/rules/missing_stereotype.rb:29
|
|
10
|
+
- lib/ea/query/builder.rb:66
|
|
11
|
+
- lib/ea/ocl/evaluator.rb:41, 52
|
|
12
|
+
|
|
13
|
+
## Plan
|
|
14
|
+
|
|
15
|
+
Replace `respond_to?(:x)` with explicit type checks via `is_a?`:
|
|
16
|
+
|
|
17
|
+
- For `stereotype_refs` checks: `classifier.is_a?(Ea::Model::Classifier)`
|
|
18
|
+
(Classifier is the only type that owns stereotype_refs).
|
|
19
|
+
- For `each` checks: `collection.is_a?(Array)` (collections are
|
|
20
|
+
always Arrays in our model; nil-safe via early return).
|
|
21
|
+
|
|
22
|
+
## Acceptance
|
|
23
|
+
|
|
24
|
+
- `grep -rn "respond_to?" lib/ea/` returns 0 hits.
|
|
25
|
+
- Existing specs still pass.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# TODO.complete/52: Decouple XSD Generator from fixture paths
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Export::Xsd::Generator` hardcodes:
|
|
6
|
+
DEFAULT_MAPPING_PATH = "spec/fixtures/mdg/ea_config/gml/GMLClassMapping.xml"
|
|
7
|
+
|
|
8
|
+
Lib code should never reference `spec/` paths. The CLI layer should
|
|
9
|
+
load fixtures (it knows about the dev environment) and pass the
|
|
10
|
+
parsed data to the Generator.
|
|
11
|
+
|
|
12
|
+
## Plan
|
|
13
|
+
|
|
14
|
+
1. Generator's `initialize` defaults to empty `ClassMapping.new` /
|
|
15
|
+
`NamespaceRegistry.new` (no file IO).
|
|
16
|
+
2. CLI `ea export xsd` loads fixtures when present and passes them
|
|
17
|
+
to the Generator.
|
|
18
|
+
3. Generator stays pure: data in, XSD out.
|
|
19
|
+
|
|
20
|
+
## Acceptance
|
|
21
|
+
|
|
22
|
+
- `grep -n "spec/fixtures" lib/ea/export/` returns 0 hits.
|
|
23
|
+
- `ea export xsd` still produces valid XSD when run from repo root.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# TODO.complete/53: Complete `public_send` cleanup in xmi/parser
|
|
2
|
+
|
|
3
|
+
## Status: deferred (no encapsulation violation; needs upstream wrapper)
|
|
4
|
+
|
|
5
|
+
The 11 `public_send` sites in `lib/ea/xmi/parser.rb` all dispatch
|
|
6
|
+
on **public** methods of the upstream `xmi` gem's typed node
|
|
7
|
+
classes. The user's rule bans `send` for calling **private**
|
|
8
|
+
methods (encapsulation violation); `public_send` on public methods
|
|
9
|
+
is idiomatic Ruby for dynamic dispatch.
|
|
10
|
+
|
|
11
|
+
Removing these calls would require either:
|
|
12
|
+
1. Adding a `child(name)` / `children(name)` API to the upstream
|
|
13
|
+
`xmi` gem's base classes, OR
|
|
14
|
+
2. Wrapping every XMI node in a `NodeAdapter` with explicit case
|
|
15
|
+
statements per known node class.
|
|
16
|
+
|
|
17
|
+
Both are substantial refactors with no functional benefit. The
|
|
18
|
+
current code works correctly.
|
|
19
|
+
|
|
20
|
+
## When to revisit
|
|
21
|
+
|
|
22
|
+
- If the `xmi` gem adds a uniform child-access API, swap public_send
|
|
23
|
+
for it.
|
|
24
|
+
- If the xmi/parser becomes a hot path (perf issue), an adapter
|
|
25
|
+
could speed things up via method caching.
|
|
26
|
+
- Until then, the existing public_send on public methods is fine.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# TODO.complete/54: Wire StereotypeIconRenderer into SVG emitter
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Svg::EaEmitter::Element::StereotypeIconRenderer` is defined
|
|
6
|
+
and autoloaded but never invoked. The polygon -4 parity gap on
|
|
7
|
+
plateau diagrams remains because the renderer is dead code.
|
|
8
|
+
|
|
9
|
+
## Plan
|
|
10
|
+
|
|
11
|
+
1. Call `StereotypeIconRenderer.render(...)` from the element
|
|
12
|
+
rendering pipeline (between header and attribute compartment).
|
|
13
|
+
2. Pass: classifier, bounds, canvas.
|
|
14
|
+
3. Insert the emitted polygon into the element's `<g>` group.
|
|
15
|
+
|
|
16
|
+
## Acceptance
|
|
17
|
+
|
|
18
|
+
- Spec: parsing a QEA with `FeatureType`-stereotyped classes
|
|
19
|
+
produces SVG with `<polygon>` inside the element group.
|
|
20
|
+
- Parity harness: plateau polygon count improves (was -4).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# TODO.complete/55: Wire ShapeScript into StereotypeIconRenderer
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`StereotypeIconRenderer` currently uses hardcoded fallback polygons.
|
|
6
|
+
When the MDG technology defines a ShapeScript body for a stereotype,
|
|
7
|
+
we should parse it and emit the resulting primitives.
|
|
8
|
+
|
|
9
|
+
## Plan
|
|
10
|
+
|
|
11
|
+
1. Look up the stereotype's ShapeScript from the MDG registry.
|
|
12
|
+
2. If found: `Ea::Shapescript::Parser.parse(body)` →
|
|
13
|
+
`Ea::Shapescript::Renderer.render(shapes)`.
|
|
14
|
+
3. If not found: use existing hardcoded fallback.
|
|
15
|
+
4. Translate the SVG fragment to absolute element coordinates.
|
|
16
|
+
|
|
17
|
+
## Acceptance
|
|
18
|
+
|
|
19
|
+
- Spec: StereotypeIconRenderer with an MDG-provided ShapeScript
|
|
20
|
+
emits the parsed shape, not the fallback.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# TODO.complete/56: Wire EmfRenderer into SVG emitter
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Image::EmfRenderer` is defined but never called from the SVG
|
|
6
|
+
emitter. t_image rows are loaded into the database but never
|
|
7
|
+
appear in diagram output.
|
|
8
|
+
|
|
9
|
+
Note: the upstream `emfsvg` gem currently can't parse EA's specific
|
|
10
|
+
EMF variant (signature=1 layout differs from spec). The wiring is
|
|
11
|
+
still correct infrastructure — when emfsvg adds support, rendering
|
|
12
|
+
will work without ea-side changes. EmfRenderer already returns nil
|
|
13
|
+
gracefully when conversion fails.
|
|
14
|
+
|
|
15
|
+
## Plan
|
|
16
|
+
|
|
17
|
+
1. In the SVG emitter, walk `database.collections[:images]`.
|
|
18
|
+
2. For each image: `svg_fragment = Ea::Image::EmfRenderer.render(image.bytes)`
|
|
19
|
+
3. If non-nil: inline as `<g transform="translate(...)">...</g>` at
|
|
20
|
+
the diagram's image placement rect.
|
|
21
|
+
4. If nil: skip silently (current behavior).
|
|
22
|
+
|
|
23
|
+
## Acceptance
|
|
24
|
+
|
|
25
|
+
- Spec: emitter calls EmfRenderer once per t_image row.
|
|
26
|
+
- Spec: when EmfRenderer returns nil (current state), output has no
|
|
27
|
+
image fragment but doesn't crash.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# TODO.complete/57: Wire OCL evaluator into `ea validate`
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Ocl::Parser` + `Evaluator` exist with full specs but no
|
|
6
|
+
production caller. `ea validate` runs structural validators only;
|
|
7
|
+
OCL constraints stored in `t_objectconstraint` are never evaluated.
|
|
8
|
+
|
|
9
|
+
## Plan
|
|
10
|
+
|
|
11
|
+
1. Add `Ea::Qea::Validation::OclConstraintValidator` that walks
|
|
12
|
+
`database.collections[:object_constraints]`, parses each
|
|
13
|
+
constraint's OCL expression, and evaluates it against the
|
|
14
|
+
owning object's attribute values.
|
|
15
|
+
2. Register in `ValidationEngine`.
|
|
16
|
+
3. Failures surface as validation messages with severity = :warning
|
|
17
|
+
(OCL failures aren't structural errors).
|
|
18
|
+
|
|
19
|
+
## Acceptance
|
|
20
|
+
|
|
21
|
+
- Spec: a constraint like `inv: self.name.matches('[A-Z]+')`
|
|
22
|
+
applied to an object with `name = "foo"` produces a warning.
|
|
23
|
+
- Spec: evaluator returns true for a passing constraint.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# TODO.complete/58: Diff comparator detects attribute modifications
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
Current `Ea::Diff::Comparator` only detects added / removed /
|
|
6
|
+
renamed entities. It misses modifications — e.g. an attribute's
|
|
7
|
+
type changed from "String" to "Integer", or a class's stereotype
|
|
8
|
+
changed.
|
|
9
|
+
|
|
10
|
+
## Plan
|
|
11
|
+
|
|
12
|
+
1. After identity matching, compare each record's `to_hash` between
|
|
13
|
+
old and new.
|
|
14
|
+
2. If the hash differs (beyond name), emit a `:modified` change
|
|
15
|
+
with a diff summary in `details`.
|
|
16
|
+
3. Add `Change#modified?` predicate (already exists in the struct).
|
|
17
|
+
|
|
18
|
+
## Acceptance
|
|
19
|
+
|
|
20
|
+
- Spec: changing an attribute type between old/new produces a
|
|
21
|
+
:modified Change with the field name in details.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# TODO.complete/59: Delete toy Export::Xmi::Generator
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Export::Xmi::Generator` is a minimal hand-rolled writer that
|
|
6
|
+
duplicates `Ea::Transformers::QeaToXmi`. The latter is the proper
|
|
7
|
+
serializer (used by `ea convert`). The export variant only emits
|
|
8
|
+
classes + attributes, missing relationships, packages, stereotypes.
|
|
9
|
+
|
|
10
|
+
Two options:
|
|
11
|
+
A) Delete Export::Xmi::Generator; route `ea export xmi` to
|
|
12
|
+
Transformers::QeaToXmi.
|
|
13
|
+
B) Complete Export::Xmi::Generator to match Transformers.
|
|
14
|
+
|
|
15
|
+
Option A is correct — DRY. Eliminates ~100 lines of duplicate
|
|
16
|
+
logic that would otherwise drift.
|
|
17
|
+
|
|
18
|
+
## Plan
|
|
19
|
+
|
|
20
|
+
1. Change `lib/ea/cli/command/export.rb` xmi lambda to call
|
|
21
|
+
`Ea::Transformers.qea_to_xmi(model)`.
|
|
22
|
+
2. Delete `lib/ea/export/xmi.rb`, `lib/ea/export/xmi/generator.rb`.
|
|
23
|
+
3. Remove `autoload :Xmi` from `lib/ea/export.rb`.
|
|
24
|
+
4. Update round_trip_spec to use the transformer.
|
|
25
|
+
|
|
26
|
+
## Acceptance
|
|
27
|
+
|
|
28
|
+
- `ea export xmi examples/qea/basic.qea` produces full Sparx XMI
|
|
29
|
+
(not just classes).
|
|
30
|
+
- No `Ea::Export::Xmi` namespace remains.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# TODO.complete/60: Curate JSON export schema
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Export::Json::Generator` dumps `record.to_hash` raw, which
|
|
6
|
+
includes Lutaml::Model internals (e.g. `record_type` field is
|
|
7
|
+
added by us but other internals may leak).
|
|
8
|
+
|
|
9
|
+
## Plan
|
|
10
|
+
|
|
11
|
+
1. Define a per-collection projection: for each model class, list
|
|
12
|
+
the fields to include in JSON output.
|
|
13
|
+
2. Walk collections, project each record through the curated schema.
|
|
14
|
+
3. Output `{ "collections": { "objects": [...], "packages": [...], ... } }`
|
|
15
|
+
with a top-level structure (current output is flat).
|
|
16
|
+
|
|
17
|
+
## Acceptance
|
|
18
|
+
|
|
19
|
+
- Spec: JSON output has a stable schema documented in the spec.
|
|
20
|
+
- Spec: Lutaml::Model internals do not appear in output.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# TODO.complete/61: PlantUML export — relationships + packages
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
Current `Ea::Export::PlantUml::Generator` only emits classes +
|
|
6
|
+
their attributes. Doesn't emit:
|
|
7
|
+
- Package nesting (`package "X" { ... }`)
|
|
8
|
+
- Generalizations (`Parent <|-- Child`)
|
|
9
|
+
- Associations with multiplicity (`A "1" --> "0..*" B : name`)
|
|
10
|
+
|
|
11
|
+
## Plan
|
|
12
|
+
|
|
13
|
+
1. Wrap classes in their containing package blocks.
|
|
14
|
+
2. Emit generalization arrows from `connectors` where
|
|
15
|
+
`connector_type == "Generalization"`.
|
|
16
|
+
3. Emit associations with source/target multiplicities and role names.
|
|
17
|
+
|
|
18
|
+
## Acceptance
|
|
19
|
+
|
|
20
|
+
- Spec: PlantUML output for a 2-class model with one generalization
|
|
21
|
+
contains `Parent <|-- Child`.
|
|
22
|
+
- Spec: classes are nested in `package "X" { ... }` blocks.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# TODO.complete/62: Add CHANGELOG.md
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
No CHANGELOG exists. Releases happen but aren't documented.
|
|
6
|
+
|
|
7
|
+
## Plan
|
|
8
|
+
|
|
9
|
+
1. Create `CHANGELOG.md` following Keep-a-Changelog format.
|
|
10
|
+
2. Backfill 0.5.0 entry summarizing the headless-EA-replacement
|
|
11
|
+
release.
|
|
12
|
+
3. Backfill 0.4.0 from git log if straightforward.
|
|
13
|
+
|
|
14
|
+
## Acceptance
|
|
15
|
+
|
|
16
|
+
- File exists at repo root.
|
|
17
|
+
- 0.5.0 entry lists the major additions.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# TODO.complete/63: Address dependabot vulnerability
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`git push` reported: "GitHub found 1 vulnerability on lutaml/ea's
|
|
6
|
+
default branch (1 moderate)". Need to triage.
|
|
7
|
+
|
|
8
|
+
## Plan
|
|
9
|
+
|
|
10
|
+
1. Inspect the alert via `gh api repos/lutaml/ea/dependabot/alerts`.
|
|
11
|
+
2. If transitive (gem dependency): bump via Gemfile + bundle update.
|
|
12
|
+
3. If direct: upgrade affected gem.
|
|
13
|
+
4. Verify alert resolves.
|
|
14
|
+
|
|
15
|
+
## Acceptance
|
|
16
|
+
|
|
17
|
+
- Dependabot alert state is "dismissed" or "fixed".
|
|
18
|
+
- `git push` no longer reports vulnerability.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# TODO.complete/64: QeaToXmi emits connector elements
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Transformers::QeaToXmi` emits associations as `<memberEnd>` +
|
|
6
|
+
`<ownedEnd>` on the owning class, but does NOT emit EA's
|
|
7
|
+
`<connector>` elements. Per the parity regression spec, that's the
|
|
8
|
+
#1 missing category (73/73 in basic.qea, 73/80 in plateau).
|
|
9
|
+
|
|
10
|
+
## Plan
|
|
11
|
+
|
|
12
|
+
1. After serializing the model root + classes, walk `t_connector`
|
|
13
|
+
for associations/aggregations/compositions.
|
|
14
|
+
2. For each connector, locate the corresponding `t_diagramlinks` row
|
|
15
|
+
to retrieve geometry (SX/SY/EX/EY/EDGE) and visual style
|
|
16
|
+
(lineStyle/lineColor).
|
|
17
|
+
3. Emit `<connector>` element with geometry in `<style>` sub-element.
|
|
18
|
+
|
|
19
|
+
## Acceptance
|
|
20
|
+
|
|
21
|
+
- `ea export xmi` output for basic.qea now contains
|
|
22
|
+
`<connector>` elements (was 0/73).
|
|
23
|
+
- `spec/ea/validation/xmi_parity_spec.rb` packagedElement threshold
|
|
24
|
+
raised from 5% to 25% (connectors represent ~25% of EA's output).
|
|
25
|
+
|
|
26
|
+
## OCP
|
|
27
|
+
|
|
28
|
+
Each connector type (Association/Aggregation/Composition) gets a
|
|
29
|
+
private serializer method dispatched by `connector_type`. New
|
|
30
|
+
connector types = new case branch; no other code changes.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# TODO.complete/65: QeaToXmi emits diagram elements
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Transformers::QeaToXmi` does not emit EA's `<diagram>` elements
|
|
6
|
+
at all. The parity spec confirms 0/23 in basic.qea, 0/2 in test.qea.
|
|
7
|
+
|
|
8
|
+
## Plan
|
|
9
|
+
|
|
10
|
+
1. Walk `t_diagram` for every diagram.
|
|
11
|
+
2. For each diagram, walk `t_diagramlinks` to find placed
|
|
12
|
+
elements + connectors; emit them as `<element>` children of
|
|
13
|
+
`<diagram>`.
|
|
14
|
+
3. Each element child references its `xmi:idref` to the model
|
|
15
|
+
class.
|
|
16
|
+
4. Connector children emit as `<connector>` with geometry (see
|
|
17
|
+
TODO 64).
|
|
18
|
+
|
|
19
|
+
## Acceptance
|
|
20
|
+
|
|
21
|
+
- `ea export xmi` output for basic.qea now contains
|
|
22
|
+
`<diagram>` elements (was 0/23).
|
|
23
|
+
- Parity threshold raised from 25% to 50%.
|
|
24
|
+
|
|
25
|
+
## OCP
|
|
26
|
+
|
|
27
|
+
Diagrams emit via a new private method `emit_diagrams(model)`
|
|
28
|
+
called after the model class tree. Adding new diagram metadata
|
|
29
|
+
(swimlane info, etc.) = new private method, no other changes.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# TODO.complete/66: QeaToXmi emits style / tags / documentation
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
EA's reference XMI contains hundreds of `<style>`, `<tags>`, and
|
|
6
|
+
`<documentation>` elements per diagram. Ours emits zero. Per the
|
|
7
|
+
parity spec: 0/663 styles, 0/478 tags, 0/357 documentation entries.
|
|
8
|
+
|
|
9
|
+
## Plan
|
|
10
|
+
|
|
11
|
+
1. Walk `t_diagramlinks` to find connector+element style strings.
|
|
12
|
+
2. Emit `<style>` children of `<connector>` / `<element>` with the
|
|
13
|
+
stored style XML verbatim.
|
|
14
|
+
3. Walk `t_taggedvalue` for tagged values; emit as `<tags>` children
|
|
15
|
+
with `<tag>` items.
|
|
16
|
+
4. Walk `t_objectnotes` for documentation; emit as `<documentation>`
|
|
17
|
+
children of the owning element.
|
|
18
|
+
|
|
19
|
+
## Acceptance
|
|
20
|
+
|
|
21
|
+
- Output contains `<style>`, `<tags>`, `<documentation>` elements.
|
|
22
|
+
- Parity threshold raised from 50% to 75%.
|
|
23
|
+
|
|
24
|
+
## OCP
|
|
25
|
+
|
|
26
|
+
Each sub-element type (style/tags/documentation) is a private
|
|
27
|
+
emitter method dispatched by collection. New element types = new
|
|
28
|
+
case branch.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# TODO.complete/67: OCL collection operations
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Ocl` evaluates a subset of OCL: `exists`, `forAll`, `matches`,
|
|
6
|
+
`and`/`or`/`not`, attribute access. Real EA constraints use
|
|
7
|
+
`size()` and `isEmpty()` (parity: 0/0 because the OCL evaluator
|
|
8
|
+
wasn't even invoked before this session).
|
|
9
|
+
|
|
10
|
+
## Plan
|
|
11
|
+
|
|
12
|
+
1. Add `CollectionSize` AST node: `<collection>->size()`.
|
|
13
|
+
2. Add `CollectionIsEmpty` AST node: `<collection>->isEmpty()`.
|
|
14
|
+
3. Parser recognizes `->size` and `->isEmpty` patterns.
|
|
15
|
+
4. Evaluator returns integer / boolean.
|
|
16
|
+
|
|
17
|
+
## Acceptance
|
|
18
|
+
|
|
19
|
+
- Spec: `inv: self.items->size() > 0` parses + evaluates.
|
|
20
|
+
- Spec: `inv: self.items->isEmpty() or self.required` parses + evaluates.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# TODO.complete/68: OCL comparison operators
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
`Ea::Ocl` supports `=`/`==` via equality, but not ordering: `>`,
|
|
6
|
+
`<`, `>=`, `<=`. These appear in real OCL invariants.
|
|
7
|
+
|
|
8
|
+
## Plan
|
|
9
|
+
|
|
10
|
+
1. Add `Comparison` AST node: `left op right` where op is one of
|
|
11
|
+
`>`, `<`, `>=`, `<=`.
|
|
12
|
+
2. Parser recognizes the operators.
|
|
13
|
+
3. Evaluator compares numeric operands; raises `UnsupportedError` on
|
|
14
|
+
non-numeric.
|
|
15
|
+
|
|
16
|
+
## Acceptance
|
|
17
|
+
|
|
18
|
+
- Spec: `inv: self.age >= 18` parses + evaluates (true / false).
|
|
19
|
+
- Spec: `inv: self.count < self.max` parses + evaluates.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# TODO.complete/69: Specs for newly-added QEA models
|
|
2
|
+
|
|
3
|
+
## Status: open
|
|
4
|
+
|
|
5
|
+
The following models were added in TODO 44 / TODO 7 sessions but
|
|
6
|
+
have no spec coverage: `EaSecrypt`, `EaPalette`, `EaPaletteItem`,
|
|
7
|
+
`EaImplement`, `EaRoleConstraint`, `EaObjectProblem`, `EaObjectRisk`,
|
|
8
|
+
`EaObjectTest`, `EaObjectEffort`, `EaObjectResource`,
|
|
9
|
+
`EaObjectScenario`, `EaObjectRequire`, `EaObjectTrx`.
|
|
10
|
+
|
|
11
|
+
Without specs, regressions in column mapping or primary key logic
|
|
12
|
+
go undetected.
|
|
13
|
+
|
|
14
|
+
## Plan
|
|
15
|
+
|
|
16
|
+
1. Single consolidated spec file: `spec/ea/qea/models/
|
|
17
|
+
auxiliary_models_spec.rb`.
|
|
18
|
+
2. Per-model `it "loads primary key and columns"` block.
|
|
19
|
+
3. Verifies `primary_key_column` is correct.
|
|
20
|
+
4. Verifies `column_map` translates known column names to symbols.
|
|
21
|
+
|
|
22
|
+
## Acceptance
|
|
23
|
+
|
|
24
|
+
- File exists, all 13 models have at least 1 example.
|
|
25
|
+
- `bundle exec rspec` passes with 0 failures.
|