ea 0.5.1 → 0.6.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.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/TODO.complete/01-t-xref-parsing.md +1 -1
  3. data/TODO.complete/02-per-label-geometry.md +1 -1
  4. data/TODO.complete/03-object-properties-constraints.md +1 -1
  5. data/TODO.complete/04-operation-params.md +1 -1
  6. data/TODO.complete/05-pdata-flag-matrix.md +1 -1
  7. data/TODO.complete/06-emf-image-rendering.md +1 -1
  8. data/TODO.complete/07-auxiliary-tables.md +1 -1
  9. data/TODO.complete/10-mdg-stereotype-registry.md +1 -1
  10. data/TODO.complete/11-gml-xsd-generation.md +1 -1
  11. data/TODO.complete/13-shapescript-interpreter.md +12 -23
  12. data/TODO.complete/20-cli-diff.md +1 -1
  13. data/TODO.complete/21-cli-render.md +1 -1
  14. data/TODO.complete/22-cli-export.md +1 -1
  15. data/TODO.complete/23-cli-mdg.md +1 -1
  16. data/TODO.complete/30-headerlines-ocp-refactor.md +1 -1
  17. data/TODO.complete/32-spec-coverage.md +1 -1
  18. data/TODO.complete/33-blocked-parity-gaps.md +1 -1
  19. data/TODO.complete/36-stereotype-icon-wiring.md +1 -1
  20. data/TODO.complete/37-cli-lint.md +1 -1
  21. data/TODO.complete/38-cli-query.md +1 -1
  22. data/TODO.complete/39-cli-info.md +1 -1
  23. data/TODO.complete/40-ocl-evaluator.md +1 -1
  24. data/TODO.complete/41-round-trip-spec.md +1 -1
  25. data/TODO.complete/42-html-diff-report.md +1 -1
  26. data/TODO.complete/43-json-schema-export.md +1 -1
  27. data/TODO.complete/44-remaining-qea-tables.md +1 -1
  28. data/TODO.complete/45-shapescript-extensions.md +1 -1
  29. data/TODO.complete/46-xsd-consolidation.md +1 -1
  30. data/TODO.complete/47-headerlines-legacy-removal.md +1 -1
  31. data/TODO.complete/51-remove-respond-to.md +42 -15
  32. data/TODO.complete/52-xsd-decouple-fixtures.md +1 -1
  33. data/TODO.complete/54-wire-stereotype-icon-renderer.md +1 -1
  34. data/TODO.complete/55-wire-shapescript.md +1 -1
  35. data/TODO.complete/56-wire-emf-renderer.md +1 -1
  36. data/TODO.complete/57-wire-ocl-evaluator.md +1 -1
  37. data/TODO.complete/58-diff-modifications.md +1 -1
  38. data/TODO.complete/59-delete-toy-xmi-export.md +1 -1
  39. data/TODO.complete/60-curate-json-export.md +1 -1
  40. data/TODO.complete/61-plantuml-relationships.md +1 -1
  41. data/TODO.complete/62-changelog.md +1 -1
  42. data/TODO.complete/63-dependabot-fix.md +1 -1
  43. data/TODO.complete/64-qeatoxmi-connectors.md +15 -0
  44. data/TODO.complete/65-qeatoxmi-diagrams.md +15 -0
  45. data/TODO.complete/66-qeatoxmi-style-tags-docs.md +35 -0
  46. data/TODO.complete/67-ocl-collection-ops.md +20 -0
  47. data/TODO.complete/68-ocl-comparison-ops.md +24 -0
  48. data/TODO.complete/69-spec-new-models.md +20 -0
  49. data/TODO.complete/70-specs-for-all-models.md +21 -0
  50. data/TODO.complete/71-autoload-audit.md +26 -0
  51. data/TODO.complete/72-extension-serializer-ocp-naming.md +26 -0
  52. data/TODO.complete/73-ocl-validator-latent-bugs.md +50 -0
  53. data/TODO.complete/74-visibility-symbol-dry.md +39 -0
  54. data/TODO.complete/75-database-table-collection-registry.md +32 -0
  55. data/TODO.complete/76-stale-todo-cleanup.md +52 -0
  56. data/TODO.complete/77-eliminate-banned-patterns-from-specs.md +55 -0
  57. data/TODO.complete/78-mdg-stereotype-emission.md +66 -0
  58. data/TODO.complete/79-equivalence-fixes.md +57 -0
  59. data/TODO.complete/80-performance-extension-serializer-indexes.md +43 -0
  60. data/TODO.complete/81-dry-scope-guid-extraction.md +33 -0
  61. data/TODO.complete/82-public-send-audit-conclusion.md +25 -0
  62. data/TODO.complete/83-dry-shared-xml-escape-guid-format.md +52 -0
  63. data/TODO.complete/84-ocp-markers-shape-registry.md +54 -0
  64. data/TODO.complete/85-frozen-literal-rubocop-normalize-type-spec.md +38 -0
  65. data/TODO.complete/86-frozen-sweep-lint-query-specs.md +55 -0
  66. data/TODO.complete/STATUS.md +26 -5
  67. data/lib/ea/cli/app.rb +1 -0
  68. data/lib/ea/cli/command/convert.rb +1 -1
  69. data/lib/ea/cli/command/export.rb +10 -1
  70. data/lib/ea/cli/command/mdg.rb +1 -10
  71. data/lib/ea/cli/command/render.rb +2 -1
  72. data/lib/ea/diff/html_reporter.rb +1 -5
  73. data/lib/ea/export/json/generator.rb +5 -6
  74. data/lib/ea/export/plantuml/generator.rb +5 -3
  75. data/lib/ea/guid_format.rb +91 -0
  76. data/lib/ea/mdg/document.rb +2 -1
  77. data/lib/ea/mdg/loader.rb +2 -1
  78. data/lib/ea/mdg/registry.rb +57 -2
  79. data/lib/ea/mdg/xml/applies_to.rb +1 -1
  80. data/lib/ea/mdg/xml/apply.rb +1 -1
  81. data/lib/ea/mdg/xml/content.rb +1 -1
  82. data/lib/ea/mdg/xml/documentation.rb +1 -1
  83. data/lib/ea/mdg/xml/stereotype.rb +1 -1
  84. data/lib/ea/mdg/xml/stereotypes.rb +1 -1
  85. data/lib/ea/mdg/xml/tag.rb +1 -1
  86. data/lib/ea/mdg/xml/tagged_values.rb +1 -1
  87. data/lib/ea/mdg/xml/technology.rb +1 -1
  88. data/lib/ea/mdg/xml/uml_profile.rb +1 -1
  89. data/lib/ea/mdg/xml/uml_profiles.rb +1 -1
  90. data/lib/ea/mdg/xml.rb +2 -1
  91. data/lib/ea/mdg.rb +2 -1
  92. data/lib/ea/model/ghost_label.rb +2 -1
  93. data/lib/ea/ocl/evaluator.rb +39 -0
  94. data/lib/ea/ocl/nodes.rb +9 -0
  95. data/lib/ea/ocl/parser.rb +60 -6
  96. data/lib/ea/qea/database.rb +57 -2
  97. data/lib/ea/qea/factory/reference_resolver.rb +1 -1
  98. data/lib/ea/qea/models/ea_attribute.rb +1 -17
  99. data/lib/ea/qea/models/ea_connector.rb +3 -2
  100. data/lib/ea/qea/models/ea_object.rb +14 -9
  101. data/lib/ea/qea/models/ea_operation.rb +1 -17
  102. data/lib/ea/qea/models/ea_xref.rb +3 -0
  103. data/lib/ea/qea/models/scope_predicate.rb +29 -0
  104. data/lib/ea/qea/models.rb +1 -0
  105. data/lib/ea/qea/repositories/base_repository.rb +4 -1
  106. data/lib/ea/qea/validation/base_validator.rb +3 -48
  107. data/lib/ea/qea/validation/database/ocl_constraint_validator.rb +23 -13
  108. data/lib/ea/shapescript/renderer.rb +1 -3
  109. data/lib/ea/sources/qea/diagram_builder.rb +1 -0
  110. data/lib/ea/sources/qea/id_normalizer.rb +2 -2
  111. data/lib/ea/svg/ea_emitter/background.rb +2 -1
  112. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +1 -6
  113. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +2 -7
  114. data/lib/ea/svg/ea_emitter/elements.rb +1 -3
  115. data/lib/ea/svg/ea_emitter/ghost_labels.rb +2 -1
  116. data/lib/ea/svg/ea_emitter/label/end_label.rb +1 -6
  117. data/lib/ea/svg/ea_emitter/marker/package_import.rb +1 -1
  118. data/lib/ea/svg/ea_emitter/markers.rb +52 -23
  119. data/lib/ea/svg/ea_emitter/text_renderer.rb +1 -4
  120. data/lib/ea/svg/ea_emitter/visibility_symbol.rb +37 -0
  121. data/lib/ea/svg/ea_emitter.rb +1 -0
  122. data/lib/ea/svg/parity/source.rb +0 -2
  123. data/lib/ea/svg/parity/suite.rb +0 -1
  124. data/lib/ea/transformers/qea_to_xmi/cardinality.rb +40 -28
  125. data/lib/ea/transformers/qea_to_xmi/context.rb +35 -1
  126. data/lib/ea/transformers/qea_to_xmi/extension_serializer.rb +686 -0
  127. data/lib/ea/transformers/qea_to_xmi/guid_format.rb +5 -48
  128. data/lib/ea/transformers/qea_to_xmi/id_allocator.rb +55 -54
  129. data/lib/ea/transformers/qea_to_xmi/primitive_types.rb +105 -0
  130. data/lib/ea/transformers/qea_to_xmi/profile_serializer.rb +163 -0
  131. data/lib/ea/transformers/qea_to_xmi/run_state.rb +7 -6
  132. data/lib/ea/transformers/qea_to_xmi/transformer.rb +423 -76
  133. data/lib/ea/transformers/qea_to_xmi/visibility.rb +30 -19
  134. data/lib/ea/transformers/qea_to_xmi.rb +5 -2
  135. data/lib/ea/transformers.rb +8 -2
  136. data/lib/ea/validation.rb +1 -1
  137. data/lib/ea/version.rb +1 -1
  138. data/lib/ea/xmi/liquid_drops/attribute_drop.rb +12 -4
  139. data/lib/ea/xmi/liquid_drops/klass_drop.rb +1 -2
  140. data/lib/ea/xmi/lookup_service.rb +4 -0
  141. data/lib/ea/xmi/parser.rb +30 -1
  142. data/lib/ea/xml_escape.rb +21 -0
  143. data/lib/ea.rb +2 -0
  144. metadata +34 -11
  145. data/lutaml-uml-0.5.1.gem +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8649c4d58ca59e1a753bf7b4c1400e14ac7026e1142e914a4025dfd09a2e5bb1
4
- data.tar.gz: 170d39d2601ea16f0dd171c7ab51906b4bbe0baf5c973eaffdfc02df2e27ab59
3
+ metadata.gz: 8176d9a9c6b3d499aeab9f51409190c951b062a890ce66a5e39ce2e4f9fbd056
4
+ data.tar.gz: 0d92ca54dff55c01469465c6ff276a0e9d9ae1ad58325aed7ab5ca96443ed00a
5
5
  SHA512:
6
- metadata.gz: f7bd4ceb020497b93a2c9c9e0c60d3aa57a0cbb664803f4609a7ec82b2129649496bca45000b2ec91ba1c07a9254b1382bce67411f9f35b5d41dcaebe22590ff
7
- data.tar.gz: ed3b011237a1a76a85ac1af8315afcfd9250b97396fbbcefe15f0491adbe1a51a1944abd7ba9ec513b0011c2461c4ff3c7bb5be20dfa58156cc93e3698c39d44
6
+ metadata.gz: 33649bc4e8f12a30a1838c80e2359f5dfaa03f9ffeb63ed0655a989559d2cbb0ec314fd673f0802baff90d0d53f75902b2aa3814942bf4a735f853367f31faa7
7
+ data.tar.gz: b2761649c59502772d5406573d6bc02e88dcc3cabe42be17cf34733a553661fc83b94cab4581c11fd80001e71c332812a77307bdb956c9b6ce1e3495c2e9d71b
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/01: Full t_xref parser
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  EA's `t_xref` table stores semi-structured metadata in a custom mini-language.
6
6
  We currently only consume the stereotype-application rows for classifier
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/02: Per-label Geometry box parsing
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  EA's `t_diagramlinks.Geometry` field encodes per-label styling boxes:
6
6
 
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/03: t_objectproperties + t_objectconstraint parsing
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Two EA tables we currently ignore. Both carry modeling metadata that maps
6
6
  to UML2 concepts:
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/04: t_operationparams parsing
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `t_operationparams` stores the parameters of an operation (method).
6
6
  We parse `t_operation` but lose the parameter list.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/05: Complete PDATA/StyleEx flag matrix
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  EA's `t_diagram.PDATA` carries ~30 rendering flags as `Key=value;` pairs.
6
6
  We currently parse only ~4 (`HideAtts`, `HideOps`, `HideParents`, `HideProps`).
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/06: EMF→SVG conversion for t_image
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  EA's `t_image` table stores image blobs as Enhanced Metafile (EMF).
6
6
  We currently skip them entirely.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/07: Auxiliary QEA tables
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  EA has ~96 tables. We currently parse 24. Beyond the structural core
6
6
  (objects, connectors, diagrams, packages, operations, attributes, xref),
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/10: MDG stereotype registry
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  We have 49 EA-bundled MDG/GML definition files in `spec/fixtures/mdg/`:
6
6
 
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/11: GML XSD schema generation
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  The `GMLClassMapping.xml` file defines how UML classes map to GML XML
6
6
  Schema constructs:
@@ -1,28 +1,17 @@
1
1
  # TODO.complete/13: Basic ShapeScript interpreter
2
2
 
3
- ## Status: deferred
3
+ ## Status: done
4
4
 
5
- EA's MDG technologies can define stereotype icons via ShapeScript — a
6
- domain-specific language for vector shapes (lines, polygons, ellipses).
5
+ ShapeScript parser + renderer implemented with vars, arithmetic,
6
+ conditionals, subshapes, and labels. Wired into
7
+ StereotypeIconRenderer for stereotype decorator icons.
7
8
 
8
- This is what closes the **polygon -4 parity gap** (TODO.diagrams/73): the
9
- small stereotype decorator icons EA renders inside element bodies.
9
+ ## Implementation
10
10
 
11
- ## Why deferred
12
-
13
- - Full ShapeScript interpreter is high effort (~1-2 weeks).
14
- - The gap is small (4 polygons across 188 diagrams).
15
- - EA's InternalTechnologies encryption blocks the easy path to reference
16
- shape definitions (see TODO.diagrams/87).
17
-
18
- ## When to revisit
19
-
20
- - Encryption is broken and we have plaintext shape definitions.
21
- - A user specifically requests stereotype decorator icon rendering.
22
- - A larger gap emerges that ShapeScript would close.
23
-
24
- ## Partial path (lower effort)
25
-
26
- If we acquire plaintext shape definitions for a few high-value stereotypes
27
- (FeatureType, Type), we can hardcode their polygons without a full
28
- ShapeScript interpreter. This is a tactical compromise.
11
+ - `lib/ea/shapescript/parser.rb` — tokenizes and parses ShapeScript
12
+ source into `Shape` value objects.
13
+ - `lib/ea/shapescript/shape.rb` `Shape` model (rect, polygon,
14
+ ellipse, line, text).
15
+ - `lib/ea/shapescript/renderer.rb` walks a parsed `Shape` tree and
16
+ emits SVG elements.
17
+ - 21 specs in `spec/ea/shapescript/shapescript_spec.rb` (0 failures).
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/20: `ea diff` CLI command
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Structural diff between two QEA files (or QEA vs XMI). Useful for:
6
6
 
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/21: `ea render` unified rendering command
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Consolidate the existing `svg` command into a more general `render`
6
6
  command that supports multiple output formats.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/22: `ea export` command
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Single command for all model exports.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/23: `ea mdg` command
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Expose the MDG technology registry via CLI.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/30: HeaderLines OCP refactor (provider chain)
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Svg::EaEmitter::Element::HeaderLines` is a monolithic module with
6
6
  conditional logic for stereotype fallback, qualified name wrap, abstract
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/32: Specs for new code paths
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  New code added in Streams A/B/C must have specs. This file is the
6
6
  tracking list — each completed TODO contributes specs.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/33: Blocked parity gaps (deferral log)
2
2
 
3
- ## Status: open (informational)
3
+ ## Status: done
4
4
 
5
5
  Parity work that is currently blocked beyond reasonable effort. Documented
6
6
  so future contributors don't re-investigate the same dead ends.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/36: Stereotype icon wiring (closes polygon -4 parity gap)
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  The `Ea::Shapescript::Parser` and `Renderer` exist but aren't wired
6
6
  into the SVG emitter. As a result, stereotype decorator icons
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/37: `ea lint` command
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Model quality checks beyond structural validation:
6
6
  - Naming convention violations (CamelCase classes, camelCase attrs)
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/38: `ea query` command
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Filter/search DSL for ad-hoc exploration. Currently you can list
6
6
  everything but can't say "find all classes named X" or "classes
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/39: `ea info` command
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Show details of a single element by name or GUID. Useful for
6
6
  debugging and exploration without firing up a GUI.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/40: OCL constraint evaluator
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Qea::Models::EaObjectConstraint` carries OCL expressions like
6
6
  `inv: self.string->exists(o | o.matches('[a-zA-Z0-9]+'))`. We parse
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/41: Round-trip stability spec
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  The contract `parse → serialize → parse` should produce identical
6
6
  models. Currently there's no spec that verifies this end-to-end.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/42: HTML diff report
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Text diff is hard to scan in PR descriptions. HTML report with
6
6
  color-coded added/removed/renamed rows is much more reviewable.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/43: JSON Schema export
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  XSD is one XML schema format. JSON Schema is the JSON equivalent
6
6
  and equally useful for downstream tooling (API validation, form
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/44: Remaining QEA tables
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Still uncovered tables with real value:
6
6
 
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/45: ShapeScript extensions
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Current interpreter handles only primitives. Real EA ShapeScript
6
6
  files use variables, conditionals, and subshapes.
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/46: XSD Generator consolidation
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Export::Xsd::CliBridge` is glue that loads fixtures then
6
6
  delegates to `Generator`. The bridge exists only because the CLI
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/47: HeaderLines legacy module removal
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Svg::EaEmitter::Element::HeaderLines` still exists alongside
6
6
  the new `HeaderLinePipeline`. After verifying the pipeline covers
@@ -1,25 +1,52 @@
1
1
  # TODO.complete/51: Remove `respond_to?` from lib code
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
- The user's rule: "never use respond_to (poor typing)". Five call
6
- sites violate it, all added in recent sessions:
5
+ The user's rule: "never use respond_to (poor typing)". All 6 call
6
+ sites in lib/ have been replaced with `is_a?` type checks or direct
7
+ method calls (typed dispatch).
7
8
 
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
9
+ ## Sites fixed
12
10
 
13
- ## Plan
11
+ 1. `lib/ea/qea/validation/database/ocl_constraint_validator.rb:54` —
12
+ `constraint.respond_to?(:ea_object_id)` → direct call (constraint
13
+ is always `EaObjectConstraint`, which has `ea_object_id`). Also
14
+ fixed latent bug: `o.object_id` (Ruby's `Object#object_id`) →
15
+ `o.ea_object_id`; the old code never matched any owner, silently
16
+ skipping all OCL validation.
14
17
 
15
- Replace `respond_to?(:x)` with explicit type checks via `is_a?`:
18
+ 2. `lib/ea/export/json/generator.rb:64`
19
+ `record.class.respond_to?(:primary_key_column)` →
20
+ `record.is_a?(Ea::Qea::Models::BaseModel)` (BaseModel defines
21
+ `primary_key_column` as a class method).
16
22
 
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).
23
+ 3. `lib/ea/export/json/generator.rb:72`
24
+ `record.respond_to?(:name)` `record.to_hash["name"]` (safe hash
25
+ access, returns nil when absent).
26
+
27
+ 4. `lib/ea/ocl/evaluator.rb:66` —
28
+ `collection.respond_to?(:size)` → `collection.is_a?(Array)`.
29
+
30
+ 5. `lib/ea/ocl/evaluator.rb:73` —
31
+ `collection.respond_to?(:empty?)` → `collection.is_a?(Array)`.
32
+
33
+ 6. `lib/ea/export/plantuml/generator.rb:130` —
34
+ `l.respond_to?(:ea_object_id)` →
35
+ `l.is_a?(Ea::Qea::Models::EaAttribute)`.
36
+
37
+ ## Follow-on fixes
38
+
39
+ Fixing site #1 exposed two latent bugs in the OCL constraint
40
+ validator that had been masked by the `owner_for` always returning nil:
41
+
42
+ - `result.add(:info, ...)` was calling a non-existent API — replaced
43
+ with `result.add_info(category:..., message:..., **opts)`.
44
+ - The OCL evaluator's `attribute_value` raised `NoMethodError` on
45
+ unknown attributes — now rescues and returns nil (OCL semantics:
46
+ missing attribute = null).
21
47
 
22
48
  ## Acceptance
23
49
 
24
- - `grep -rn "respond_to?" lib/ea/` returns 0 hits.
25
- - Existing specs still pass.
50
+ - `grep -rn "respond_to?" lib/` returns zero results.
51
+ - All validation + OCL specs pass (including the previously-skipped
52
+ OCL validation specs that now run to completion).
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/52: Decouple XSD Generator from fixture paths
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Export::Xsd::Generator` hardcodes:
6
6
  DEFAULT_MAPPING_PATH = "spec/fixtures/mdg/ea_config/gml/GMLClassMapping.xml"
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/54: Wire StereotypeIconRenderer into SVG emitter
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Svg::EaEmitter::Element::StereotypeIconRenderer` is defined
6
6
  and autoloaded but never invoked. The polygon -4 parity gap on
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/55: Wire ShapeScript into StereotypeIconRenderer
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `StereotypeIconRenderer` currently uses hardcoded fallback polygons.
6
6
  When the MDG technology defines a ShapeScript body for a stereotype,
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/56: Wire EmfRenderer into SVG emitter
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Image::EmfRenderer` is defined but never called from the SVG
6
6
  emitter. t_image rows are loaded into the database but never
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/57: Wire OCL evaluator into `ea validate`
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Ocl::Parser` + `Evaluator` exist with full specs but no
6
6
  production caller. `ea validate` runs structural validators only;
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/58: Diff comparator detects attribute modifications
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Current `Ea::Diff::Comparator` only detects added / removed /
6
6
  renamed entities. It misses modifications — e.g. an attribute's
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/59: Delete toy Export::Xmi::Generator
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Export::Xmi::Generator` is a minimal hand-rolled writer that
6
6
  duplicates `Ea::Transformers::QeaToXmi`. The latter is the proper
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/60: Curate JSON export schema
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `Ea::Export::Json::Generator` dumps `record.to_hash` raw, which
6
6
  includes Lutaml::Model internals (e.g. `record_type` field is
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/61: PlantUML export — relationships + packages
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  Current `Ea::Export::PlantUml::Generator` only emits classes +
6
6
  their attributes. Doesn't emit:
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/62: Add CHANGELOG.md
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  No CHANGELOG exists. Releases happen but aren't documented.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # TODO.complete/63: Address dependabot vulnerability
2
2
 
3
- ## Status: open
3
+ ## Status: done
4
4
 
5
5
  `git push` reported: "GitHub found 1 vulnerability on lutaml/ea's
6
6
  default branch (1 moderate)". Need to triage.
@@ -0,0 +1,15 @@
1
+ # TODO.complete/64: QeaToXmi emits connector elements
2
+
3
+ ## Status: done (via TODO 66 — ExtensionSerializer)
4
+
5
+ `Ea::Transformers::QeaToXmi` now emits `<connector>` elements as part
6
+ of the `<connectors>` extension section. Each connector has full
7
+ source/target/end blocks with `<style>`, `<documentation/>`, `<tags/>`
8
+ each, plus connector-level body (properties, appearance, style).
9
+
10
+ Parity: 72/72 connectors matched for basic.qea.
11
+
12
+ ## Implementation
13
+
14
+ Extracted to `Ea::Transformers::QeaToXmi::ExtensionSerializer` (OCP).
15
+ See [[66-qeatoxmi-style-tags-docs]] for the full restructuring.
@@ -0,0 +1,15 @@
1
+ # TODO.complete/65: QeaToXmi emits diagram elements
2
+
3
+ ## Status: done (via TODO 66 — ExtensionSerializer)
4
+
5
+ `Ea::Transformers::QeaToXmi` now emits `<diagram>` elements as part
6
+ of the `<diagrams>` extension section. Each diagram has a `<model>`
7
+ block, `<properties>` block, and `<elements>` containing placed
8
+ `<element subject="EAID_..." geometry="..."/>` children.
9
+
10
+ Parity: 22/22 diagrams matched for basic.qea.
11
+
12
+ ## Implementation
13
+
14
+ Extracted to `Ea::Transformers::QeaToXmi::ExtensionSerializer` (OCP).
15
+ See [[66-qeatoxmi-style-tags-docs]] for the full restructuring.
@@ -0,0 +1,35 @@
1
+ # TODO.complete/66: QeaToXmi emits style / tags / documentation
2
+
3
+ ## Status: done
4
+
5
+ EA's reference XMI contains hundreds of `<style>`, `<tags>`, and
6
+ `<documentation>` elements per diagram. Previously ours emitted zero.
7
+
8
+ ## Outcome
9
+
10
+ Extracted extension serialization into `ExtensionSerializer` (OCP:
11
+ new element types = new method, no existing code change). Emits the
12
+ proper Sparx XMI structure:
13
+
14
+ - `<elements>` — one `<element>` per package/classifier, each with
15
+ `<model>`, `<properties documentation="...">`, `<style>`, `<tags>`,
16
+ and (for classifiers) `<attributes>` and `<operations>` sub-blocks.
17
+ - `<connectors>` — full source/target/end blocks with `<style>`,
18
+ `<documentation/>`, `<tags/>` each, plus connector-level body.
19
+ - `<diagrams>` — placed `<element>` children with geometry.
20
+
21
+ Parity counts (basic.qea):
22
+
23
+ | type | before | after | ref |
24
+ |--------------|--------|-------|-----|
25
+ | style | 0 | 508 | 478 |
26
+ | tags | 0 | 508 | 478 |
27
+ | documentation| 0 | 345 | 357 |
28
+
29
+ ## Notes
30
+
31
+ - Removed banned `respond_to?` patterns from the old code.
32
+ - The old top-level `<tags>` and `<documentation>` sections were
33
+ structurally wrong — Sparx nests these inside per-element blocks.
34
+ - `serialize(with_extensions: false)` (used by `ea convert`) skips
35
+ this entirely for round-trip safety.
@@ -0,0 +1,20 @@
1
+ # TODO.complete/67: OCL collection operations
2
+
3
+ ## Status: done
4
+
5
+ `Ea::Ocl` evaluates `->size()` and `->isEmpty()` collection
6
+ operations. Specified in `spec/ea/ocl/ocl_spec.rb` (4 examples).
7
+
8
+ ## Implementation
9
+
10
+ - `Nodes::CollectionSize` — `<collection>->size()` AST node.
11
+ - `Nodes::CollectionIsEmpty` — `<collection>->isEmpty()` AST node.
12
+ - `Parser` recognizes `->size` and `->isEmpty` patterns via regex.
13
+ - `Evaluator#eval_size` returns integer; `#eval_is_empty` returns
14
+ boolean. Both check `is_a?(Array)` (not `respond_to?`) per the
15
+ typing rules.
16
+
17
+ ## Acceptance
18
+
19
+ - `inv: self.items->size() > 0` parses + evaluates.
20
+ - `inv: self.items->isEmpty() or self.required` parses + evaluates.
@@ -0,0 +1,24 @@
1
+ # TODO.complete/68: OCL comparison operators
2
+
3
+ ## Status: done
4
+
5
+ `Ea::Ocl` evaluates all comparison operators: `>`, `<`, `>=`, `<=`,
6
+ `=`, `==`, `!=`. Non-numeric operands raise `UnsupportedError`.
7
+
8
+ ## Implementation
9
+
10
+ - `Nodes::Comparison` — `left op right` AST node.
11
+ - `Parser#split_on_comparison_op` handles all 7 operators with
12
+ correct precedence (multi-char ops like `>=` checked before `>`).
13
+ - `Evaluator#eval_comparison` dispatches on `ast.op`, enforces
14
+ `Numeric` operands.
15
+
16
+ ## Acceptance
17
+
18
+ - `inv: self.age >= 18` parses + evaluates.
19
+ - `inv: self.count < self.max` parses + evaluates.
20
+ - `inv: self.x = self.y` evaluates as equality.
21
+ - `inv: self.x != self.y` evaluates as inequality.
22
+ - Non-numeric comparison raises `UnsupportedError`.
23
+
24
+ All specified in `spec/ea/ocl/ocl_spec.rb` (3 examples, 6 assertions).
@@ -0,0 +1,20 @@
1
+ # TODO.complete/69: Specs for newly-added QEA models
2
+
3
+ ## Status: done
4
+
5
+ All 13 models listed below have primary_key, table_name, column_map,
6
+ and from_db_row coverage in
7
+ `spec/ea/qea/models/auxiliary_models_spec.rb` (66 examples, 0
8
+ failures).
9
+
10
+ ## Models covered
11
+
12
+ `EaSecrypt`, `EaPalette`, `EaPaletteItem`, `EaImplement`,
13
+ `EaRoleConstraint`, `EaObjectProblem`, `EaObjectRisk`, `EaObjectTest`,
14
+ `EaObjectEffort`, `EaObjectResource`, `EaObjectScenario`,
15
+ `EaObjectRequire`, `EaObjectTrx`.
16
+
17
+ ## Follow-up
18
+
19
+ See [[70-specs-for-all-models]] for expanding spec coverage to the
20
+ remaining 18 models that currently rely on integration tests only.
@@ -0,0 +1,21 @@
1
+ # TODO.complete/70: Specs for all remaining QEA models
2
+
3
+ ## Status: done
4
+
5
+ Added consolidated spec coverage for the 18 remaining QEA models
6
+ that had no dedicated specs. Each model gets `table_name`,
7
+ `primary_key_column`, and `from_db_row` coverage.
8
+
9
+ ## Models covered
10
+
11
+ `EaAttributeTag`, `EaAuthor`, `EaComplexityType`, `EaConnectorType`,
12
+ `EaConstraintType`, `EaDatatype`, `EaDiagramLink`,
13
+ `EaDiagramObject`, `EaDiagramType`, `EaGlossary`, `EaImage`,
14
+ `EaList`, `EaObjectProperty`, `EaObjectType`, `EaPhase`,
15
+ `EaStatusType`, `EaStereotype`, `EaTaggedValue`, `EaVersion`.
16
+
17
+ ## Implementation
18
+
19
+ Spec file: `spec/ea/qea/models/all_models_spec.rb`. Uses the same
20
+ consolidated pattern as `auxiliary_models_spec.rb` — one shared
21
+ example per model, parameterized by expected table/pk.