ea 0.4.0 → 0.5.1

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 (548) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -1
  3. data/Rakefile +3 -0
  4. data/TODO.complete/01-t-xref-parsing.md +91 -0
  5. data/TODO.complete/02-per-label-geometry.md +50 -0
  6. data/TODO.complete/03-object-properties-constraints.md +57 -0
  7. data/TODO.complete/04-operation-params.md +37 -0
  8. data/TODO.complete/05-pdata-flag-matrix.md +52 -0
  9. data/TODO.complete/06-emf-image-rendering.md +34 -0
  10. data/TODO.complete/07-auxiliary-tables.md +47 -0
  11. data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
  12. data/TODO.complete/11-gml-xsd-generation.md +42 -0
  13. data/TODO.complete/13-shapescript-interpreter.md +28 -0
  14. data/TODO.complete/20-cli-diff.md +46 -0
  15. data/TODO.complete/21-cli-render.md +26 -0
  16. data/TODO.complete/22-cli-export.md +29 -0
  17. data/TODO.complete/23-cli-mdg.md +23 -0
  18. data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
  19. data/TODO.complete/31-public-send-cleanup.md +61 -0
  20. data/TODO.complete/32-spec-coverage.md +33 -0
  21. data/TODO.complete/33-blocked-parity-gaps.md +41 -0
  22. data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
  23. data/TODO.complete/37-cli-lint.md +32 -0
  24. data/TODO.complete/38-cli-query.md +26 -0
  25. data/TODO.complete/39-cli-info.md +23 -0
  26. data/TODO.complete/40-ocl-evaluator.md +31 -0
  27. data/TODO.complete/41-round-trip-spec.md +18 -0
  28. data/TODO.complete/42-html-diff-report.md +18 -0
  29. data/TODO.complete/43-json-schema-export.md +20 -0
  30. data/TODO.complete/44-remaining-qea-tables.md +40 -0
  31. data/TODO.complete/45-shapescript-extensions.md +25 -0
  32. data/TODO.complete/46-xsd-consolidation.md +20 -0
  33. data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
  34. data/TODO.complete/51-remove-respond-to.md +25 -0
  35. data/TODO.complete/52-xsd-decouple-fixtures.md +23 -0
  36. data/TODO.complete/53-xmi-public-send-cleanup.md +26 -0
  37. data/TODO.complete/54-wire-stereotype-icon-renderer.md +20 -0
  38. data/TODO.complete/55-wire-shapescript.md +20 -0
  39. data/TODO.complete/56-wire-emf-renderer.md +27 -0
  40. data/TODO.complete/57-wire-ocl-evaluator.md +23 -0
  41. data/TODO.complete/58-diff-modifications.md +21 -0
  42. data/TODO.complete/59-delete-toy-xmi-export.md +30 -0
  43. data/TODO.complete/60-curate-json-export.md +20 -0
  44. data/TODO.complete/61-plantuml-relationships.md +22 -0
  45. data/TODO.complete/62-changelog.md +17 -0
  46. data/TODO.complete/63-dependabot-fix.md +18 -0
  47. data/TODO.complete/STATUS.md +85 -0
  48. data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
  49. data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
  50. data/TODO.diagrams/03-text-over-rendering.md +30 -0
  51. data/TODO.diagrams/04-rect-under-rendering.md +33 -0
  52. data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
  53. data/TODO.diagrams/06-group-layering-parity.md +39 -0
  54. data/TODO.diagrams/07-text-content-fidelity.md +65 -0
  55. data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
  56. data/TODO.diagrams/12-connector-labels.md +40 -0
  57. data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
  58. data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
  59. data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
  60. data/TODO.diagrams/14-center-header-text.md +33 -0
  61. data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
  62. data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
  63. data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
  64. data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
  65. data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
  66. data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
  67. data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
  68. data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
  69. data/TODO.diagrams/18-property-lookup-index.md +42 -0
  70. data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
  71. data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
  72. data/TODO.diagrams/20-split-labels-emitter.md +56 -0
  73. data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
  74. data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
  75. data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
  76. data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
  77. data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
  78. data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
  79. data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
  80. data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
  81. data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
  82. data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
  83. data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
  84. data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
  85. data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
  86. data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
  87. data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
  88. data/TODO.diagrams/36-instance-specification-model.md +42 -0
  89. data/TODO.diagrams/37-element-icon-decorations.md +41 -0
  90. data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
  91. data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
  92. data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
  93. data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
  94. data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
  95. data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
  96. data/TODO.diagrams/44-element-icon-decorations.md +34 -0
  97. data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
  98. data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
  99. data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
  100. data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
  101. data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
  102. data/TODO.diagrams/50-examples-parity.md +85 -0
  103. data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
  104. data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
  105. data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
  106. data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
  107. data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
  108. data/TODO.diagrams/56-package-contents-rendering.md +148 -0
  109. data/TODO.diagrams/57-instance-specification-model.md +100 -0
  110. data/TODO.diagrams/58-domain-model-note-text.md +67 -0
  111. data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
  112. data/TODO.diagrams/60-testschema-association-marker.md +40 -0
  113. data/TODO.diagrams/61-legend-block-rendering.md +55 -0
  114. data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
  115. data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
  116. data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
  117. data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
  118. data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
  119. data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
  120. data/TODO.diagrams/68-inherited-attributes.md +65 -0
  121. data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
  122. data/TODO.diagrams/70-mdg-technology-support.md +68 -0
  123. data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
  124. data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
  125. data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
  126. data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
  127. data/TODO.diagrams/75-plateau-text-gap.md +39 -0
  128. data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
  129. data/TODO.diagrams/77-basic-text-overrender.md +40 -0
  130. data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
  131. data/TODO.diagrams/79-architecture-backlog.md +65 -0
  132. data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
  133. data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
  134. data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
  135. data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
  136. data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
  137. data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
  138. data/TODO.diagrams/86-foreign-package-rule.md +62 -0
  139. data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
  140. data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
  141. data/TODO.diagrams/README.md +69 -0
  142. data/TODO.diagrams/STATUS.md +73 -0
  143. data/TODO.fixup/01-default-grouped-paths.md +34 -0
  144. data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
  145. data/TODO.fixup/03-diagram-font-inference.md +28 -0
  146. data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
  147. data/TODO.fixup/05-marker-registry-ocp.md +32 -0
  148. data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
  149. data/TODO.fixup/07-edge-attachment-formula.md +22 -0
  150. data/TODO.fixup/08-visual-diff-harness.md +28 -0
  151. data/TODO.fixup/09-extract-element-compartments.md +34 -0
  152. data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
  153. data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
  154. data/TODO.fixup/12-path-style-harmony.md +23 -0
  155. data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
  156. data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
  157. data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
  158. data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
  159. data/TODO.fixup/17-path-count-calibration.md +27 -0
  160. data/TODO.fixup/18-polygon-count-calibration.md +32 -0
  161. data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
  162. data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
  163. data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
  164. data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
  165. data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
  166. data/TODO.fixup/24-note-element-rendering.md +23 -0
  167. data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
  168. data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
  169. data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
  170. data/TODO.fixup/28-geometry-parser-identification.md +57 -0
  171. data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
  172. data/TODO.fixup/30-theme-system-stub.md +46 -0
  173. data/TODO.fixup/31-theme-value-object-registry.md +17 -0
  174. data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
  175. data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
  176. data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
  177. data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
  178. data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
  179. data/TODO.fixup/37-package-shape-rendering.md +22 -0
  180. data/TODO.fixup/38-note-element-rendering.md +15 -0
  181. data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
  182. data/TODO.fixup/40-connector-dashed-lines.md +15 -0
  183. data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
  184. data/TODO.fixup/42-textrenderer-centralization.md +10 -0
  185. data/TODO.fixup/43-colorresolver-unification.md +24 -0
  186. data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
  187. data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
  188. data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
  189. data/TODO.fixup/47-canvas-frame-inset.md +19 -0
  190. data/TODO.fixup/48-background-rect-format.md +15 -0
  191. data/TODO.fixup/49-all-samples-integration-test.md +17 -0
  192. data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
  193. data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
  194. data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
  195. data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
  196. data/TODO.fixup/54-diagram-theme-api.md +50 -0
  197. data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
  198. data/TODO.fixup/56-theme-yaml-files.md +65 -0
  199. data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
  200. data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
  201. data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
  202. data/TODO.fixup/60-cli-theme-option.md +22 -0
  203. data/TODO.fixup/61-theme-validation.md +28 -0
  204. data/TODO.fixup/62-theme-builder-dsl.md +31 -0
  205. data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
  206. data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
  207. data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
  208. data/TODO.fixup/66-styleex-writeback.md +22 -0
  209. data/TODO.fixup/67-delete-dead-code.md +28 -0
  210. data/TODO.fixup/68-figure-parity-status.md +82 -0
  211. data/TODO.fixup/69-package-polygon-rendering.md +54 -0
  212. data/TODO.fixup/70-tagged-values-compartment.md +39 -0
  213. data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
  214. data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
  215. data/TODO.fixup/73-delete-dead-transformations.md +14 -0
  216. data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
  217. data/TODO.fixup/75-visibility-legend-icons.md +23 -0
  218. data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
  219. data/TODO.fixup/77-canvas-frame-margins.md +28 -0
  220. data/TODO.fixup/78-note-element-rendering.md +30 -0
  221. data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
  222. data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
  223. data/TODO.fixup/81-figure-parity-current-state.md +63 -0
  224. data/config/qea_schema.yml +356 -0
  225. data/config/themes/119.yml +98 -0
  226. data/config/themes/default.yml +14 -0
  227. data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
  228. data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
  229. data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
  230. data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
  231. data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
  232. data/examples/exports/UmlModel_template/model.xml +23 -0
  233. data/examples/exports/basic/UML_EA.DTD +6856 -0
  234. data/examples/exports/basic/model.xml +8039 -0
  235. data/examples/exports/simple/UML_EA.DTD +6856 -0
  236. data/examples/exports/simple/model.xml +585 -0
  237. data/examples/exports/simple_example/UML_EA.DTD +6856 -0
  238. data/examples/exports/simple_example/model.xml +23 -0
  239. data/examples/exports/test/UML_EA.DTD +6856 -0
  240. data/examples/exports/test/model.xml +1638 -0
  241. data/examples/qea/basic.qea +0 -0
  242. data/frontend/README.md +51 -0
  243. data/frontend/dist/app.iife.js +24 -0
  244. data/frontend/dist/style.css +1 -0
  245. data/frontend/index.html +26 -0
  246. data/frontend/package-lock.json +2359 -0
  247. data/frontend/package.json +26 -0
  248. data/frontend/src/App.vue +59 -0
  249. data/frontend/src/app.ts +8 -0
  250. data/frontend/src/components/AppHeader.vue +127 -0
  251. data/frontend/src/components/AppSidebar.vue +119 -0
  252. data/frontend/src/components/ClassDetails.vue +247 -0
  253. data/frontend/src/components/DiagramView.vue +79 -0
  254. data/frontend/src/components/PackageDetails.vue +92 -0
  255. data/frontend/src/components/PackageTreeNode.vue +64 -0
  256. data/frontend/src/components/SearchResults.vue +48 -0
  257. data/frontend/src/components/WelcomeView.vue +87 -0
  258. data/frontend/src/shims-vue.d.ts +5 -0
  259. data/frontend/src/stores/dataStore.ts +79 -0
  260. data/frontend/src/stores/uiStore.ts +167 -0
  261. data/frontend/src/styles/main.css +1566 -0
  262. data/frontend/src/types.ts +221 -0
  263. data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
  264. data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
  265. data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
  266. data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
  267. data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
  268. data/frontend/tests/e2e/render.spec.ts +188 -0
  269. data/frontend/tsconfig.json +20 -0
  270. data/frontend/vite.config.ts +26 -0
  271. data/frontend/vitest.config.ts +8 -0
  272. data/lib/ea/cli/app.rb +57 -2
  273. data/lib/ea/cli/command/diagrams.rb +37 -28
  274. data/lib/ea/cli/command/diff.rb +46 -0
  275. data/lib/ea/cli/command/export.rb +101 -0
  276. data/lib/ea/cli/command/info.rb +75 -0
  277. data/lib/ea/cli/command/lint.rb +48 -0
  278. data/lib/ea/cli/command/mdg.rb +98 -0
  279. data/lib/ea/cli/command/query.rb +34 -0
  280. data/lib/ea/cli/command/render.rb +135 -0
  281. data/lib/ea/cli/command/svg.rb +8 -15
  282. data/lib/ea/cli/command.rb +7 -0
  283. data/lib/ea/diagram/display_config.rb +184 -0
  284. data/lib/ea/diagram.rb +4 -41
  285. data/lib/ea/diff/change.rb +30 -0
  286. data/lib/ea/diff/comparator.rb +109 -0
  287. data/lib/ea/diff/html_reporter.rb +91 -0
  288. data/lib/ea/diff.rb +15 -0
  289. data/lib/ea/export/json/generator.rb +118 -0
  290. data/lib/ea/export/json.rb +12 -0
  291. data/lib/ea/export/json_schema/generator.rb +77 -0
  292. data/lib/ea/export/json_schema.rb +12 -0
  293. data/lib/ea/export/plantuml/generator.rb +140 -0
  294. data/lib/ea/export/plantuml.rb +12 -0
  295. data/lib/ea/export/xsd/class_mapping.rb +65 -0
  296. data/lib/ea/export/xsd/generator.rb +137 -0
  297. data/lib/ea/export/xsd/namespace_registry.rb +82 -0
  298. data/lib/ea/export/xsd.rb +19 -0
  299. data/lib/ea/export.rb +13 -0
  300. data/lib/ea/image/emf_renderer.rb +42 -0
  301. data/lib/ea/image.rb +12 -0
  302. data/lib/ea/lint/engine.rb +30 -0
  303. data/lib/ea/lint/lint_rule.rb +38 -0
  304. data/lib/ea/lint/offense.rb +18 -0
  305. data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
  306. data/lib/ea/lint/rules/duplicate_name.rb +28 -0
  307. data/lib/ea/lint/rules/missing_stereotype.rb +40 -0
  308. data/lib/ea/lint/rules/naming_convention.rb +44 -0
  309. data/lib/ea/lint/rules/orphan_element.rb +28 -0
  310. data/lib/ea/lint/rules.rb +14 -0
  311. data/lib/ea/lint.rb +13 -0
  312. data/lib/ea/mdg/document.rb +120 -0
  313. data/lib/ea/mdg/loader.rb +118 -0
  314. data/lib/ea/mdg/registry.rb +98 -0
  315. data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
  316. data/lib/ea/mdg/xml/applies_to.rb +18 -0
  317. data/lib/ea/mdg/xml/apply.rb +18 -0
  318. data/lib/ea/mdg/xml/content.rb +18 -0
  319. data/lib/ea/mdg/xml/documentation.rb +24 -0
  320. data/lib/ea/mdg/xml/stereotype.rb +28 -0
  321. data/lib/ea/mdg/xml/stereotypes.rb +18 -0
  322. data/lib/ea/mdg/xml/tag.rb +28 -0
  323. data/lib/ea/mdg/xml/tagged_values.rb +18 -0
  324. data/lib/ea/mdg/xml/technology.rb +28 -0
  325. data/lib/ea/mdg/xml/uml_profile.rb +22 -0
  326. data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
  327. data/lib/ea/mdg/xml.rb +24 -0
  328. data/lib/ea/mdg.rb +25 -0
  329. data/lib/ea/model/classifier.rb +4 -0
  330. data/lib/ea/model/constraint.rb +24 -0
  331. data/lib/ea/model/diagram.rb +85 -0
  332. data/lib/ea/model/diagram_connector.rb +34 -0
  333. data/lib/ea/model/diagram_element.rb +16 -0
  334. data/lib/ea/model/document.rb +47 -2
  335. data/lib/ea/model/ghost_label.rb +32 -0
  336. data/lib/ea/model/instance_specification.rb +34 -0
  337. data/lib/ea/model/legend.rb +43 -0
  338. data/lib/ea/model/legend_item.rb +26 -0
  339. data/lib/ea/model/note.rb +28 -0
  340. data/lib/ea/model/operation.rb +2 -0
  341. data/lib/ea/model/property.rb +2 -0
  342. data/lib/ea/model/relationship.rb +2 -0
  343. data/lib/ea/model/signal.rb +14 -0
  344. data/lib/ea/model/slot.rb +19 -0
  345. data/lib/ea/model.rb +8 -0
  346. data/lib/ea/ocl/evaluator.rb +94 -0
  347. data/lib/ea/ocl/nodes.rb +30 -0
  348. data/lib/ea/ocl/parser.rb +133 -0
  349. data/lib/ea/ocl/unsupported_error.rb +7 -0
  350. data/lib/ea/ocl.rb +13 -0
  351. data/lib/ea/qea/factory/document_builder.rb +24 -10
  352. data/lib/ea/qea/factory/generalization_builder.rb +9 -11
  353. data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
  354. data/lib/ea/qea/models/ea_author.rb +35 -0
  355. data/lib/ea/qea/models/ea_glossary.rb +34 -0
  356. data/lib/ea/qea/models/ea_image.rb +53 -0
  357. data/lib/ea/qea/models/ea_implement.rb +32 -0
  358. data/lib/ea/qea/models/ea_list.rb +42 -0
  359. data/lib/ea/qea/models/ea_object_effort.rb +34 -0
  360. data/lib/ea/qea/models/ea_object_problem.rb +37 -0
  361. data/lib/ea/qea/models/ea_object_require.rb +34 -0
  362. data/lib/ea/qea/models/ea_object_resource.rb +34 -0
  363. data/lib/ea/qea/models/ea_object_risk.rb +34 -0
  364. data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
  365. data/lib/ea/qea/models/ea_object_test.rb +35 -0
  366. data/lib/ea/qea/models/ea_object_trx.rb +34 -0
  367. data/lib/ea/qea/models/ea_operation.rb +7 -0
  368. data/lib/ea/qea/models/ea_palette.rb +30 -0
  369. data/lib/ea/qea/models/ea_palette_item.rb +36 -0
  370. data/lib/ea/qea/models/ea_phase.rb +40 -0
  371. data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
  372. data/lib/ea/qea/models/ea_secrypt.rb +34 -0
  373. data/lib/ea/qea/models/ea_version.rb +39 -0
  374. data/lib/ea/qea/models/ea_xref.rb +11 -1
  375. data/lib/ea/qea/models.rb +19 -0
  376. data/lib/ea/qea/services/database_loader.rb +22 -1
  377. data/lib/ea/qea/validation/database/ocl_constraint_validator.rb +65 -0
  378. data/lib/ea/qea/validation/database.rb +2 -0
  379. data/lib/ea/qea/validation/validation_engine.rb +2 -0
  380. data/lib/ea/qea/validation.rb +2 -0
  381. data/lib/ea/query/builder.rb +127 -0
  382. data/lib/ea/query.rb +9 -0
  383. data/lib/ea/render/image_converter.rb +101 -0
  384. data/lib/ea/render.rb +10 -0
  385. data/lib/ea/shapescript/parser.rb +208 -0
  386. data/lib/ea/shapescript/renderer.rb +74 -0
  387. data/lib/ea/shapescript/shape.rb +34 -0
  388. data/lib/ea/shapescript.rb +24 -0
  389. data/lib/ea/sources/qea/adapter.rb +22 -5
  390. data/lib/ea/sources/qea/classifier_builder.rb +184 -7
  391. data/lib/ea/sources/qea/diagram_builder.rb +352 -24
  392. data/lib/ea/sources/qea/id_normalizer.rb +16 -1
  393. data/lib/ea/sources/qea/instance_builder.rb +113 -0
  394. data/lib/ea/sources/qea/legend_builder.rb +137 -0
  395. data/lib/ea/sources/qea/note_builder.rb +58 -0
  396. data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
  397. data/lib/ea/sources/qea/operation_builder.rb +1 -0
  398. data/lib/ea/sources/qea/package_builder.rb +16 -0
  399. data/lib/ea/sources/qea/relationship_builder.rb +21 -5
  400. data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
  401. data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
  402. data/lib/ea/sources/qea/xref/parser.rb +150 -0
  403. data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
  404. data/lib/ea/sources/qea/xref/record.rb +41 -0
  405. data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
  406. data/lib/ea/sources/qea/xref.rb +27 -0
  407. data/lib/ea/sources/qea.rb +4 -0
  408. data/lib/ea/sources/xmi/adapter.rb +80 -2
  409. data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
  410. data/lib/ea/sources/xmi/diagram_builder.rb +95 -18
  411. data/lib/ea/sources/xmi/extension_geometry_parser.rb +19 -2
  412. data/lib/ea/sources/xmi/extension_style_parser.rb +15 -2
  413. data/lib/ea/sources/xmi/note_builder.rb +46 -0
  414. data/lib/ea/sources/xmi/property_builder.rb +9 -0
  415. data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
  416. data/lib/ea/sources/xmi/tag_builder.rb +45 -0
  417. data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
  418. data/lib/ea/sources/xmi.rb +4 -0
  419. data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
  420. data/lib/ea/spa/output/single_file_strategy.rb +8 -2
  421. data/lib/ea/spa/output/strategy.rb +34 -0
  422. data/lib/ea/svg/connector_router.rb +134 -0
  423. data/lib/ea/svg/ea_emitter/background.rb +2 -3
  424. data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
  425. data/lib/ea/svg/ea_emitter/canvas.rb +56 -33
  426. data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
  427. data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
  428. data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
  429. data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
  430. data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
  431. data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
  432. data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
  433. data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
  434. data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
  435. data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
  436. data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
  437. data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
  438. data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
  439. data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
  440. data/lib/ea/svg/ea_emitter/compartment/stereotype_icon.rb +32 -0
  441. data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
  442. data/lib/ea/svg/ea_emitter/compartment.rb +60 -0
  443. data/lib/ea/svg/ea_emitter/connectors.rb +46 -12
  444. data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
  445. data/lib/ea/svg/ea_emitter/document.rb +49 -25
  446. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
  447. data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
  448. data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
  449. data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
  450. data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
  451. data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
  452. data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
  453. data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
  454. data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
  455. data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
  456. data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
  457. data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
  458. data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
  459. data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
  460. data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
  461. data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
  462. data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
  463. data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
  464. data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
  465. data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
  466. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
  467. data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
  468. data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
  469. data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
  470. data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +119 -0
  471. data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
  472. data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
  473. data/lib/ea/svg/ea_emitter/element.rb +37 -0
  474. data/lib/ea/svg/ea_emitter/elements.rb +283 -95
  475. data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
  476. data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
  477. data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
  478. data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
  479. data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
  480. data/lib/ea/svg/ea_emitter/label.rb +23 -0
  481. data/lib/ea/svg/ea_emitter/labels.rb +93 -27
  482. data/lib/ea/svg/ea_emitter/layer.rb +20 -0
  483. data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
  484. data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
  485. data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
  486. data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
  487. data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
  488. data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
  489. data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
  490. data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
  491. data/lib/ea/svg/ea_emitter/marker.rb +37 -0
  492. data/lib/ea/svg/ea_emitter/markers.rb +351 -64
  493. data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
  494. data/lib/ea/svg/ea_emitter/style.rb +15 -0
  495. data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
  496. data/lib/ea/svg/ea_emitter.rb +33 -11
  497. data/lib/ea/svg/parity/checker.rb +105 -0
  498. data/lib/ea/svg/parity/source.rb +59 -0
  499. data/lib/ea/svg/parity/suite.rb +113 -0
  500. data/lib/ea/svg/parity.rb +14 -0
  501. data/lib/ea/svg.rb +2 -15
  502. data/lib/ea/theme/definition.rb +176 -0
  503. data/lib/ea/theme/loader.rb +125 -0
  504. data/lib/ea/theme/registry.rb +96 -0
  505. data/lib/ea/theme.rb +37 -0
  506. data/lib/ea/transformations.rb +5 -88
  507. data/lib/ea/validation/xmi_parity.rb +80 -0
  508. data/lib/ea/validation.rb +12 -0
  509. data/lib/ea/version.rb +4 -1
  510. data/lib/ea.rb +15 -4
  511. data/lib/tasks/svg_bench.rake +87 -0
  512. data/lutaml-uml-0.5.1.gem +0 -0
  513. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
  514. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
  515. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
  516. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
  517. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
  518. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
  519. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
  520. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
  521. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
  522. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
  523. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
  524. metadata +464 -26
  525. data/lib/ea/diagram/configuration.rb +0 -379
  526. data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
  527. data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
  528. data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
  529. data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
  530. data/lib/ea/diagram/element_renderers.rb +0 -43
  531. data/lib/ea/diagram/extractor.rb +0 -566
  532. data/lib/ea/diagram/layout_engine.rb +0 -170
  533. data/lib/ea/diagram/path_builder.rb +0 -202
  534. data/lib/ea/diagram/style_parser.rb +0 -42
  535. data/lib/ea/diagram/style_resolver.rb +0 -291
  536. data/lib/ea/diagram/svg_renderer.rb +0 -274
  537. data/lib/ea/diagram/util.rb +0 -73
  538. data/lib/ea/svg/bounds_calculator.rb +0 -74
  539. data/lib/ea/svg/connector_path.rb +0 -138
  540. data/lib/ea/svg/element_box.rb +0 -256
  541. data/lib/ea/svg/renderer.rb +0 -77
  542. data/lib/ea/svg/style_resolver.rb +0 -72
  543. data/lib/ea/transformations/configuration.rb +0 -333
  544. data/lib/ea/transformations/format_registry.rb +0 -366
  545. data/lib/ea/transformations/parsers/base_parser.rb +0 -482
  546. data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
  547. data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
  548. data/lib/ea/transformations/transformation_engine.rb +0 -390
@@ -0,0 +1,62 @@
1
+ # TODO-D 65: Path coordinate frame mismatch (y-axis sign)
2
+
3
+ ## Status: open
4
+
5
+ Elements render at the wrong vertical position because
6
+ `bounds_from_rect` interprets `RectTop` as the math-convention
7
+ y (negative, larger=lower) when EA actually stores it as the
8
+ negation of the screen-space y (negative, larger=higher).
9
+
10
+ The bench's shape_delta_total doesn't catch this because counts
11
+ match — but per-path coordinate comparison shows every ref path
12
+ is "missing" from our output (coordinate values differ).
13
+
14
+ ## Evidence (plateau QEA, "Bridge" diagram)
15
+
16
+ Raw EA rect for `_CityObject`:
17
+ - RectLeft=611, RectTop=-64, RectRight=941, RectBottom=-186
18
+
19
+ Reference SVG renders `_CityObject` text at `y=73`.
20
+
21
+ Our model produces `bounds.y = -186` (taking `min(RectTop, RectBottom)`).
22
+ After canvas translation we render at `y > 1000` (bottom of canvas).
23
+
24
+ The correct interpretation is:
25
+ - screen-y of element's top edge = `-RectTop = 64`
26
+ - height = `RectTop - RectBottom = -64 - (-186) = 122`
27
+
28
+ With a small offset (33 in basic.qea, 9 in plateau Bridge) we'd
29
+ match the reference's text baseline.
30
+
31
+ ## Approach
32
+
33
+ Update `DiagramBuilder#bounds_from_rect`:
34
+
35
+ ```ruby
36
+ def bounds_from_rect(obj_row)
37
+ left = obj_row.rectleft || 0
38
+ right = obj_row.rectright || 0
39
+ top = obj_row.recttop || 0
40
+ bottom = obj_row.rectbottom || 0
41
+ Ea::Model::Bounds.new(
42
+ x: [left, right].min,
43
+ y: -[top, bottom].max, # flip y-axis
44
+ width: (right - left).abs,
45
+ height: (bottom - top).abs
46
+ )
47
+ end
48
+ ```
49
+
50
+ Then rework `Canvas#translate_y` and `BoundsCalculator` to use
51
+ positive y values consistently. The current min_y computation
52
+ also needs to flip.
53
+
54
+ This is a large change — needs careful re-verification against
55
+ basic.qea and test.qea to avoid regressing the 24/24 currently
56
+ matched.
57
+
58
+ ## Impact
59
+
60
+ Doesn't change counts (and so won't move the bench needle), but
61
+ makes the visual output match EA positionally. Required before
62
+ we can claim "100% identical to QEA->SVG" in any visual sense.
@@ -0,0 +1,62 @@
1
+ # TODO-D 67: Path coordinate frame (y-axis sign)
2
+
3
+ ## Status: open
4
+
5
+ Elements render at the wrong vertical position because
6
+ `bounds_from_rect` interprets `RectTop` as the math-convention
7
+ y (negative, larger=lower on screen) when EA actually stores
8
+ it as the negation of the screen-space y.
9
+
10
+ The bench's shape_delta_total doesn't catch this because counts
11
+ match — but per-path coordinate comparison shows every ref path
12
+ is "missing" from our output (coordinate values differ).
13
+
14
+ ## Evidence (plateau QEA, "Bridge" diagram)
15
+
16
+ Raw EA rect for `_CityObject`:
17
+ - RectLeft=611, RectTop=-64, RectRight=941, RectBottom=-186
18
+
19
+ Reference SVG renders `_CityObject` text at `y=73`.
20
+
21
+ Our model produces `bounds.y = -186` (taking `min(RectTop, RectBottom)`).
22
+ After canvas translation we render at `y > 1000` (bottom of canvas).
23
+
24
+ The correct interpretation is:
25
+ - screen-y of element's top edge = `-RectTop = 64`
26
+ - height = `RectTop - RectBottom = -64 - (-186) = 122`
27
+
28
+ With the canvas's positive offset (40 frame inset + diagram-specific),
29
+ we match the reference's text baseline.
30
+
31
+ ## Approach
32
+
33
+ Update `DiagramBuilder#bounds_from_rect`:
34
+
35
+ ```ruby
36
+ def bounds_from_rect(obj_row)
37
+ left = obj_row.rectleft || 0
38
+ right = obj_row.rectright || 0
39
+ top = obj_row.recttop || 0
40
+ bottom = obj_row.rectbottom || 0
41
+ Ea::Model::Bounds.new(
42
+ x: [left, right].min,
43
+ y: -[top, bottom].max, # flip y-axis
44
+ width: (right - left).abs,
45
+ height: (bottom - top).abs
46
+ )
47
+ end
48
+ ```
49
+
50
+ Then rework `Canvas#translate_y` and `BoundsCalculator` to use
51
+ positive y values consistently. The current min_y computation
52
+ also needs to flip.
53
+
54
+ This is a large change — needs careful re-verification against
55
+ basic.qea and test.qea to avoid regressing the 184/188 currently
56
+ matched.
57
+
58
+ ## Impact
59
+
60
+ Doesn't change counts (and so won't move the bench needle), but
61
+ makes the visual output match EA positionally. Required before
62
+ we can claim "100% identical to QEA->SVG" in any visual sense.
@@ -0,0 +1,65 @@
1
+ # TODO-D 68: Association-derived virtual properties (phantom attributes)
2
+
3
+ ## Status: open (discriminator unresolved)
4
+
5
+ EA renders some association SourceRole values as virtual
6
+ "property" attributes inside the source classifier's attribute
7
+ compartment. For example, ImplicitGeometry has 4 associations to
8
+ CityFurniture with SourceRoles lod1..4ImplicitRepresentation.
9
+ EA renders "+lod1ImplicitRepresentation" inside ImplicitGeometry's
10
+ attribute compartment on every diagram where ImplicitGeometry is
11
+ placed with an expanded attribute compartment.
12
+
13
+ ## Investigation findings
14
+
15
+ The phantom attributes come from t_connector.SourceRole on
16
+ Association and Aggregation connectors. In the plateau QEA:
17
+ - 206 Aggregations have SourceRoles
18
+ - 172 Associations have SourceRoles
19
+
20
+ Not all SourceRoles render as virtual attributes. The discriminator
21
+ that gates rendering has NOT been identified. Adding all 378
22
+ SourceRoles as properties causes massive over-rendering (text
23
+ delta: +20,000). The correct subset is much smaller.
24
+
25
+ ### What was tried
26
+
27
+ 1. **All SourceRoles as properties**: text +20k — far too many.
28
+ The vast majority of SourceRoles do NOT render in EA output.
29
+
30
+ 2. **Only when connector NOT on current diagram**: incorrect —
31
+ on the ImplicitGeometry diagram, the lod* connectors ARE on
32
+ the diagram AND the phantom attrs still show.
33
+
34
+ 3. **Only for GML stereotypes (Type/FeatureType)**: promising
35
+ but not all "Type" stereotyped classifiers show SourceRole
36
+ attrs on every diagram. CityGMLCore shows ImplicitGeometry
37
+ WITHOUT the lod texts (element is in collapsed mode).
38
+
39
+ ### What's known
40
+
41
+ - SourceRoles render ONLY when the element's attribute compartment
42
+ is visible AND expanded (has NSL/font settings in ObjectStyle).
43
+ - The position of phantom attr texts in the ref SVG is OUTSIDE
44
+ any element rect (floating) on some diagrams, suggesting EA
45
+ places them at connector-label positions rather than inside
46
+ the attribute compartment.
47
+ - Multiple phantom attrs at the same position suggests overlap
48
+ rendering (all at same x,y) which is characteristic of connector
49
+ end-labels, not attribute-compartment lines.
50
+
51
+ ### Next steps
52
+
53
+ 1. Investigate whether the phantom attrs are actually connector
54
+ LABELS (from $LLB/$LLT geometry) rather than attribute
55
+ compartment lines. The position (412, 473) doesn't match any
56
+ element's attribute compartment area.
57
+
58
+ 2. Check if the phantom attrs come from a per-diagram setting
59
+ like "Show inherited/association attributes" flag in the
60
+ t_diagram StyleEx or PDATA.
61
+
62
+ 3. If they ARE attribute-compartment lines (not labels),
63
+ identify the precise subset of SourceRoles that EA renders
64
+ (maybe only when the connector's DestRole is empty AND the
65
+ SourceRole matches a naming convention).
@@ -0,0 +1,29 @@
1
+ # TODO-D 69: Package anchor marker conditional rendering
2
+
3
+ ## Status: completed
4
+
5
+ The «import» connector's package_anchor marker (4-point closed
6
+ trapezoid at the source end) was rendered unconditionally,
7
+ causing 9 phantom paths on the plateau "Urban Planning ADE2"
8
+ diagram.
9
+
10
+ ## Root cause
11
+
12
+ EA's t_diagramlinks.Geometry string carries explicit SX/SY/EX/EY
13
+ offset fields when the connector has been explicitly configured
14
+ with edge-attachment offsets. When SX/SY are absent, the
15
+ connector is auto-routed and EA suppresses the package_anchor
16
+ marker.
17
+
18
+ ## Fix
19
+
20
+ Added `has_geometry_offsets` boolean to DiagramConnector model.
21
+ DiagramBuilder sets it by checking whether the raw Geometry
22
+ string contains "SX=". PackageImport marker returns [] when
23
+ false.
24
+
25
+ ## Verification
26
+
27
+ - basic.qea Package Imports: SX=0;SY=0 present -> marker renders
28
+ - plateau Urban Planning ADE2: SX/SY absent -> no marker
29
+ - Urban Planning ADE2 delta dropped from 9 to 0 → matched
@@ -0,0 +1,68 @@
1
+ # TODO-D 70: MDG Technology Support
2
+
3
+ ## Status: Phases 1 & 2 complete; Phase 3 deferred
4
+
5
+ EA's MDG (Model Driven Generation) technologies bundle UML
6
+ profiles, reference models, and toolbox definitions in a single
7
+ XMI file. When EA loads an MDG, the MDG's classes/attributes/
8
+ stereotypes become available to all models — including inherited
9
+ attribute rendering when a classifier's stereotype maps to an
10
+ MDG-defined metaclass.
11
+
12
+ ## Architecture (shipped)
13
+
14
+ ```
15
+ Ea::Mdg # standalone namespace
16
+ ├─ Document # one MDG file's parsed model
17
+ │ ├─ ClassifierEntry (id, name, package_name, properties)
18
+ │ ├─ PropertyEntry (name, type_name, visibility, mult)
19
+ │ └─ GeneralizationEntry (specific_id, general_id)
20
+ ├─ Loader # XMI parser → Document
21
+ └─ Registry # multi-MDG lookup, ancestor walking
22
+ ```
23
+
24
+ Integration:
25
+
26
+ - `Ea::Sources::Qea::Adapter.from_path(path, mdg_registry: nil)`
27
+ - When `mdg_registry:` is wired, `ClassifierBuilder#properties_for`
28
+ merges MDG-inherited attributes into the classifier's property
29
+ list.
30
+ - Backward-compatible: omitting `mdg_registry:` preserves prior
31
+ behavior exactly.
32
+
33
+ ## Verified against reference MDG files
34
+
35
+ - `MDG ISO19103.xml` (12 classifiers, 5 packages)
36
+ - `ISO 19103 Edition 1 XML.xml` (62 classifiers, 68 generalizations,
37
+ properties under UML:Classifier.feature)
38
+ - Ancestor walk yields correct inherited properties
39
+ (e.g. UnitsList → StandardUnits → 11 properties)
40
+
41
+ ## What's still needed for plateau parity
42
+
43
+ The plateau phantom attributes (`+lod1ImplicitRepresentation`
44
+ on `ImplicitGeometry`, `+boundedBy` on `_CityObject`, etc.) come
45
+ from a **CityGML/GML MDG** that is not in the user's
46
+ `~/src/lutaml/xmi/references/ImplementationModels/` directory.
47
+
48
+ To close those specific gaps:
49
+ 1. Obtain the CityGML/GML MDG technology XML file.
50
+ 2. Pass it via `mdg_registry:` when loading the plateau QEA.
51
+ 3. The classifier's `Type` stereotype will resolve to the MDG's
52
+ `Type` class, and its ancestor properties will merge in.
53
+
54
+ This is data-availability, not architecture. The plumbing works.
55
+
56
+ ## Phase 3 (deferred)
57
+
58
+ - Stereotype definition extraction (UML:Profile/Stereotype) for
59
+ applying tagged values from MDG stereotype definitions.
60
+ - CLI subcommand: `ea mdg list` / `ea mdg show <name>`.
61
+ - Toolbox definition parsing (for future toolbox rendering).
62
+
63
+ ## Test coverage
64
+
65
+ - `spec/ea/mdg/loader_spec.rb` (6 specs)
66
+ - `spec/ea/mdg/registry_spec.rb` (8 specs)
67
+ - `spec/ea/sources/qea/mdg_integration_spec.rb` (3 specs)
68
+ - Total: 17 new specs; full suite 1839 examples, 0 failures.
@@ -0,0 +1,45 @@
1
+ # TODO-D 71: Off-canvas parent class ghost line in element header
2
+
3
+ ## Status: completed (2026-08-01)
4
+
5
+ EA prepends the off-canvas parent classifier's name as an italic
6
+ line at the top of a placed element's header when ALL of:
7
+
8
+ 1. The diagram's HideParents PDATA flag is 0 (default).
9
+ 2. The placed element has a Generalization to a parent NOT placed
10
+ on the current diagram.
11
+ 3. No other element from the parent's package is placed on the
12
+ diagram (EA treats the parent's package as "represented").
13
+
14
+ e.g. on the indoor diagram (HideParents=0), Room's parent
15
+ _CityObject (in the "core" package, off-canvas, no other core
16
+ elements placed) renders as an italic "_CityObject" line above
17
+ Room's own header. On Building (HideParents=1), no parent ghosts
18
+ render at all.
19
+
20
+ ## Implementation
21
+
22
+ - RelationshipBuilder populates Generalization.specific_id and
23
+ .general_id (child + parent GUIDs).
24
+ - Diagram model gains show_parents attribute; DiagramBuilder
25
+ parses HideParents= from t_diagram.PDATA.
26
+ - RenderContext carries off_canvas_parent_name; Elements resolves
27
+ it via document.relationships + model_index + diagram.elements.
28
+ - HeaderLines prepends [name, :italic] when the value is non-nil.
29
+ - LayerSequencer threads `document:` to Elements.
30
+
31
+ ## Plateau QEA impact
32
+
33
+ - Before: text delta -98 (98 texts missing vs ref)
34
+ - After: text delta -36 (62 texts closed)
35
+ - 188/188 diagrams matched.
36
+
37
+ ## Remaining gap (-36)
38
+
39
+ The foreign-package rule is slightly too aggressive — some diagrams
40
+ (tran_2, urf_urbanFunction) render parent ghosts for parents in
41
+ "represented" packages. Removing the foreign-package check
42
+ over-corrects to +60 (over-render). The true discriminator is
43
+ narrower than "package represented" but broader than just
44
+ HideParents. Defer to a future investigation if a clearer signal
45
+ (e.g., a t_object flag, MDG stereotype pattern) is identified.
@@ -0,0 +1,39 @@
1
+ # TODO-D 72: Spurious per-attribute divider paths on basic.qea outlier
2
+
3
+ ## Status: open
4
+
5
+ basic.qea diagram "Two Level Class Composition Hierarchy with
6
+ Attributes" (4FC1D352-...) over-renders 16 short horizontal <path>
7
+ elements that the EA reference does not emit.
8
+
9
+ ## Symptom
10
+
11
+ - rect: ours=18 ref=18 (matches)
12
+ - path: ours=50 ref=34 (+16 overshoot)
13
+ - polygon: ours=17 ref=17 (matches)
14
+ - text: ours=102 ref=102 (matches)
15
+
16
+ ## Pattern of the extra paths
17
+
18
+ All 16 extras are short 110px-wide horizontal lines at evenly
19
+ spaced y coordinates that line up with attribute rows:
20
+
21
+ - M 661 66 L 771 66
22
+ - M 661 152 L 771 152
23
+ - M 661 238 L 771 238
24
+ - M 487 66 L 597 66
25
+ - M 487 152 L 597 152
26
+ - ... (12 more at the same y values across 4 element columns)
27
+
28
+ ## Hypothesis
29
+
30
+ We render per-attribute separator lines between each attribute row.
31
+ EA only emits a single header→content divider plus the element rect
32
+ outline; attribute rows are NOT visually separated by horizontal
33
+ lines in EA's encoding.
34
+
35
+ ## Next step
36
+
37
+ Audit Compartment::Attributes and DividerRenderer for any per-row
38
+ line emission. The fix is to suppress row separators and keep only
39
+ the header divider.
@@ -0,0 +1,69 @@
1
+ # TODO-D 73: Plateau polygon under-render (-4)
2
+
3
+ ## Status: partially investigated (2026-08-02)
4
+
5
+ Across 188 plateau diagrams, we render 4 fewer `<polygon>` elements
6
+ than EA's reference SVG. Per-diagram deltas:
7
+
8
+ - Appearance (BC1F7E00, C31C1314): -2 each
9
+ - CityGMLCore (88D0CB44): -1
10
+ - 都市計画決定情報の概要 (8FD488EF): -1
11
+ - 立体的な範囲、区域界、品質属性 (1321F39B): -1
12
+ - 都市施設 (C96CBC24): -1
13
+ - 3D都市モデル応用スキーマと他のスキーマとの関係 (DFBB1072): +3
14
+ - udx (6481E2CC): +1
15
+
16
+ ## Investigation update (2026-08-02)
17
+
18
+ For 都市施設 / 都市計画決定情報 / 立体的な範囲: each missing
19
+ polygon is a small 4-point DIAMOND inside an element body.
20
+
21
+ Example (都市施設):
22
+ `<polygon points="323 401 328 411 333 401 328 391" ...>`
23
+ Inside a `<g>` with fill="#FAF1EC" stroke="#69738C"
24
+
25
+ These colors (#FAF1EC, #69738C) are NOT standard aggregation
26
+ diamond colors (#FFFFFF fill, #000000 stroke). They appear to be
27
+ **stereotype decorator icons** — small symbolic icons EA renders
28
+ inside element bodies when a stereotype provides a custom icon.
29
+
30
+ ## Follow-up investigation (2026-08-02)
31
+
32
+ Found EA installation at:
33
+ ~/Library/Application Support/CrossOver/Bottles/
34
+ Enterprise Architect 16.x/drive_c/Program Files/Sparx Systems/EA/
35
+
36
+ Located stereotype-related files:
37
+ - Config/GML/GMLStereotypes.xml — only stereotype ALIASES, no icons
38
+ - MDGTechnologies/*.xml — many MDG files, none reference icons
39
+ - TemplateResources161.dll — likely contains compiled icon resources
40
+ - t_stereotypes table — empty Metafile BLOBs for FeatureType
41
+
42
+ Found element-style flag `HideIcon=0` on FeatureType elements on
43
+ 都市施設 — confirmed EA DOES intend to show an icon.
44
+
45
+ ## Discriminator puzzle
46
+
47
+ On 都市施設, ALL 21 placed FeatureType elements have HideIcon=0.
48
+ But ref renders the diamond icon for only 1 of them
49
+ (CollectiveFacilitiesForReconstruction — the largest element).
50
+
51
+ The discriminator is NOT:
52
+ - HideIcon flag (all elements have it = 0)
53
+ - Stereotype (all are FeatureType)
54
+ - Element size (icon position is element-relative)
55
+
56
+ Hypotheses for the actual discriminator:
57
+ 1. The element is "selected" or "active" in the source QEA
58
+ 2. The element is the diagram's "subject" (a per-diagram flag)
59
+ 3. The icon is part of a legend/key, not per-element
60
+
61
+ ## Implementation needed
62
+
63
+ To close this gap requires either:
64
+ 1. Reverse-engineering EA's stereotype decorator icon logic
65
+ 2. Parsing the EMF BLOB from t_image (1 image, 69KB)
66
+ 3. Extracting icon resources from EA.exe / TemplateResources161.dll
67
+
68
+ Even then, the discriminator for WHICH elements get icons is
69
+ unclear from available data.
@@ -0,0 +1,22 @@
1
+ # TODO-D 74: Plateau rect over-render (+4)
2
+
3
+ ## Status: open
4
+
5
+ Across 188 plateau diagrams, we render 4 more `<rect>` elements
6
+ than EA's reference SVG. Per-diagram deltas are spread thin.
7
+
8
+ ## Likely causes
9
+
10
+ 1. **Phantom connector label boxes**: my phantom connector code
11
+ synthesizes label boxes (LLB/LLT) that may render extra rects.
12
+ 2. **Element rect for hidden elements**: elements that should be
13
+ filtered (e.g., via element_filter) but still render their
14
+ bounding rects.
15
+ 3. **Compartment background rects**: extra rects for compartments
16
+ that EA suppresses in certain modes.
17
+
18
+ ## Next step
19
+
20
+ Identify the 4 specific diagrams with rect_delta > 0 and inspect
21
+ the actual `<rect>` content vs ref. Likely a per-diagram PDATA
22
+ flag mismatch.
@@ -0,0 +1,39 @@
1
+ # TODO-D 75: Plateau text under-render (-36)
2
+
3
+ ## Status: open (partial — closed 62 of original -98 in TODO-D 71)
4
+
5
+ Across 188 plateau diagrams, we render 36 fewer `<text>` elements
6
+ than EA's reference SVG. Top undershoot diagrams:
7
+
8
+ - tran_2 (-4): missing 2× RoadAttribute, 1× TransportationComplex,
9
+ 1× _TransportationObject, 1× TrafficAreaAttribute
10
+ - urf_urbanFunction (-4): similar pattern
11
+ - 12 diagrams at -3 each
12
+ - many at -2
13
+
14
+ ## Root cause
15
+
16
+ The foreign-package rule in `off_canvas_parent_name_for` is too
17
+ aggressive. It suppresses parent ghosts when ANY placed element
18
+ shares the parent's package, but EA actually renders ghosts in
19
+ this case for diagrams like tran_2 and urf_urbanFunction.
20
+
21
+ The discriminator is narrower than "package represented" — possibly
22
+ related to whether the parent is in a base library (gml) vs a user
23
+ package (uro, tran), or some other property of the parent class.
24
+
25
+ ## What was tried
26
+
27
+ 1. **Just HideParents flag**: closed -98 to +60 (over-rendered 60).
28
+ 2. **HideParents + foreign-package check**: closed +60 to -36
29
+ (under-rendered 36).
30
+
31
+ The truth is between these. Narrower discriminator needed.
32
+
33
+ ## Deferred
34
+
35
+ Requires identifying the precise EA rule. Could be:
36
+ - A t_object flag on the parent (e.g., is it generic/template)
37
+ - The parent's package being a "base library" (gml vs user model)
38
+ - A specific stereotype pattern (e.g., base GML stereotypes)
39
+ - Connector-level metadata we're not yet reading
@@ -0,0 +1,41 @@
1
+ # TODO-D 76: basic.qea polygon under-render (-6) and path over-render (+6)
2
+
3
+ ## Status: open
4
+
5
+ After the aggregation arrow fix (TODO-D 73), basic.qea reached
6
+ 22/22 diagrams matched within tolerance, but two aggregate deltas
7
+ remain:
8
+
9
+ - polygon: ours=95, ref=101 (-6)
10
+ - path: ours=208, ref=202 (+6)
11
+
12
+ ## Per-diagram pattern
13
+
14
+ - Package Dependencies (0EDEA6EF): polygon +3
15
+ - Basic Class Diagram with Attributes (4F421236): polygon -2
16
+ - Basic Class Diagram with Operations (2AAB709F): polygon -2
17
+ - Basic Class Diagram with Receptions (4DBDAB9E): polygon -2
18
+ - Basic Class Diagram with Attributes and Operations (D2FA55D3): polygon -2
19
+ - Basic Class Diagram with Multiplicities (78030266): polygon -1
20
+ - Basic Class Diaram with Roles (6E95B74E): polygon -1
21
+ - Domain Model (E325B9D8): polygon +1
22
+
23
+ ## Likely cause (Basic Class Diagram family)
24
+
25
+ For the 4 diagrams with polygon=-2, we're missing 2 small triangle
26
+ polygon markers per diagram. These are likely Generalization arrow
27
+ triangles that we suppress somewhere.
28
+
29
+ The +3 polygon overshoot on "Package Dependencies" is likely a
30
+ package-import marker (anchor shape) that EA omits.
31
+
32
+ ## Path over-render (+6)
33
+
34
+ After the aggregation arrow fix, the +16 path over-render on the
35
+ outlier closed (to 0). The remaining +6 paths are likely from
36
+ similar marker issues on the diagrams above.
37
+
38
+ ## Next step
39
+
40
+ For each affected diagram, compare our markers vs ref's markers.
41
+ Identify which marker emission is incorrect.
@@ -0,0 +1,40 @@
1
+ # TODO-D 77: basic.qea text over-render (+2)
2
+
3
+ ## Status: open
4
+
5
+ basic.qea's two diagrams overshoot text by 1 each:
6
+
7
+ - Classes: +1
8
+ - Composition with Substitution: +1
9
+
10
+ ## Composition with Substitution diff
11
+
12
+ Ours has:
13
+ +1 "Class B.3" (split qualified name part)
14
+ +1 "Class B.2"
15
+ +1 "Class B.1"
16
+ +1 "«property»" (spurious property stereotype)
17
+
18
+ Ref has:
19
+ +1 "Class B::Class B.1" (single qualified name line)
20
+ +1 "Class B::Class B.2"
21
+ +1 "Class B::Class B.3"
22
+
23
+ So our qualified-name wrap is incorrectly splitting "Class B::X"
24
+ into two lines for these nested classes. The qualified name should
25
+ render as ONE line per element, not as "Class B::" + "X".
26
+
27
+ The spurious "«property»" text appears to come from a connector
28
+ SourceRole label that we render but ref doesn't on this diagram.
29
+
30
+ ## Classes diff
31
+
32
+ Need to identify what specific text differs on the Classes diagram.
33
+
34
+ ## Next step
35
+
36
+ 1. Inspect why qualified-name wrap triggers for "Class B::Class B.X"
37
+ (likely a width estimation mismatch).
38
+ 2. Identify the connector whose SourceRole produces "«property»"
39
+ and apply the right suppression (similar to aggregation arrow
40
+ fix — only render on specific directions).
@@ -0,0 +1,65 @@
1
+ # TODO-D 78: Refactor HeaderLines into provider chain (OCP)
2
+
3
+ ## Status: open (architecture improvement)
4
+
5
+ The current `HeaderLines.for` accepts a growing list of kwargs:
6
+
7
+ ```ruby
8
+ def for(classifier,
9
+ diagram_package_id: nil,
10
+ visually_nested: false,
11
+ umldi_keyword: nil,
12
+ bounds_width: nil,
13
+ font_size: 9,
14
+ off_canvas_parent_name: nil) # added in TODO-D 71
15
+ ...
16
+ end
17
+ ```
18
+
19
+ Adding the off-canvas parent line required:
20
+ 1. A new kwarg on `for`
21
+ 2. New logic inside `for` to prepend the line
22
+ 3. Threading the value from `Elements#build_context` through `RenderContext`
23
+
24
+ This is OCP-violating: each new header line variant (e.g., "realized
25
+ interfaces", "template parameters", "constraint summary") would
26
+ require modifying `HeaderLines.for` again.
27
+
28
+ ## Proposed refactor
29
+
30
+ Convert `HeaderLines` into a chain of line providers, each
31
+ contributing 0+ lines to the header. New line types = new provider
32
+ class, registered into the chain (no modification of existing
33
+ code).
34
+
35
+ ```ruby
36
+ module Element
37
+ module HeaderLineProvider
38
+ ALL = [
39
+ StereotypeLine, # «FeatureType» line (when present)
40
+ ParentClassLine, # italic off-canvas parent (TODO-D 71)
41
+ QualifiedNameLine, # the bold class name (with optional wrap)
42
+ ].freeze
43
+
44
+ def self.lines_for(classifier, context:)
45
+ ALL.flat_map { |provider| provider.lines_for(classifier, context) }
46
+ end
47
+ end
48
+ end
49
+ ```
50
+
51
+ Where `context` is a small Struct carrying the inputs each provider
52
+ may need (diagram_package_id, visually_nested, off_canvas_parent_name,
53
+ bounds_width, font_size, etc.).
54
+
55
+ ## Benefit
56
+
57
+ Adding a new line type (e.g., "interface signatures" on Interface
58
+ classifiers) becomes a single new provider class — `HeaderLines.for`
59
+ never changes.
60
+
61
+ ## Migration
62
+
63
+ Incremental: extract one provider at a time, starting with the
64
+ off-canvas parent line (the most recent addition). Each extraction
65
+ is independently shippable.