ea 0.3.1 → 0.5.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 (544) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -0
  3. data/TODO.complete/01-t-xref-parsing.md +91 -0
  4. data/TODO.complete/02-per-label-geometry.md +50 -0
  5. data/TODO.complete/03-object-properties-constraints.md +57 -0
  6. data/TODO.complete/04-operation-params.md +37 -0
  7. data/TODO.complete/05-pdata-flag-matrix.md +52 -0
  8. data/TODO.complete/06-emf-image-rendering.md +34 -0
  9. data/TODO.complete/07-auxiliary-tables.md +47 -0
  10. data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
  11. data/TODO.complete/11-gml-xsd-generation.md +42 -0
  12. data/TODO.complete/13-shapescript-interpreter.md +28 -0
  13. data/TODO.complete/20-cli-diff.md +46 -0
  14. data/TODO.complete/21-cli-render.md +26 -0
  15. data/TODO.complete/22-cli-export.md +29 -0
  16. data/TODO.complete/23-cli-mdg.md +23 -0
  17. data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
  18. data/TODO.complete/31-public-send-cleanup.md +61 -0
  19. data/TODO.complete/32-spec-coverage.md +33 -0
  20. data/TODO.complete/33-blocked-parity-gaps.md +41 -0
  21. data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
  22. data/TODO.complete/37-cli-lint.md +32 -0
  23. data/TODO.complete/38-cli-query.md +26 -0
  24. data/TODO.complete/39-cli-info.md +23 -0
  25. data/TODO.complete/40-ocl-evaluator.md +31 -0
  26. data/TODO.complete/41-round-trip-spec.md +18 -0
  27. data/TODO.complete/42-html-diff-report.md +18 -0
  28. data/TODO.complete/43-json-schema-export.md +20 -0
  29. data/TODO.complete/44-remaining-qea-tables.md +40 -0
  30. data/TODO.complete/45-shapescript-extensions.md +25 -0
  31. data/TODO.complete/46-xsd-consolidation.md +20 -0
  32. data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
  33. data/TODO.complete/STATUS.md +109 -0
  34. data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
  35. data/TODO.diagrams/01-xmi-extension-elements-parsing.md +67 -0
  36. data/TODO.diagrams/02-diagram-element-rich-model.md +61 -0
  37. data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
  38. data/TODO.diagrams/03-ea-style-svg-emitter.md +70 -0
  39. data/TODO.diagrams/03-text-over-rendering.md +30 -0
  40. data/TODO.diagrams/04-connector-routing-from-soid-eoid.md +55 -0
  41. data/TODO.diagrams/04-rect-under-rendering.md +33 -0
  42. data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
  43. data/TODO.diagrams/05-marker-rendering-per-relationship-type.md +49 -0
  44. data/TODO.diagrams/06-connector-labels.md +49 -0
  45. data/TODO.diagrams/06-group-layering-parity.md +39 -0
  46. data/TODO.diagrams/07-canvas-size-and-viewbox.md +39 -0
  47. data/TODO.diagrams/07-text-content-fidelity.md +65 -0
  48. data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
  49. data/TODO.diagrams/08-visual-regression-harness.md +34 -0
  50. data/TODO.diagrams/09-cli-render-all-diagrams.md +25 -0
  51. data/TODO.diagrams/10-stereotype-color-config.md +29 -0
  52. data/TODO.diagrams/11-elkrb-auto-layout-integration.md +53 -0
  53. data/TODO.diagrams/12-connector-labels.md +40 -0
  54. data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
  55. data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
  56. data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
  57. data/TODO.diagrams/14-center-header-text.md +33 -0
  58. data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
  59. data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
  60. data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
  61. data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
  62. data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
  63. data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
  64. data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
  65. data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
  66. data/TODO.diagrams/18-property-lookup-index.md +42 -0
  67. data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
  68. data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
  69. data/TODO.diagrams/20-split-labels-emitter.md +56 -0
  70. data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
  71. data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
  72. data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
  73. data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
  74. data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
  75. data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
  76. data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
  77. data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
  78. data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
  79. data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
  80. data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
  81. data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
  82. data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
  83. data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
  84. data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
  85. data/TODO.diagrams/36-instance-specification-model.md +42 -0
  86. data/TODO.diagrams/37-element-icon-decorations.md +41 -0
  87. data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
  88. data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
  89. data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
  90. data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
  91. data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
  92. data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
  93. data/TODO.diagrams/44-element-icon-decorations.md +34 -0
  94. data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
  95. data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
  96. data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
  97. data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
  98. data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
  99. data/TODO.diagrams/50-examples-parity.md +85 -0
  100. data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
  101. data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
  102. data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
  103. data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
  104. data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
  105. data/TODO.diagrams/56-package-contents-rendering.md +148 -0
  106. data/TODO.diagrams/57-instance-specification-model.md +100 -0
  107. data/TODO.diagrams/58-domain-model-note-text.md +67 -0
  108. data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
  109. data/TODO.diagrams/60-testschema-association-marker.md +40 -0
  110. data/TODO.diagrams/61-legend-block-rendering.md +55 -0
  111. data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
  112. data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
  113. data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
  114. data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
  115. data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
  116. data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
  117. data/TODO.diagrams/68-inherited-attributes.md +65 -0
  118. data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
  119. data/TODO.diagrams/70-mdg-technology-support.md +68 -0
  120. data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
  121. data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
  122. data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
  123. data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
  124. data/TODO.diagrams/75-plateau-text-gap.md +39 -0
  125. data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
  126. data/TODO.diagrams/77-basic-text-overrender.md +40 -0
  127. data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
  128. data/TODO.diagrams/79-architecture-backlog.md +65 -0
  129. data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
  130. data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
  131. data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
  132. data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
  133. data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
  134. data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
  135. data/TODO.diagrams/86-foreign-package-rule.md +62 -0
  136. data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
  137. data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
  138. data/TODO.diagrams/README.md +69 -0
  139. data/TODO.diagrams/STATUS.md +73 -0
  140. data/TODO.fixup/01-default-grouped-paths.md +34 -0
  141. data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
  142. data/TODO.fixup/03-diagram-font-inference.md +28 -0
  143. data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
  144. data/TODO.fixup/05-marker-registry-ocp.md +32 -0
  145. data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
  146. data/TODO.fixup/07-edge-attachment-formula.md +22 -0
  147. data/TODO.fixup/08-visual-diff-harness.md +28 -0
  148. data/TODO.fixup/09-extract-element-compartments.md +34 -0
  149. data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
  150. data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
  151. data/TODO.fixup/12-path-style-harmony.md +23 -0
  152. data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
  153. data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
  154. data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
  155. data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
  156. data/TODO.fixup/17-path-count-calibration.md +27 -0
  157. data/TODO.fixup/18-polygon-count-calibration.md +32 -0
  158. data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
  159. data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
  160. data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
  161. data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
  162. data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
  163. data/TODO.fixup/24-note-element-rendering.md +23 -0
  164. data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
  165. data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
  166. data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
  167. data/TODO.fixup/28-geometry-parser-identification.md +57 -0
  168. data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
  169. data/TODO.fixup/30-theme-system-stub.md +46 -0
  170. data/TODO.fixup/31-theme-value-object-registry.md +17 -0
  171. data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
  172. data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
  173. data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
  174. data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
  175. data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
  176. data/TODO.fixup/37-package-shape-rendering.md +22 -0
  177. data/TODO.fixup/38-note-element-rendering.md +15 -0
  178. data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
  179. data/TODO.fixup/40-connector-dashed-lines.md +15 -0
  180. data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
  181. data/TODO.fixup/42-textrenderer-centralization.md +10 -0
  182. data/TODO.fixup/43-colorresolver-unification.md +24 -0
  183. data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
  184. data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
  185. data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
  186. data/TODO.fixup/47-canvas-frame-inset.md +19 -0
  187. data/TODO.fixup/48-background-rect-format.md +15 -0
  188. data/TODO.fixup/49-all-samples-integration-test.md +17 -0
  189. data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
  190. data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
  191. data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
  192. data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
  193. data/TODO.fixup/54-diagram-theme-api.md +50 -0
  194. data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
  195. data/TODO.fixup/56-theme-yaml-files.md +65 -0
  196. data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
  197. data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
  198. data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
  199. data/TODO.fixup/60-cli-theme-option.md +22 -0
  200. data/TODO.fixup/61-theme-validation.md +28 -0
  201. data/TODO.fixup/62-theme-builder-dsl.md +31 -0
  202. data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
  203. data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
  204. data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
  205. data/TODO.fixup/66-styleex-writeback.md +22 -0
  206. data/TODO.fixup/67-delete-dead-code.md +28 -0
  207. data/TODO.fixup/68-figure-parity-status.md +82 -0
  208. data/TODO.fixup/69-package-polygon-rendering.md +54 -0
  209. data/TODO.fixup/70-tagged-values-compartment.md +39 -0
  210. data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
  211. data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
  212. data/TODO.fixup/73-delete-dead-transformations.md +14 -0
  213. data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
  214. data/TODO.fixup/75-visibility-legend-icons.md +23 -0
  215. data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
  216. data/TODO.fixup/77-canvas-frame-margins.md +28 -0
  217. data/TODO.fixup/78-note-element-rendering.md +30 -0
  218. data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
  219. data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
  220. data/TODO.fixup/81-figure-parity-current-state.md +63 -0
  221. data/config/qea_schema.yml +356 -0
  222. data/config/stereotype_colors.yml +15 -0
  223. data/config/themes/119.yml +98 -0
  224. data/config/themes/default.yml +14 -0
  225. data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
  226. data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
  227. data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
  228. data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
  229. data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
  230. data/examples/exports/UmlModel_template/model.xml +23 -0
  231. data/examples/exports/basic/UML_EA.DTD +6856 -0
  232. data/examples/exports/basic/model.xml +8039 -0
  233. data/examples/exports/simple/UML_EA.DTD +6856 -0
  234. data/examples/exports/simple/model.xml +585 -0
  235. data/examples/exports/simple_example/UML_EA.DTD +6856 -0
  236. data/examples/exports/simple_example/model.xml +23 -0
  237. data/examples/exports/test/UML_EA.DTD +6856 -0
  238. data/examples/exports/test/model.xml +1638 -0
  239. data/examples/qea/basic.qea +0 -0
  240. data/frontend/README.md +51 -0
  241. data/frontend/dist/app.iife.js +24 -0
  242. data/frontend/dist/style.css +1 -0
  243. data/frontend/index.html +26 -0
  244. data/frontend/package-lock.json +2359 -0
  245. data/frontend/package.json +26 -0
  246. data/frontend/src/App.vue +59 -0
  247. data/frontend/src/app.ts +8 -0
  248. data/frontend/src/components/AppHeader.vue +127 -0
  249. data/frontend/src/components/AppSidebar.vue +119 -0
  250. data/frontend/src/components/ClassDetails.vue +247 -0
  251. data/frontend/src/components/DiagramView.vue +79 -0
  252. data/frontend/src/components/PackageDetails.vue +92 -0
  253. data/frontend/src/components/PackageTreeNode.vue +64 -0
  254. data/frontend/src/components/SearchResults.vue +48 -0
  255. data/frontend/src/components/WelcomeView.vue +87 -0
  256. data/frontend/src/shims-vue.d.ts +5 -0
  257. data/frontend/src/stores/dataStore.ts +79 -0
  258. data/frontend/src/stores/uiStore.ts +167 -0
  259. data/frontend/src/styles/main.css +1566 -0
  260. data/frontend/src/types.ts +221 -0
  261. data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
  262. data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
  263. data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
  264. data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
  265. data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
  266. data/frontend/tests/e2e/render.spec.ts +188 -0
  267. data/frontend/tsconfig.json +20 -0
  268. data/frontend/vite.config.ts +26 -0
  269. data/frontend/vitest.config.ts +8 -0
  270. data/lib/ea/cli/app.rb +62 -1
  271. data/lib/ea/cli/command/diagrams.rb +37 -28
  272. data/lib/ea/cli/command/diff.rb +46 -0
  273. data/lib/ea/cli/command/export.rb +80 -0
  274. data/lib/ea/cli/command/info.rb +75 -0
  275. data/lib/ea/cli/command/lint.rb +48 -0
  276. data/lib/ea/cli/command/mdg.rb +98 -0
  277. data/lib/ea/cli/command/query.rb +34 -0
  278. data/lib/ea/cli/command/render.rb +135 -0
  279. data/lib/ea/cli/command/svg.rb +43 -6
  280. data/lib/ea/cli/command.rb +7 -0
  281. data/lib/ea/diagram/display_config.rb +184 -0
  282. data/lib/ea/diagram.rb +4 -41
  283. data/lib/ea/diff/change.rb +30 -0
  284. data/lib/ea/diff/comparator.rb +82 -0
  285. data/lib/ea/diff/html_reporter.rb +91 -0
  286. data/lib/ea/diff.rb +15 -0
  287. data/lib/ea/export/json/generator.rb +42 -0
  288. data/lib/ea/export/json.rb +12 -0
  289. data/lib/ea/export/json_schema/generator.rb +77 -0
  290. data/lib/ea/export/json_schema.rb +12 -0
  291. data/lib/ea/export/plantuml/generator.rb +73 -0
  292. data/lib/ea/export/plantuml.rb +12 -0
  293. data/lib/ea/export/xmi/generator.rb +77 -0
  294. data/lib/ea/export/xmi.rb +11 -0
  295. data/lib/ea/export/xsd/class_mapping.rb +65 -0
  296. data/lib/ea/export/xsd/generator.rb +142 -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 +14 -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 +35 -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 +53 -1
  333. data/lib/ea/model/diagram_element.rb +44 -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/query/builder.rb +108 -0
  378. data/lib/ea/query.rb +9 -0
  379. data/lib/ea/render/image_converter.rb +101 -0
  380. data/lib/ea/render.rb +10 -0
  381. data/lib/ea/shapescript/parser.rb +208 -0
  382. data/lib/ea/shapescript/renderer.rb +74 -0
  383. data/lib/ea/shapescript/shape.rb +34 -0
  384. data/lib/ea/shapescript.rb +24 -0
  385. data/lib/ea/sources/qea/adapter.rb +22 -5
  386. data/lib/ea/sources/qea/classifier_builder.rb +184 -7
  387. data/lib/ea/sources/qea/diagram_builder.rb +352 -24
  388. data/lib/ea/sources/qea/id_normalizer.rb +16 -1
  389. data/lib/ea/sources/qea/instance_builder.rb +113 -0
  390. data/lib/ea/sources/qea/legend_builder.rb +137 -0
  391. data/lib/ea/sources/qea/note_builder.rb +58 -0
  392. data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
  393. data/lib/ea/sources/qea/operation_builder.rb +1 -0
  394. data/lib/ea/sources/qea/package_builder.rb +16 -0
  395. data/lib/ea/sources/qea/relationship_builder.rb +21 -5
  396. data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
  397. data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
  398. data/lib/ea/sources/qea/xref/parser.rb +150 -0
  399. data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
  400. data/lib/ea/sources/qea/xref/record.rb +41 -0
  401. data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
  402. data/lib/ea/sources/qea/xref.rb +27 -0
  403. data/lib/ea/sources/qea.rb +4 -0
  404. data/lib/ea/sources/xmi/adapter.rb +80 -2
  405. data/lib/ea/sources/xmi/annotation_builder.rb +1 -1
  406. data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
  407. data/lib/ea/sources/xmi/diagram_builder.rb +242 -45
  408. data/lib/ea/sources/xmi/extension_elements.rb +74 -0
  409. data/lib/ea/sources/xmi/extension_geometry_parser.rb +124 -0
  410. data/lib/ea/sources/xmi/extension_style_parser.rb +91 -0
  411. data/lib/ea/sources/xmi/note_builder.rb +46 -0
  412. data/lib/ea/sources/xmi/property_builder.rb +9 -0
  413. data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
  414. data/lib/ea/sources/xmi/tag_builder.rb +45 -0
  415. data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
  416. data/lib/ea/sources/xmi.rb +7 -0
  417. data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
  418. data/lib/ea/spa/output/single_file_strategy.rb +8 -2
  419. data/lib/ea/spa/output/strategy.rb +34 -0
  420. data/lib/ea/svg/connector_router.rb +134 -0
  421. data/lib/ea/svg/ea_emitter/background.rb +15 -0
  422. data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
  423. data/lib/ea/svg/ea_emitter/canvas.rb +88 -0
  424. data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
  425. data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
  426. data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
  427. data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
  428. data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
  429. data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
  430. data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
  431. data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
  432. data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
  433. data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
  434. data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
  435. data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
  436. data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
  437. data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
  438. data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
  439. data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
  440. data/lib/ea/svg/ea_emitter/connectors.rb +84 -0
  441. data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
  442. data/lib/ea/svg/ea_emitter/document.rb +35 -0
  443. data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
  444. data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
  445. data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
  446. data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
  447. data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
  448. data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
  449. data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
  450. data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
  451. data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
  452. data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
  453. data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
  454. data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
  455. data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
  456. data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
  457. data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
  458. data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
  459. data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
  460. data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
  461. data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
  462. data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
  463. data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
  464. data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
  465. data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
  466. data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
  467. data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
  468. data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
  469. data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
  470. data/lib/ea/svg/ea_emitter/element.rb +37 -0
  471. data/lib/ea/svg/ea_emitter/elements.rb +357 -0
  472. data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
  473. data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
  474. data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
  475. data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
  476. data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
  477. data/lib/ea/svg/ea_emitter/label.rb +23 -0
  478. data/lib/ea/svg/ea_emitter/labels.rb +130 -0
  479. data/lib/ea/svg/ea_emitter/layer.rb +20 -0
  480. data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
  481. data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
  482. data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
  483. data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
  484. data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
  485. data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
  486. data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
  487. data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
  488. data/lib/ea/svg/ea_emitter/marker.rb +37 -0
  489. data/lib/ea/svg/ea_emitter/markers.rb +404 -0
  490. data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
  491. data/lib/ea/svg/ea_emitter/style.rb +15 -0
  492. data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
  493. data/lib/ea/svg/ea_emitter.rb +51 -0
  494. data/lib/ea/svg/parity/checker.rb +105 -0
  495. data/lib/ea/svg/parity/source.rb +59 -0
  496. data/lib/ea/svg/parity/suite.rb +113 -0
  497. data/lib/ea/svg/parity.rb +14 -0
  498. data/lib/ea/svg/stereotype_color_resolver.rb +50 -0
  499. data/lib/ea/svg.rb +4 -15
  500. data/lib/ea/theme/definition.rb +176 -0
  501. data/lib/ea/theme/loader.rb +125 -0
  502. data/lib/ea/theme/registry.rb +96 -0
  503. data/lib/ea/theme.rb +37 -0
  504. data/lib/ea/transformations.rb +5 -88
  505. data/lib/ea/version.rb +4 -1
  506. data/lib/ea.rb +14 -4
  507. data/lib/tasks/svg_bench.rake +87 -0
  508. data/lutaml-uml-0.5.1.gem +0 -0
  509. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
  510. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
  511. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
  512. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
  513. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
  514. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
  515. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
  516. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
  517. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
  518. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
  519. data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
  520. metadata +473 -26
  521. data/lib/ea/diagram/configuration.rb +0 -379
  522. data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
  523. data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
  524. data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
  525. data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
  526. data/lib/ea/diagram/element_renderers.rb +0 -43
  527. data/lib/ea/diagram/extractor.rb +0 -566
  528. data/lib/ea/diagram/layout_engine.rb +0 -170
  529. data/lib/ea/diagram/path_builder.rb +0 -202
  530. data/lib/ea/diagram/style_parser.rb +0 -42
  531. data/lib/ea/diagram/style_resolver.rb +0 -291
  532. data/lib/ea/diagram/svg_renderer.rb +0 -274
  533. data/lib/ea/diagram/util.rb +0 -73
  534. data/lib/ea/svg/bounds_calculator.rb +0 -74
  535. data/lib/ea/svg/connector_path.rb +0 -138
  536. data/lib/ea/svg/element_box.rb +0 -256
  537. data/lib/ea/svg/renderer.rb +0 -77
  538. data/lib/ea/svg/style_resolver.rb +0 -72
  539. data/lib/ea/transformations/configuration.rb +0 -333
  540. data/lib/ea/transformations/format_registry.rb +0 -366
  541. data/lib/ea/transformations/parsers/base_parser.rb +0 -482
  542. data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
  543. data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
  544. data/lib/ea/transformations/transformation_engine.rb +0 -390
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Diagram
5
+ # Models the behavioral display flags from t_diagram.Style and
6
+ # t_diagram.StyleEx. Controls WHAT is rendered (compartments,
7
+ # visibility levels, notes) — distinct from Theme which controls
8
+ # HOW it looks (colors, fonts, stroke widths).
9
+ #
10
+ # Style (a.k.a. Style1) carries the per-diagram visibility
11
+ # toggles set via the "Features" panel:
12
+ #
13
+ # HideAtts=1 → hide attribute compartment
14
+ # HideOps=1 → hide operation compartment
15
+ # HideStereo=1 → hide stereotype labels
16
+ #
17
+ # StyleEx carries extended flags including the theme identifier
18
+ # and notes/labels visibility:
19
+ #
20
+ # Theme=:119 → theme id (consumed by Ea::Theme::Registry)
21
+ # SuppressFOC=1 → suppress foreign object content (images, OLE)
22
+ # AttPub=1 → show public attributes
23
+ # AttPri=1 → show private attributes
24
+ # AttPro=1 → show protected attributes
25
+ # ShowNotes=0 → hide element notes
26
+ # ShowBorder=1 → render diagram frame
27
+ # HideQuals=0 → show qualifier names
28
+ # SuppConnLbls=0 → show connector labels
29
+ #
30
+ # Usage:
31
+ # config = DisplayConfig.from_style(style: diagram.style,
32
+ # style_ex: diagram.style_ex)
33
+ # config.show_attributes? # → false iff Style has HideAtts=1
34
+ #
35
+ class DisplayConfig
36
+ DEFAULT_SHOW_PUBLIC = "1"
37
+ DEFAULT_SHOW_PRIVATE = "1"
38
+ DEFAULT_SHOW_PROTECTED = "1"
39
+ DEFAULT_SHOW_BORDER = "1"
40
+ DEFAULT_SUPPRESS_CONN_LABELS = "0"
41
+ DEFAULT_SHOW_NOTES = "0"
42
+
43
+ attr_reader :style_flags, :style_ex_flags
44
+
45
+ def initialize(style_flags: {}, style_ex_flags: {})
46
+ @style_flags = style_flags
47
+ @style_ex_flags = style_ex_flags
48
+ end
49
+
50
+ # Build a DisplayConfig from the raw Style and StyleEx strings.
51
+ # Both are optional; missing strings produce an empty flag set.
52
+ #
53
+ # @param style [String, nil] t_diagram.Style content
54
+ # @param style_ex [String, nil] t_diagram.StyleEx content
55
+ # @return [DisplayConfig]
56
+ def self.from_style(style:, style_ex:)
57
+ new(style_flags: parse_flags(style),
58
+ style_ex_flags: parse_flags(style_ex))
59
+ end
60
+
61
+ # Backwards-compatible single-arg form: treats the argument as
62
+ # StyleEx. New callers should pass both style: and style_ex:.
63
+ def self.from_style_ex(style_ex)
64
+ from_style(style: nil, style_ex: style_ex)
65
+ end
66
+
67
+ # ---- Feature visibility (Style) ----
68
+
69
+ def show_attributes?
70
+ style_flags["HideAtts"] != "1"
71
+ end
72
+
73
+ def show_operations?
74
+ style_flags["HideOps"] != "1"
75
+ end
76
+
77
+ def show_stereotypes?
78
+ style_flags["HideStereo"] != "1"
79
+ end
80
+
81
+ # Tagged values compartment. EA defaults to hiding it; the user
82
+ # explicitly opts in via Style1 ShowTags=1.
83
+ def show_tagged_values?
84
+ style_flags["ShowTags"] == "1"
85
+ end
86
+
87
+ # Extended stereotype labels (e.g., profile-specific stereotypes
88
+ # beyond UML's standard set). EA defaults to showing them.
89
+ def show_extended_stereotypes?
90
+ style_flags["HideEStereo"] != "1"
91
+ end
92
+
93
+ # Sequence numbers on elements. EA defaults to hiding them.
94
+ def show_sequence_numbers?
95
+ style_flags["ShowSN"] == "1"
96
+ end
97
+
98
+ # Operation parameter type list. When false, EA shows `op()`
99
+ # instead of `op(name: Type)`. Defaults to true.
100
+ def show_operation_parameters?
101
+ style_flags["OpParams"] != "0"
102
+ end
103
+
104
+ # Element Alias instead of Name in the header. Defaults to false
105
+ # — most diagrams show the Name.
106
+ def use_alias?
107
+ style_flags["UseAlias"] == "1"
108
+ end
109
+
110
+ # Connector role/name labels. EA defaults to showing them.
111
+ def show_connector_names?
112
+ style_flags["SuppCN"] != "1"
113
+ end
114
+
115
+ # Constraints compartment (OCL invariants). Defaults to false.
116
+ def show_constraints?
117
+ style_flags["ShowCons"] == "1"
118
+ end
119
+
120
+ # Page indicator scaling (Print... → Show Page Breaks).
121
+ def scale_page_indicators?
122
+ style_flags["ScalePI"] == "1"
123
+ end
124
+
125
+ # ---- Attribute visibility levels (StyleEx) ----
126
+
127
+ def show_public_attributes?
128
+ style_ex_flags.fetch("AttPub", DEFAULT_SHOW_PUBLIC) == "1"
129
+ end
130
+
131
+ def show_private_attributes?
132
+ style_ex_flags.fetch("AttPri", DEFAULT_SHOW_PRIVATE) == "1"
133
+ end
134
+
135
+ def show_protected_attributes?
136
+ style_ex_flags.fetch("AttPro", DEFAULT_SHOW_PROTECTED) == "1"
137
+ end
138
+
139
+ # ---- Diagram decorations (StyleEx) ----
140
+
141
+ def show_notes?
142
+ style_ex_flags.fetch("ShowNotes", DEFAULT_SHOW_NOTES) == "1"
143
+ end
144
+
145
+ def show_border?
146
+ style_ex_flags.fetch("ShowBorder", DEFAULT_SHOW_BORDER) == "1"
147
+ end
148
+
149
+ def show_connector_labels?
150
+ style_ex_flags.fetch("SuppConnectorLabels",
151
+ DEFAULT_SUPPRESS_CONN_LABELS) != "1"
152
+ end
153
+
154
+ def hide_qualifiers?
155
+ style_ex_flags["HideQuals"] == "1"
156
+ end
157
+
158
+ def suppress_foreign_object_content?
159
+ style_ex_flags["SuppressFOC"] == "1"
160
+ end
161
+
162
+ # Serialize the union of flags back to a StyleEx-shaped string.
163
+ # Style and StyleEx are merged because EA serializes them as
164
+ # one string when round-tripped through some tools.
165
+ def to_style_ex
166
+ style_flags.merge(style_ex_flags).map { |k, v| "#{k}=#{v}" }.join(";")
167
+ end
168
+
169
+ # ---- private ----
170
+
171
+ def self.parse_flags(raw)
172
+ return {} if raw.nil? || raw.empty?
173
+
174
+ raw.split(";").filter_map do |pair|
175
+ next nil unless pair.include?("=")
176
+
177
+ key, value = pair.split("=", 2)
178
+ [key, value.to_s] if key && !key.empty?
179
+ end.to_h
180
+ end
181
+ private_class_method :parse_flags
182
+ end
183
+ end
184
+ end
data/lib/ea/diagram.rb CHANGED
@@ -1,47 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ea
4
+ # Ea::Diagram holds display-layer helpers shared between sources
5
+ # and emitters. Distinct from Ea::Svg::EaEmitter which produces
6
+ # the standalone SVG output.
4
7
  module Diagram
5
- autoload :SvgRenderer, "ea/diagram/svg_renderer"
6
- autoload :LayoutEngine, "ea/diagram/layout_engine"
7
- autoload :StyleParser, "ea/diagram/style_parser"
8
- autoload :PathBuilder, "ea/diagram/path_builder"
9
- autoload :StyleResolver, "ea/diagram/style_resolver"
10
- autoload :Configuration, "ea/diagram/configuration"
11
- autoload :Util, "ea/diagram/util"
12
- autoload :Extractor, "ea/diagram/extractor"
13
- autoload :ElementRenderers, "ea/diagram/element_renderers"
14
-
15
- class DiagramRenderer
16
- attr_reader :diagram_data, :layout_engine, :style_parser
17
-
18
- def initialize(diagram_data)
19
- @diagram_data = diagram_data
20
- @layout_engine = LayoutEngine.new
21
- @style_parser = StyleParser.new
22
- end
23
-
24
- def render_svg(options = {})
25
- svg_renderer = SvgRenderer.new(self, options)
26
- svg_renderer.render
27
- end
28
-
29
- def bounds
30
- layout_engine.calculate_bounds(diagram_data)
31
- end
32
-
33
- def elements
34
- diagram_data[:elements] || []
35
- end
36
-
37
- def connectors
38
- diagram_data[:connectors] || []
39
- end
40
- end
41
-
42
- def self.render(diagram_data, options = {})
43
- renderer = DiagramRenderer.new(diagram_data)
44
- renderer.render_svg(options)
45
- end
8
+ autoload :DisplayConfig, "ea/diagram/display_config"
46
9
  end
47
10
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Diff
5
+ # One structural change between two EA databases.
6
+ #
7
+ # `change` is one of: :added, :removed, :renamed, :modified.
8
+ # `kind` is the collection name (e.g. :packages, :classes).
9
+ # `id` is the entity's primary key (string or int).
10
+ # `name` is a human-readable label for the entity.
11
+ Change = Struct.new(:change, :kind, :id, :name, :details,
12
+ keyword_init: true) do
13
+ def added?
14
+ change == :added
15
+ end
16
+
17
+ def removed?
18
+ change == :removed
19
+ end
20
+
21
+ def renamed?
22
+ change == :renamed
23
+ end
24
+
25
+ def modified?
26
+ change == :modified
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Diff
5
+ # Compares two Ea::Qea::Database instances and produces a list of
6
+ # structural changes. Identity is keyed by primary-key value within
7
+ # each collection; renaming surfaces as :removed + :added unless the
8
+ # name change happens with the same PK (then it's :renamed).
9
+ #
10
+ # OCP: new entity types are added by registering a comparator entry
11
+ # in COLLECTIONS, not by modifying this class.
12
+ class Comparator
13
+ attr_reader :old_db, :new_db, :differences
14
+
15
+ # Each entry maps a collection name to the attribute used as the
16
+ # human-readable label. Add new collections here without touching
17
+ # the diff algorithm.
18
+ COLLECTIONS = {
19
+ packages: :name,
20
+ objects: :name,
21
+ attributes: :name,
22
+ operations: :name,
23
+ connectors: :name,
24
+ diagrams: :name
25
+ }.freeze
26
+
27
+ def initialize(old_db, new_db)
28
+ @old_db = old_db
29
+ @new_db = new_db
30
+ @differences = []
31
+ compare_all
32
+ end
33
+
34
+ def identical?
35
+ @differences.empty?
36
+ end
37
+
38
+ private
39
+
40
+ def compare_all
41
+ COLLECTIONS.each do |collection, label_attr|
42
+ compare_collection(collection, label_attr)
43
+ end
44
+ end
45
+
46
+ def compare_collection(name, label_attr)
47
+ old_records = index_by_id(old_db, name, label_attr)
48
+ new_records = index_by_id(new_db, name, label_attr)
49
+
50
+ old_records.each do |id, old_entry|
51
+ new_entry = new_records.delete(id)
52
+ if new_entry.nil?
53
+ add(:removed, name, id, old_entry[:label])
54
+ elsif new_entry[:label] != old_entry[:label]
55
+ add(:renamed, name, id, "#{old_entry[:label]} → #{new_entry[:label]}")
56
+ end
57
+ end
58
+
59
+ new_records.each_value do |entry|
60
+ add(:added, name, entry[:id], entry[:label])
61
+ end
62
+ end
63
+
64
+ def index_by_id(db, collection_name, label_attr)
65
+ records = db.collections[collection_name] || []
66
+ records.each_with_object({}) do |record, acc|
67
+ id = record.public_send(record.class.primary_key_column)
68
+ next if id.nil?
69
+
70
+ acc[id] = {
71
+ id: id,
72
+ label: record.public_send(label_attr).to_s
73
+ }
74
+ end
75
+ end
76
+
77
+ def add(change, kind, id, name)
78
+ @differences << Change.new(change: change, kind: kind, id: id, name: name)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Diff
5
+ # Renders a Comparator's differences as an HTML report with
6
+ # color-coded rows. Useful for CI artifacts and PR review.
7
+ class HtmlReporter
8
+ attr_reader :comparator
9
+
10
+ def initialize(comparator)
11
+ @comparator = comparator
12
+ end
13
+
14
+ # @return [String] standalone HTML document
15
+ def render
16
+ <<~HTML
17
+ <!DOCTYPE html>
18
+ <html lang="en">
19
+ <head>
20
+ <meta charset="utf-8">
21
+ <title>EA Diff Report</title>
22
+ <style>#{css}</style>
23
+ </head>
24
+ <body>
25
+ <h1>EA Diff Report</h1>
26
+ #{summary_section}
27
+ #{table_section}
28
+ </body>
29
+ </html>
30
+ HTML
31
+ end
32
+
33
+ private
34
+
35
+ def summary_section
36
+ added = comparator.differences.count(&:added?)
37
+ removed = comparator.differences.count(&:removed?)
38
+ renamed = comparator.differences.count(&:renamed?)
39
+ <<~HTML
40
+ <section class="summary">
41
+ <span class="added">+#{added} added</span>
42
+ <span class="removed">-#{removed} removed</span>
43
+ <span class="renamed">~#{renamed} renamed</span>
44
+ </section>
45
+ HTML
46
+ end
47
+
48
+ def table_section
49
+ rows = comparator.differences.map do |diff|
50
+ %(<tr class="#{diff.change}"><td>#{escape(diff.change)}</td>" \
51
+ "<td>#{escape(diff.kind)}</td><td>#{escape(diff.id)}</td>" \
52
+ "<td>#{escape(diff.name)}</td></tr>")
53
+ end.join("\n")
54
+ <<~HTML
55
+ <table>
56
+ <thead><tr><th>Change</th><th>Kind</th><th>ID</th><th>Name</th></tr></thead>
57
+ <tbody>
58
+ #{rows}
59
+ </tbody>
60
+ </table>
61
+ HTML
62
+ end
63
+
64
+ def css
65
+ <<~CSS
66
+ body { font-family: -apple-system, system-ui, sans-serif; margin: 2em; }
67
+ table { border-collapse: collapse; width: 100%; }
68
+ th, td { border: 1px solid #ddd; padding: 0.5em; text-align: left; }
69
+ tr.added { background: #e6ffe6; }
70
+ tr.removed { background: #ffe6e6; }
71
+ tr.renamed { background: #fff9e6; }
72
+ .summary { margin: 1em 0; }
73
+ .summary span { padding: 0.25em 0.5em; margin-right: 0.5em; border-radius: 3px; }
74
+ .added { background: #d4edda; color: #155724; }
75
+ .removed { background: #f8d7da; color: #721c24; }
76
+ .renamed { background: #fff3cd; color: #856404; }
77
+ CSS
78
+ end
79
+
80
+ def escape(text)
81
+ return "" if text.nil?
82
+
83
+ text.to_s
84
+ .gsub("&", "&amp;")
85
+ .gsub("<", "&lt;")
86
+ .gsub(">", "&gt;")
87
+ .gsub('"', "&quot;")
88
+ end
89
+ end
90
+ end
91
+ end
data/lib/ea/diff.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ # Structural diff between two EA databases (or pre-parsed models).
5
+ # Returns a list of `Diff::Change` records describing what was added,
6
+ # removed, or modified.
7
+ #
8
+ # Compares by entity identity (table + primary key) and surfaces
9
+ # human-readable change descriptions.
10
+ module Diff
11
+ autoload :Change, "ea/diff/change"
12
+ autoload :Comparator, "ea/diff/comparator"
13
+ autoload :HtmlReporter, "ea/diff/html_reporter"
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Ea
6
+ module Export
7
+ module Json
8
+ # Generates a JSON snapshot of a parsed QEA model.
9
+ # Walks each collection and emits array entries with the row's
10
+ # lutaml-model hash representation.
11
+ class Generator
12
+ def self.call(model, **_opts)
13
+ new(model).call
14
+ end
15
+
16
+ attr_reader :model
17
+
18
+ def initialize(model)
19
+ @model = model
20
+ end
21
+
22
+ def call
23
+ JSON.pretty_generate(document_hash)
24
+ end
25
+
26
+ private
27
+
28
+ def document_hash
29
+ model.collections.each_with_object({}) do |(name, records), acc|
30
+ acc[name] = records.map { |r| record_hash(r) }
31
+ end
32
+ end
33
+
34
+ def record_hash(record)
35
+ hash = record.to_hash
36
+ hash["record_type"] = record.class.name.split("::").last
37
+ hash
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Export
5
+ # JSON serialization namespace. Produces a JSON document of the
6
+ # model's collections, suitable for downstream tools (web apps,
7
+ # diff tools, etc.).
8
+ module Json
9
+ autoload :Generator, "ea/export/json/generator"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Ea
6
+ module Export
7
+ module JsonSchema
8
+ # Generates a JSON Schema (draft 2020-12) document from a
9
+ # parsed QEA model. Each UML Class becomes a `$defs` entry
10
+ # with `properties` derived from its attributes.
11
+ class Generator
12
+ SCHEMA_URI = "https://json-schema.org/draft/2020-12/schema".freeze
13
+
14
+ # EA primitive → JSON Schema type
15
+ TYPE_MAP = {
16
+ "int" => "integer", "Integer" => "integer",
17
+ "long" => "integer", "Long" => "integer",
18
+ "double" => "number", "Double" => "number",
19
+ "float" => "number", "Float" => "number",
20
+ "boolean" => "boolean", "Boolean" => "boolean",
21
+ "String" => "string", "string" => "string",
22
+ "char" => "string", "Character" => "string",
23
+ "Date" => "string", "DateTime" => "string"
24
+ }.freeze
25
+
26
+ def self.call(model, **_opts)
27
+ new(model).call
28
+ end
29
+
30
+ attr_reader :model
31
+
32
+ def initialize(model)
33
+ @model = model
34
+ end
35
+
36
+ def call
37
+ classes = (model.collections[:objects] || [])
38
+ .select { |o| o.object_type == "Class" }
39
+ defs = classes.each_with_object({}) do |klass, acc|
40
+ acc[klass.name] = class_schema(klass)
41
+ end
42
+
43
+ {
44
+ "$schema" => SCHEMA_URI,
45
+ "$id" => "https://example.com/schema.json",
46
+ "type" => "object",
47
+ "$defs" => defs
48
+ }.to_json
49
+ end
50
+
51
+ private
52
+
53
+ def class_schema(klass)
54
+ attrs = attribute_map[klass.object_id] || []
55
+ {
56
+ "type" => "object",
57
+ "title" => klass.name,
58
+ "properties" => attrs.each_with_object({}) do |a, props|
59
+ props[a.name] = { "type" => json_type(a.type) }
60
+ end
61
+ }
62
+ end
63
+
64
+ def json_type(ea_type)
65
+ TYPE_MAP[ea_type] || "string"
66
+ end
67
+
68
+ def attribute_map
69
+ @attribute_map ||= begin
70
+ attrs = model.collections[:attributes] || []
71
+ attrs.group_by(&:object_id)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Ea
6
+ module Export
7
+ # JSON Schema (draft 2020-12) export namespace.
8
+ module JsonSchema
9
+ autoload :Generator, "ea/export/json_schema/generator"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Export
5
+ module PlantUml
6
+ # Generates PlantUML class diagram text from a parsed QEA model.
7
+ #
8
+ # Example output:
9
+ # @startuml
10
+ # class Person {
11
+ # +name: String
12
+ # +age: Integer
13
+ # }
14
+ # Person "1" --> "0..*" Address : lives_at
15
+ # @enduml
16
+ class Generator
17
+ def self.call(model, **_opts)
18
+ new(model).call
19
+ end
20
+
21
+ attr_reader :model
22
+
23
+ def initialize(model)
24
+ @model = model
25
+ end
26
+
27
+ def call
28
+ lines = ["@startuml"]
29
+ lines.concat(class_lines)
30
+ lines.concat(connector_lines)
31
+ lines << "@enduml"
32
+ lines.join("\n") + "\n"
33
+ end
34
+
35
+ private
36
+
37
+ def class_lines
38
+ classes.map do |klass|
39
+ attrs = class_attributes(klass)
40
+ body = attrs.map { |a| " +#{a.name}: #{a.type || 'String'}" }
41
+ ["class #{klass.name} {", *body, "}"].join("\n")
42
+ end
43
+ end
44
+
45
+ def connector_lines
46
+ (model.collections[:connectors] || []).map do |conn|
47
+ source_obj = find_object(conn.start_object_id)
48
+ target_obj = find_object(conn.end_object_id)
49
+ next nil unless source_obj && target_obj
50
+
51
+ label = conn.name ? " : #{conn.name}" : ""
52
+ %Q{#{source_obj.name} --> #{target_obj.name}#{label}}
53
+ end.compact
54
+ end
55
+
56
+ def classes
57
+ (model.collections[:objects] || [])
58
+ .select { |o| o.object_type == "Class" }
59
+ end
60
+
61
+ def class_attributes(klass)
62
+ attrs = model.collections[:attributes] || []
63
+ attrs.select { |a| a.object_id == klass.object_id }
64
+ end
65
+
66
+ def find_object(object_id)
67
+ (model.collections[:objects] || [])
68
+ .find { |o| o.object_id == object_id }
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ea
4
+ module Export
5
+ # PlantUML text-format exporter. Produces a `.puml` file
6
+ # documenting the model's classes, attributes, and relationships
7
+ # in PlantUML syntax (rendered by plantuml.com/plantuml).
8
+ module PlantUml
9
+ autoload :Generator, "ea/export/plantuml/generator"
10
+ end
11
+ end
12
+ end