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.
- checksums.yaml +4 -4
- data/Rakefile +3 -0
- data/TODO.complete/01-t-xref-parsing.md +91 -0
- data/TODO.complete/02-per-label-geometry.md +50 -0
- data/TODO.complete/03-object-properties-constraints.md +57 -0
- data/TODO.complete/04-operation-params.md +37 -0
- data/TODO.complete/05-pdata-flag-matrix.md +52 -0
- data/TODO.complete/06-emf-image-rendering.md +34 -0
- data/TODO.complete/07-auxiliary-tables.md +47 -0
- data/TODO.complete/10-mdg-stereotype-registry.md +40 -0
- data/TODO.complete/11-gml-xsd-generation.md +42 -0
- data/TODO.complete/13-shapescript-interpreter.md +28 -0
- data/TODO.complete/20-cli-diff.md +46 -0
- data/TODO.complete/21-cli-render.md +26 -0
- data/TODO.complete/22-cli-export.md +29 -0
- data/TODO.complete/23-cli-mdg.md +23 -0
- data/TODO.complete/30-headerlines-ocp-refactor.md +72 -0
- data/TODO.complete/31-public-send-cleanup.md +61 -0
- data/TODO.complete/32-spec-coverage.md +33 -0
- data/TODO.complete/33-blocked-parity-gaps.md +41 -0
- data/TODO.complete/36-stereotype-icon-wiring.md +32 -0
- data/TODO.complete/37-cli-lint.md +32 -0
- data/TODO.complete/38-cli-query.md +26 -0
- data/TODO.complete/39-cli-info.md +23 -0
- data/TODO.complete/40-ocl-evaluator.md +31 -0
- data/TODO.complete/41-round-trip-spec.md +18 -0
- data/TODO.complete/42-html-diff-report.md +18 -0
- data/TODO.complete/43-json-schema-export.md +20 -0
- data/TODO.complete/44-remaining-qea-tables.md +40 -0
- data/TODO.complete/45-shapescript-extensions.md +25 -0
- data/TODO.complete/46-xsd-consolidation.md +20 -0
- data/TODO.complete/47-headerlines-legacy-removal.md +20 -0
- data/TODO.complete/STATUS.md +109 -0
- data/TODO.diagrams/01-svg-measurement-harness.md +31 -0
- data/TODO.diagrams/01-xmi-extension-elements-parsing.md +67 -0
- data/TODO.diagrams/02-diagram-element-rich-model.md +61 -0
- data/TODO.diagrams/02-polygon-over-rendering.md +29 -0
- data/TODO.diagrams/03-ea-style-svg-emitter.md +70 -0
- data/TODO.diagrams/03-text-over-rendering.md +30 -0
- data/TODO.diagrams/04-connector-routing-from-soid-eoid.md +55 -0
- data/TODO.diagrams/04-rect-under-rendering.md +33 -0
- data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
- data/TODO.diagrams/05-marker-rendering-per-relationship-type.md +49 -0
- data/TODO.diagrams/06-connector-labels.md +49 -0
- data/TODO.diagrams/06-group-layering-parity.md +39 -0
- data/TODO.diagrams/07-canvas-size-and-viewbox.md +39 -0
- data/TODO.diagrams/07-text-content-fidelity.md +65 -0
- data/TODO.diagrams/08-qea-direct-pipeline.md +46 -0
- data/TODO.diagrams/08-visual-regression-harness.md +34 -0
- data/TODO.diagrams/09-cli-render-all-diagrams.md +25 -0
- data/TODO.diagrams/10-stereotype-color-config.md +29 -0
- data/TODO.diagrams/11-elkrb-auto-layout-integration.md +53 -0
- data/TODO.diagrams/12-connector-labels.md +40 -0
- data/TODO.diagrams/12-per-entity-svg-layer-ordering.md +24 -0
- data/TODO.diagrams/13-marker-polygon-vs-path-dispatch.md +20 -0
- data/TODO.diagrams/13-per-text-type-font-sizes.md +33 -0
- data/TODO.diagrams/14-center-header-text.md +33 -0
- data/TODO.diagrams/14-filter-diagram-frame-elements.md +18 -0
- data/TODO.diagrams/15-deep-dead-code-audit.md +47 -0
- data/TODO.diagrams/15-per-element-font-from-style.md +24 -0
- data/TODO.diagrams/16-canvas-marker-extent.md +30 -0
- data/TODO.diagrams/16-document-remaining-parity-gaps.md +91 -0
- data/TODO.diagrams/17-italic-abstract-classes.md +28 -0
- data/TODO.diagrams/17-remaining-parity-gaps.md +90 -0
- data/TODO.diagrams/18-canvas-from-image-bounds.md +20 -0
- data/TODO.diagrams/18-property-lookup-index.md +42 -0
- data/TODO.diagrams/19-connector-sx-sy-routing.md +27 -0
- data/TODO.diagrams/19-replace-respond-to-with-is-a.md +31 -0
- data/TODO.diagrams/20-split-labels-emitter.md +56 -0
- data/TODO.diagrams/20-visibility-glyph-font-encoding.md +27 -0
- data/TODO.diagrams/21-aggregation-navigability-arrow.md +21 -0
- data/TODO.diagrams/21-auto-generated-legend-block.md +65 -0
- data/TODO.diagrams/22-ghost-element-discriminator.md +57 -0
- data/TODO.diagrams/22-style-based-path-grouping.md +28 -0
- data/TODO.diagrams/23-marker-polygon-deduplication.md +47 -0
- data/TODO.diagrams/23-multiplicity-label-positioning.md +29 -0
- data/TODO.diagrams/24-marker-anchor-structural.md +35 -0
- data/TODO.diagrams/24-track-marker-anchors-structurally.md +66 -0
- data/TODO.diagrams/24-truncate-properties-to-fit-box.md +24 -0
- data/TODO.diagrams/26-phantom-general-parent-rendering.md +59 -0
- data/TODO.diagrams/27-path-grouping-mode-detection.md +43 -0
- data/TODO.diagrams/28-architecture-cleanup-batch.md +47 -0
- data/TODO.diagrams/30-decompose-elements-groups-for.md +52 -0
- data/TODO.diagrams/32-examples-coverage-batch.md +78 -0
- data/TODO.diagrams/36-instance-specification-model.md +42 -0
- data/TODO.diagrams/37-element-icon-decorations.md +41 -0
- data/TODO.diagrams/38-html-note-and-receptions.md +32 -0
- data/TODO.diagrams/39-property-stereotype-discriminator.md +40 -0
- data/TODO.diagrams/40-standalone-1-discriminator.md +38 -0
- data/TODO.diagrams/41-xmi-to-svg-pipeline.md +113 -0
- data/TODO.diagrams/42-close-all-parity-deltas.md +69 -0
- data/TODO.diagrams/43-marker-deduplication-strategy.md +54 -0
- data/TODO.diagrams/44-element-icon-decorations.md +34 -0
- data/TODO.diagrams/45-phantom-parent-class-boxes.md +40 -0
- data/TODO.diagrams/46-user-drawn-legend-swatches.md +44 -0
- data/TODO.diagrams/47-attribute-line-fidelity.md +72 -0
- data/TODO.diagrams/48-spec-coverage-critical-emitter-components.md +45 -0
- data/TODO.diagrams/49-spec-coverage-orchestrators.md +25 -0
- data/TODO.diagrams/50-examples-parity.md +85 -0
- data/TODO.diagrams/51-property-oy-gap-and-remaining-gaps.md +48 -0
- data/TODO.diagrams/52-marker-registration-architecture.md +89 -0
- data/TODO.diagrams/53-remaining-example-gaps.md +86 -0
- data/TODO.diagrams/54-display-name-nested-classes.md +40 -0
- data/TODO.diagrams/55-visibility-icon-discriminator.md +58 -0
- data/TODO.diagrams/56-package-contents-rendering.md +148 -0
- data/TODO.diagrams/57-instance-specification-model.md +100 -0
- data/TODO.diagrams/58-domain-model-note-text.md +67 -0
- data/TODO.diagrams/59-classes-arrow-discriminator.md +57 -0
- data/TODO.diagrams/60-testschema-association-marker.md +40 -0
- data/TODO.diagrams/61-legend-block-rendering.md +55 -0
- data/TODO.diagrams/61-plateau-parity-gaps.md +59 -0
- data/TODO.diagrams/62-ghost-element-rendering.md +56 -0
- data/TODO.diagrams/63-qualified-name-wrap.md +36 -0
- data/TODO.diagrams/64-property-stereotype-labels.md +22 -0
- data/TODO.diagrams/65-path-coordinate-frame.md +62 -0
- data/TODO.diagrams/67-path-coordinate-frame.md +62 -0
- data/TODO.diagrams/68-inherited-attributes.md +65 -0
- data/TODO.diagrams/69-package-anchor-conditional.md +29 -0
- data/TODO.diagrams/70-mdg-technology-support.md +68 -0
- data/TODO.diagrams/71-off-canvas-parent-ghost.md +45 -0
- data/TODO.diagrams/72-basic-attr-divider-paths.md +39 -0
- data/TODO.diagrams/73-plateau-polygon-gap.md +69 -0
- data/TODO.diagrams/74-plateau-rect-gap.md +22 -0
- data/TODO.diagrams/75-plateau-text-gap.md +39 -0
- data/TODO.diagrams/76-basic-poly-path-gaps.md +41 -0
- data/TODO.diagrams/77-basic-text-overrender.md +40 -0
- data/TODO.diagrams/78-headerlines-ocp-refactor.md +65 -0
- data/TODO.diagrams/79-architecture-backlog.md +65 -0
- data/TODO.diagrams/80-basic-triangle-polygons.md +51 -0
- data/TODO.diagrams/81-plateau-path-overrender.md +53 -0
- data/TODO.diagrams/82-appearance-canvas-offset.md +54 -0
- data/TODO.diagrams/83-3d-diagram-subtitle.md +58 -0
- data/TODO.diagrams/84-canvas-offset-mismatches.md +61 -0
- data/TODO.diagrams/85-phantom-property-overrender.md +95 -0
- data/TODO.diagrams/86-foreign-package-rule.md +62 -0
- data/TODO.diagrams/87-internal-tech-encryption.md +80 -0
- data/TODO.diagrams/EXAMPLES_STATUS.md +88 -0
- data/TODO.diagrams/README.md +69 -0
- data/TODO.diagrams/STATUS.md +73 -0
- data/TODO.fixup/01-default-grouped-paths.md +34 -0
- data/TODO.fixup/02-marker-consolidation-per-connector.md +20 -0
- data/TODO.fixup/03-diagram-font-inference.md +28 -0
- data/TODO.fixup/04-extract-bounds-calculator.md +25 -0
- data/TODO.fixup/05-marker-registry-ocp.md +32 -0
- data/TODO.fixup/06-connector-path-bend-routing.md +28 -0
- data/TODO.fixup/07-edge-attachment-formula.md +22 -0
- data/TODO.fixup/08-visual-diff-harness.md +28 -0
- data/TODO.fixup/09-extract-element-compartments.md +34 -0
- data/TODO.fixup/10-canvas-width-overshoot-fix.md +20 -0
- data/TODO.fixup/11-layer-sequencer-extraction.md +18 -0
- data/TODO.fixup/12-path-style-harmony.md +23 -0
- data/TODO.fixup/13-datatype-stereotype-fallback.md +28 -0
- data/TODO.fixup/14-ea-exe-reverse-engineering-notes.md +56 -0
- data/TODO.fixup/15-enumeration-literal-rendering.md +30 -0
- data/TODO.fixup/16-operation-compartment-rendering.md +42 -0
- data/TODO.fixup/17-path-count-calibration.md +27 -0
- data/TODO.fixup/18-polygon-count-calibration.md +32 -0
- data/TODO.fixup/19-rect-count-undershoot-investigation.md +40 -0
- data/TODO.fixup/20-stereotype-color-from-classifier.md +18 -0
- data/TODO.fixup/21-visibility-filter-for-properties.md +24 -0
- data/TODO.fixup/22-multiplicity-display-rule-calibration.md +25 -0
- data/TODO.fixup/23-diagram-frame-title-element.md +31 -0
- data/TODO.fixup/24-note-element-rendering.md +23 -0
- data/TODO.fixup/25-ea-exe-disassembly-findings.md +177 -0
- data/TODO.fixup/26-svg-renderer-architecture.md +78 -0
- data/TODO.fixup/27-svg-element-emitters-disassembly.md +135 -0
- data/TODO.fixup/28-geometry-parser-identification.md +57 -0
- data/TODO.fixup/29-qea-svg-xmi-triple-comparison.md +185 -0
- data/TODO.fixup/30-theme-system-stub.md +46 -0
- data/TODO.fixup/31-theme-value-object-registry.md +17 -0
- data/TODO.fixup/32-styleex-on-diagram-model.md +22 -0
- data/TODO.fixup/33-text-encoding-decimals-rotation.md +29 -0
- data/TODO.fixup/34-per-type-fill-via-theme.md +18 -0
- data/TODO.fixup/35-stroke-width-per-theme.md +7 -0
- data/TODO.fixup/36-qea-rect-coord-normalization.md +24 -0
- data/TODO.fixup/37-package-shape-rendering.md +22 -0
- data/TODO.fixup/38-note-element-rendering.md +15 -0
- data/TODO.fixup/39-styleex-flag-honoring.md +25 -0
- data/TODO.fixup/40-connector-dashed-lines.md +15 -0
- data/TODO.fixup/41-diagram-frame-showborder-detection.md +23 -0
- data/TODO.fixup/42-textrenderer-centralization.md +10 -0
- data/TODO.fixup/43-colorresolver-unification.md +24 -0
- data/TODO.fixup/44-theme-aware-textrenderer.md +17 -0
- data/TODO.fixup/45-theme-aware-fontresolver.md +22 -0
- data/TODO.fixup/46-style-parameterized-by-theme.md +21 -0
- data/TODO.fixup/47-canvas-frame-inset.md +19 -0
- data/TODO.fixup/48-background-rect-format.md +15 -0
- data/TODO.fixup/49-all-samples-integration-test.md +17 -0
- data/TODO.fixup/50-svg-emitter-architecture-docs.md +33 -0
- data/TODO.fixup/51-promote-theme-to-ea-namespace.md +28 -0
- data/TODO.fixup/52-theme-definition-integrated-fills.md +26 -0
- data/TODO.fixup/53-theme-registry-yaml-loading.md +50 -0
- data/TODO.fixup/54-diagram-theme-api.md +50 -0
- data/TODO.fixup/55-update-eaemitter-to-ea-theme.md +23 -0
- data/TODO.fixup/56-theme-yaml-files.md +65 -0
- data/TODO.fixup/57-theme-specs-and-integration.md +27 -0
- data/TODO.fixup/58-ea-entry-point-theme-autoload.md +20 -0
- data/TODO.fixup/59-thread-theme-through-all-renderers.md +29 -0
- data/TODO.fixup/60-cli-theme-option.md +22 -0
- data/TODO.fixup/61-theme-validation.md +28 -0
- data/TODO.fixup/62-theme-builder-dsl.md +31 -0
- data/TODO.fixup/63-theme-integration-rendering-spec.md +24 -0
- data/TODO.fixup/64-theme-writeback-styleex.md +21 -0
- data/TODO.fixup/65-remove-dead-eaemitter-theme-files.md +30 -0
- data/TODO.fixup/66-styleex-writeback.md +22 -0
- data/TODO.fixup/67-delete-dead-code.md +28 -0
- data/TODO.fixup/68-figure-parity-status.md +82 -0
- data/TODO.fixup/69-package-polygon-rendering.md +54 -0
- data/TODO.fixup/70-tagged-values-compartment.md +39 -0
- data/TODO.fixup/71-auto-detect-theme-from-xmi.md +37 -0
- data/TODO.fixup/72-sample-exports-as-regression-specs.md +37 -0
- data/TODO.fixup/73-delete-dead-transformations.md +14 -0
- data/TODO.fixup/74-delete-dead-diagram-renderers.md +18 -0
- data/TODO.fixup/75-visibility-legend-icons.md +23 -0
- data/TODO.fixup/76-plateau-text-undershoot.md +27 -0
- data/TODO.fixup/77-canvas-frame-margins.md +28 -0
- data/TODO.fixup/78-note-element-rendering.md +30 -0
- data/TODO.fixup/79-operation-compartment-rendering.md +27 -0
- data/TODO.fixup/80-tagged-value-stereotype-visibility.md +37 -0
- data/TODO.fixup/81-figure-parity-current-state.md +63 -0
- data/config/qea_schema.yml +356 -0
- data/config/stereotype_colors.yml +15 -0
- data/config/themes/119.yml +98 -0
- data/config/themes/default.yml +14 -0
- data/examples/exports/20251010_current_plateau_v5/UML_EA.DTD +6856 -0
- data/examples/exports/20251010_current_plateau_v5/model.xml +96709 -0
- data/examples/exports/ArcGISWorkspace_template/UML_EA.DTD +6856 -0
- data/examples/exports/ArcGISWorkspace_template/model.xml +1427 -0
- data/examples/exports/UmlModel_template/UML_EA.DTD +6856 -0
- data/examples/exports/UmlModel_template/model.xml +23 -0
- data/examples/exports/basic/UML_EA.DTD +6856 -0
- data/examples/exports/basic/model.xml +8039 -0
- data/examples/exports/simple/UML_EA.DTD +6856 -0
- data/examples/exports/simple/model.xml +585 -0
- data/examples/exports/simple_example/UML_EA.DTD +6856 -0
- data/examples/exports/simple_example/model.xml +23 -0
- data/examples/exports/test/UML_EA.DTD +6856 -0
- data/examples/exports/test/model.xml +1638 -0
- data/examples/qea/basic.qea +0 -0
- data/frontend/README.md +51 -0
- data/frontend/dist/app.iife.js +24 -0
- data/frontend/dist/style.css +1 -0
- data/frontend/index.html +26 -0
- data/frontend/package-lock.json +2359 -0
- data/frontend/package.json +26 -0
- data/frontend/src/App.vue +59 -0
- data/frontend/src/app.ts +8 -0
- data/frontend/src/components/AppHeader.vue +127 -0
- data/frontend/src/components/AppSidebar.vue +119 -0
- data/frontend/src/components/ClassDetails.vue +247 -0
- data/frontend/src/components/DiagramView.vue +79 -0
- data/frontend/src/components/PackageDetails.vue +92 -0
- data/frontend/src/components/PackageTreeNode.vue +64 -0
- data/frontend/src/components/SearchResults.vue +48 -0
- data/frontend/src/components/WelcomeView.vue +87 -0
- data/frontend/src/shims-vue.d.ts +5 -0
- data/frontend/src/stores/dataStore.ts +79 -0
- data/frontend/src/stores/uiStore.ts +167 -0
- data/frontend/src/styles/main.css +1566 -0
- data/frontend/src/types.ts +221 -0
- data/frontend/tests/e2e/__screenshots__/new-dark-mode.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-package-details.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-search-modal.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-sidebar-collapsed.png +0 -0
- data/frontend/tests/e2e/__screenshots__/new-welcome.png +0 -0
- data/frontend/tests/e2e/render.spec.ts +188 -0
- data/frontend/tsconfig.json +20 -0
- data/frontend/vite.config.ts +26 -0
- data/frontend/vitest.config.ts +8 -0
- data/lib/ea/cli/app.rb +62 -1
- data/lib/ea/cli/command/diagrams.rb +37 -28
- data/lib/ea/cli/command/diff.rb +46 -0
- data/lib/ea/cli/command/export.rb +80 -0
- data/lib/ea/cli/command/info.rb +75 -0
- data/lib/ea/cli/command/lint.rb +48 -0
- data/lib/ea/cli/command/mdg.rb +98 -0
- data/lib/ea/cli/command/query.rb +34 -0
- data/lib/ea/cli/command/render.rb +135 -0
- data/lib/ea/cli/command/svg.rb +43 -6
- data/lib/ea/cli/command.rb +7 -0
- data/lib/ea/diagram/display_config.rb +184 -0
- data/lib/ea/diagram.rb +4 -41
- data/lib/ea/diff/change.rb +30 -0
- data/lib/ea/diff/comparator.rb +82 -0
- data/lib/ea/diff/html_reporter.rb +91 -0
- data/lib/ea/diff.rb +15 -0
- data/lib/ea/export/json/generator.rb +42 -0
- data/lib/ea/export/json.rb +12 -0
- data/lib/ea/export/json_schema/generator.rb +77 -0
- data/lib/ea/export/json_schema.rb +12 -0
- data/lib/ea/export/plantuml/generator.rb +73 -0
- data/lib/ea/export/plantuml.rb +12 -0
- data/lib/ea/export/xmi/generator.rb +77 -0
- data/lib/ea/export/xmi.rb +11 -0
- data/lib/ea/export/xsd/class_mapping.rb +65 -0
- data/lib/ea/export/xsd/generator.rb +142 -0
- data/lib/ea/export/xsd/namespace_registry.rb +82 -0
- data/lib/ea/export/xsd.rb +19 -0
- data/lib/ea/export.rb +14 -0
- data/lib/ea/image/emf_renderer.rb +42 -0
- data/lib/ea/image.rb +12 -0
- data/lib/ea/lint/engine.rb +30 -0
- data/lib/ea/lint/lint_rule.rb +38 -0
- data/lib/ea/lint/offense.rb +18 -0
- data/lib/ea/lint/rules/cyclic_generalization.rb +62 -0
- data/lib/ea/lint/rules/duplicate_name.rb +28 -0
- data/lib/ea/lint/rules/missing_stereotype.rb +35 -0
- data/lib/ea/lint/rules/naming_convention.rb +44 -0
- data/lib/ea/lint/rules/orphan_element.rb +28 -0
- data/lib/ea/lint/rules.rb +14 -0
- data/lib/ea/lint.rb +13 -0
- data/lib/ea/mdg/document.rb +120 -0
- data/lib/ea/mdg/loader.rb +118 -0
- data/lib/ea/mdg/registry.rb +98 -0
- data/lib/ea/mdg/stereotype_alias_registry.rb +77 -0
- data/lib/ea/mdg/xml/applies_to.rb +18 -0
- data/lib/ea/mdg/xml/apply.rb +18 -0
- data/lib/ea/mdg/xml/content.rb +18 -0
- data/lib/ea/mdg/xml/documentation.rb +24 -0
- data/lib/ea/mdg/xml/stereotype.rb +28 -0
- data/lib/ea/mdg/xml/stereotypes.rb +18 -0
- data/lib/ea/mdg/xml/tag.rb +28 -0
- data/lib/ea/mdg/xml/tagged_values.rb +18 -0
- data/lib/ea/mdg/xml/technology.rb +28 -0
- data/lib/ea/mdg/xml/uml_profile.rb +22 -0
- data/lib/ea/mdg/xml/uml_profiles.rb +18 -0
- data/lib/ea/mdg/xml.rb +24 -0
- data/lib/ea/mdg.rb +25 -0
- data/lib/ea/model/classifier.rb +4 -0
- data/lib/ea/model/constraint.rb +24 -0
- data/lib/ea/model/diagram.rb +85 -0
- data/lib/ea/model/diagram_connector.rb +53 -1
- data/lib/ea/model/diagram_element.rb +44 -0
- data/lib/ea/model/document.rb +47 -2
- data/lib/ea/model/ghost_label.rb +32 -0
- data/lib/ea/model/instance_specification.rb +34 -0
- data/lib/ea/model/legend.rb +43 -0
- data/lib/ea/model/legend_item.rb +26 -0
- data/lib/ea/model/note.rb +28 -0
- data/lib/ea/model/operation.rb +2 -0
- data/lib/ea/model/property.rb +2 -0
- data/lib/ea/model/relationship.rb +2 -0
- data/lib/ea/model/signal.rb +14 -0
- data/lib/ea/model/slot.rb +19 -0
- data/lib/ea/model.rb +8 -0
- data/lib/ea/ocl/evaluator.rb +94 -0
- data/lib/ea/ocl/nodes.rb +30 -0
- data/lib/ea/ocl/parser.rb +133 -0
- data/lib/ea/ocl/unsupported_error.rb +7 -0
- data/lib/ea/ocl.rb +13 -0
- data/lib/ea/qea/factory/document_builder.rb +24 -10
- data/lib/ea/qea/factory/generalization_builder.rb +9 -11
- data/lib/ea/qea/infrastructure/table_reader.rb +9 -0
- data/lib/ea/qea/models/ea_author.rb +35 -0
- data/lib/ea/qea/models/ea_glossary.rb +34 -0
- data/lib/ea/qea/models/ea_image.rb +53 -0
- data/lib/ea/qea/models/ea_implement.rb +32 -0
- data/lib/ea/qea/models/ea_list.rb +42 -0
- data/lib/ea/qea/models/ea_object_effort.rb +34 -0
- data/lib/ea/qea/models/ea_object_problem.rb +37 -0
- data/lib/ea/qea/models/ea_object_require.rb +34 -0
- data/lib/ea/qea/models/ea_object_resource.rb +34 -0
- data/lib/ea/qea/models/ea_object_risk.rb +34 -0
- data/lib/ea/qea/models/ea_object_scenario.rb +34 -0
- data/lib/ea/qea/models/ea_object_test.rb +35 -0
- data/lib/ea/qea/models/ea_object_trx.rb +34 -0
- data/lib/ea/qea/models/ea_operation.rb +7 -0
- data/lib/ea/qea/models/ea_palette.rb +30 -0
- data/lib/ea/qea/models/ea_palette_item.rb +36 -0
- data/lib/ea/qea/models/ea_phase.rb +40 -0
- data/lib/ea/qea/models/ea_role_constraint.rb +32 -0
- data/lib/ea/qea/models/ea_secrypt.rb +34 -0
- data/lib/ea/qea/models/ea_version.rb +39 -0
- data/lib/ea/qea/models/ea_xref.rb +11 -1
- data/lib/ea/qea/models.rb +19 -0
- data/lib/ea/qea/services/database_loader.rb +22 -1
- data/lib/ea/query/builder.rb +108 -0
- data/lib/ea/query.rb +9 -0
- data/lib/ea/render/image_converter.rb +101 -0
- data/lib/ea/render.rb +10 -0
- data/lib/ea/shapescript/parser.rb +208 -0
- data/lib/ea/shapescript/renderer.rb +74 -0
- data/lib/ea/shapescript/shape.rb +34 -0
- data/lib/ea/shapescript.rb +24 -0
- data/lib/ea/sources/qea/adapter.rb +22 -5
- data/lib/ea/sources/qea/classifier_builder.rb +184 -7
- data/lib/ea/sources/qea/diagram_builder.rb +352 -24
- data/lib/ea/sources/qea/id_normalizer.rb +16 -1
- data/lib/ea/sources/qea/instance_builder.rb +113 -0
- data/lib/ea/sources/qea/legend_builder.rb +137 -0
- data/lib/ea/sources/qea/note_builder.rb +58 -0
- data/lib/ea/sources/qea/object_classifier_map.rb +6 -1
- data/lib/ea/sources/qea/operation_builder.rb +1 -0
- data/lib/ea/sources/qea/package_builder.rb +16 -0
- data/lib/ea/sources/qea/relationship_builder.rb +21 -5
- data/lib/ea/sources/qea/tagged_value_builder.rb +28 -9
- data/lib/ea/sources/qea/xref/legend_definition.rb +35 -0
- data/lib/ea/sources/qea/xref/parser.rb +150 -0
- data/lib/ea/sources/qea/xref/property_definition.rb +29 -0
- data/lib/ea/sources/qea/xref/record.rb +41 -0
- data/lib/ea/sources/qea/xref/stereotype_application.rb +37 -0
- data/lib/ea/sources/qea/xref.rb +27 -0
- data/lib/ea/sources/qea.rb +4 -0
- data/lib/ea/sources/xmi/adapter.rb +80 -2
- data/lib/ea/sources/xmi/annotation_builder.rb +1 -1
- data/lib/ea/sources/xmi/classifier_builder.rb +10 -1
- data/lib/ea/sources/xmi/diagram_builder.rb +242 -45
- data/lib/ea/sources/xmi/extension_elements.rb +74 -0
- data/lib/ea/sources/xmi/extension_geometry_parser.rb +124 -0
- data/lib/ea/sources/xmi/extension_style_parser.rb +91 -0
- data/lib/ea/sources/xmi/note_builder.rb +46 -0
- data/lib/ea/sources/xmi/property_builder.rb +9 -0
- data/lib/ea/sources/xmi/stereotype_builder.rb +54 -0
- data/lib/ea/sources/xmi/tag_builder.rb +45 -0
- data/lib/ea/sources/xmi/umldi_keyword_extractor.rb +87 -0
- data/lib/ea/sources/xmi.rb +7 -0
- data/lib/ea/spa/output/sharded_multi_file_strategy.rb +18 -3
- data/lib/ea/spa/output/single_file_strategy.rb +8 -2
- data/lib/ea/spa/output/strategy.rb +34 -0
- data/lib/ea/svg/connector_router.rb +134 -0
- data/lib/ea/svg/ea_emitter/background.rb +15 -0
- data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
- data/lib/ea/svg/ea_emitter/canvas.rb +88 -0
- data/lib/ea/svg/ea_emitter/color_resolver.rb +56 -0
- data/lib/ea/svg/ea_emitter/compartment/attributes.rb +28 -0
- data/lib/ea/svg/ea_emitter/compartment/constraints.rb +30 -0
- data/lib/ea/svg/ea_emitter/compartment/enum_literals.rb +86 -0
- data/lib/ea/svg/ea_emitter/compartment/header.rb +32 -0
- data/lib/ea/svg/ea_emitter/compartment/header_divider.rb +57 -0
- data/lib/ea/svg/ea_emitter/compartment/instance_slots.rb +96 -0
- data/lib/ea/svg/ea_emitter/compartment/instance_underline.rb +67 -0
- data/lib/ea/svg/ea_emitter/compartment/note_body.rb +52 -0
- data/lib/ea/svg/ea_emitter/compartment/note_text.rb +102 -0
- data/lib/ea/svg/ea_emitter/compartment/operations.rb +38 -0
- data/lib/ea/svg/ea_emitter/compartment/package_contents.rb +72 -0
- data/lib/ea/svg/ea_emitter/compartment/package_from_parent.rb +136 -0
- data/lib/ea/svg/ea_emitter/compartment/shape.rb +82 -0
- data/lib/ea/svg/ea_emitter/compartment/tagged_values.rb +30 -0
- data/lib/ea/svg/ea_emitter/compartment.rb +58 -0
- data/lib/ea/svg/ea_emitter/connectors.rb +84 -0
- data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
- data/lib/ea/svg/ea_emitter/document.rb +35 -0
- data/lib/ea/svg/ea_emitter/element/attribute_line_builder.rb +117 -0
- data/lib/ea/svg/ea_emitter/element/attribute_renderer.rb +119 -0
- data/lib/ea/svg/ea_emitter/element/bcol_decoder.rb +29 -0
- data/lib/ea/svg/ea_emitter/element/compartment_geometry.rb +113 -0
- data/lib/ea/svg/ea_emitter/element/constraint_renderer.rb +53 -0
- data/lib/ea/svg/ea_emitter/element/divider_renderer.rb +17 -0
- data/lib/ea/svg/ea_emitter/element/enumeration_literal_renderer.rb +34 -0
- data/lib/ea/svg/ea_emitter/element/filter.rb +44 -0
- data/lib/ea/svg/ea_emitter/element/hand_draw_shape_renderer.rb +77 -0
- data/lib/ea/svg/ea_emitter/element/header_line_pipeline.rb +43 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/instance_spec.rb +27 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/name.rb +76 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/parent_ghost.rb +25 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider/stereotype_label.rb +68 -0
- data/lib/ea/svg/ea_emitter/element/header_line_provider.rb +19 -0
- data/lib/ea/svg/ea_emitter/element/header_lines.rb +27 -0
- data/lib/ea/svg/ea_emitter/element/header_renderer.rb +48 -0
- data/lib/ea/svg/ea_emitter/element/icon_renderer.rb +109 -0
- data/lib/ea/svg/ea_emitter/element/legend_renderer.rb +177 -0
- data/lib/ea/svg/ea_emitter/element/note_shape_renderer.rb +112 -0
- data/lib/ea/svg/ea_emitter/element/operation_renderer.rb +100 -0
- data/lib/ea/svg/ea_emitter/element/package_shape_renderer.rb +181 -0
- data/lib/ea/svg/ea_emitter/element/row_icon_renderer.rb +156 -0
- data/lib/ea/svg/ea_emitter/element/shape_renderer.rb +17 -0
- data/lib/ea/svg/ea_emitter/element/stereotype_icon_renderer.rb +82 -0
- data/lib/ea/svg/ea_emitter/element/tagged_value_renderer.rb +50 -0
- data/lib/ea/svg/ea_emitter/element/text_escape.rb +20 -0
- data/lib/ea/svg/ea_emitter/element.rb +37 -0
- data/lib/ea/svg/ea_emitter/elements.rb +357 -0
- data/lib/ea/svg/ea_emitter/font_resolver.rb +111 -0
- data/lib/ea/svg/ea_emitter/ghost_labels.rb +66 -0
- data/lib/ea/svg/ea_emitter/label/end_label.rb +266 -0
- data/lib/ea/svg/ea_emitter/label/midpoint_label.rb +101 -0
- data/lib/ea/svg/ea_emitter/label/registry.rb +50 -0
- data/lib/ea/svg/ea_emitter/label.rb +23 -0
- data/lib/ea/svg/ea_emitter/labels.rb +130 -0
- data/lib/ea/svg/ea_emitter/layer.rb +20 -0
- data/lib/ea/svg/ea_emitter/layer_sequencer.rb +93 -0
- data/lib/ea/svg/ea_emitter/marker/arrow_path.rb +52 -0
- data/lib/ea/svg/ea_emitter/marker/diamond.rb +57 -0
- data/lib/ea/svg/ea_emitter/marker/kind.rb +35 -0
- data/lib/ea/svg/ea_emitter/marker/open_triangle.rb +27 -0
- data/lib/ea/svg/ea_emitter/marker/package_import.rb +39 -0
- data/lib/ea/svg/ea_emitter/marker/plus.rb +40 -0
- data/lib/ea/svg/ea_emitter/marker/registry.rb +42 -0
- data/lib/ea/svg/ea_emitter/marker.rb +37 -0
- data/lib/ea/svg/ea_emitter/markers.rb +404 -0
- data/lib/ea/svg/ea_emitter/render_context.rb +52 -0
- data/lib/ea/svg/ea_emitter/style.rb +15 -0
- data/lib/ea/svg/ea_emitter/text_renderer.rb +92 -0
- data/lib/ea/svg/ea_emitter.rb +51 -0
- data/lib/ea/svg/parity/checker.rb +105 -0
- data/lib/ea/svg/parity/source.rb +59 -0
- data/lib/ea/svg/parity/suite.rb +113 -0
- data/lib/ea/svg/parity.rb +14 -0
- data/lib/ea/svg/stereotype_color_resolver.rb +50 -0
- data/lib/ea/svg.rb +4 -15
- data/lib/ea/theme/definition.rb +176 -0
- data/lib/ea/theme/loader.rb +125 -0
- data/lib/ea/theme/registry.rb +96 -0
- data/lib/ea/theme.rb +37 -0
- data/lib/ea/transformations.rb +5 -88
- data/lib/ea/version.rb +4 -1
- data/lib/ea.rb +14 -4
- data/lib/tasks/svg_bench.rake +87 -0
- data/lutaml-uml-0.5.1.gem +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes-list.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-1-themes.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-2-gradients.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-3-colors.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance-fonts.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-4-appearance.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-5-behavior.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram-6-sequence.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-1-diagram.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-2-objects.png +0 -0
- data/reference-docs/enterprise-architect-appearance-dialogs/appearance-3-links.png +0 -0
- metadata +473 -26
- data/lib/ea/diagram/configuration.rb +0 -379
- data/lib/ea/diagram/element_renderers/base_renderer.rb +0 -77
- data/lib/ea/diagram/element_renderers/class_renderer.rb +0 -323
- data/lib/ea/diagram/element_renderers/connector_renderer.rb +0 -41
- data/lib/ea/diagram/element_renderers/package_renderer.rb +0 -61
- data/lib/ea/diagram/element_renderers.rb +0 -43
- data/lib/ea/diagram/extractor.rb +0 -566
- data/lib/ea/diagram/layout_engine.rb +0 -170
- data/lib/ea/diagram/path_builder.rb +0 -202
- data/lib/ea/diagram/style_parser.rb +0 -42
- data/lib/ea/diagram/style_resolver.rb +0 -291
- data/lib/ea/diagram/svg_renderer.rb +0 -274
- data/lib/ea/diagram/util.rb +0 -73
- data/lib/ea/svg/bounds_calculator.rb +0 -74
- data/lib/ea/svg/connector_path.rb +0 -138
- data/lib/ea/svg/element_box.rb +0 -256
- data/lib/ea/svg/renderer.rb +0 -77
- data/lib/ea/svg/style_resolver.rb +0 -72
- data/lib/ea/transformations/configuration.rb +0 -333
- data/lib/ea/transformations/format_registry.rb +0 -366
- data/lib/ea/transformations/parsers/base_parser.rb +0 -482
- data/lib/ea/transformations/parsers/qea_parser.rb +0 -401
- data/lib/ea/transformations/parsers/xmi_parser.rb +0 -243
- 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 :
|
|
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("&", "&")
|
|
85
|
+
.gsub("<", "<")
|
|
86
|
+
.gsub(">", ">")
|
|
87
|
+
.gsub('"', """)
|
|
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,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
|