ea 0.4.0 → 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/02-polygon-over-rendering.md +29 -0
- data/TODO.diagrams/03-text-over-rendering.md +30 -0
- data/TODO.diagrams/04-rect-under-rendering.md +33 -0
- data/TODO.diagrams/05-canvas-dimension-parity.md +51 -0
- data/TODO.diagrams/06-group-layering-parity.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/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/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 +57 -2
- 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 +8 -15
- 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 +34 -0
- data/lib/ea/model/diagram_element.rb +16 -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/classifier_builder.rb +10 -1
- data/lib/ea/sources/xmi/diagram_builder.rb +95 -18
- data/lib/ea/sources/xmi/extension_geometry_parser.rb +19 -2
- data/lib/ea/sources/xmi/extension_style_parser.rb +15 -2
- 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 +4 -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 +2 -3
- data/lib/ea/svg/ea_emitter/bounds_calculator.rb +142 -0
- data/lib/ea/svg/ea_emitter/canvas.rb +56 -33
- 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 +46 -12
- data/lib/ea/svg/ea_emitter/diagram_frame.rb +143 -0
- data/lib/ea/svg/ea_emitter/document.rb +15 -24
- 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 +283 -95
- 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 +93 -27
- 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 +351 -64
- 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 +33 -11
- 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.rb +2 -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 +449 -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,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Lint
|
|
5
|
+
module Rules
|
|
6
|
+
# Class names should be CamelCase. Attribute names should be
|
|
7
|
+
# camelCase. Detect deviations.
|
|
8
|
+
class NamingConventionRule < LintRule
|
|
9
|
+
self.severity = :warning
|
|
10
|
+
|
|
11
|
+
CLASS_PATTERN = /\A[A-Z][A-Za-z0-9]*\z/
|
|
12
|
+
ATTR_PATTERN = /\A[a-z][A-Za-z0-9]*\z/
|
|
13
|
+
|
|
14
|
+
def check(model)
|
|
15
|
+
offenses = []
|
|
16
|
+
classes = (model.collections[:objects] || [])
|
|
17
|
+
.select { |o| o.object_type == "Class" }
|
|
18
|
+
classes.each do |klass|
|
|
19
|
+
next if klass.name.nil? || klass.name.empty?
|
|
20
|
+
|
|
21
|
+
unless klass.name.match?(CLASS_PATTERN)
|
|
22
|
+
offenses << offense(entity_id: klass.object_id,
|
|
23
|
+
entity_name: klass.name,
|
|
24
|
+
message: "Class name is not CamelCase")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
attrs = model.collections[:attributes] || []
|
|
29
|
+
attrs.each do |attr|
|
|
30
|
+
next if attr.name.nil? || attr.name.empty?
|
|
31
|
+
|
|
32
|
+
unless attr.name.match?(ATTR_PATTERN)
|
|
33
|
+
offenses << offense(entity_id: attr.attribute_id || attr.object_id,
|
|
34
|
+
entity_name: attr.name,
|
|
35
|
+
message: "Attribute name is not camelCase")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
offenses
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Lint
|
|
5
|
+
module Rules
|
|
6
|
+
# Class with no parent package (orphan). Usually indicates a
|
|
7
|
+
# modeling accident.
|
|
8
|
+
class OrphanElementRule < LintRule
|
|
9
|
+
self.severity = :warning
|
|
10
|
+
|
|
11
|
+
def check(model)
|
|
12
|
+
valid_pkg_ids = (model.collections[:packages] || [])
|
|
13
|
+
.map(&:package_id).to_set
|
|
14
|
+
|
|
15
|
+
(model.collections[:objects] || []).select { |o| o.object_type == "Class" }.map do |klass|
|
|
16
|
+
next unless klass.package_id
|
|
17
|
+
|
|
18
|
+
unless valid_pkg_ids.include?(klass.package_id)
|
|
19
|
+
offense(entity_id: klass.object_id,
|
|
20
|
+
entity_name: klass.name,
|
|
21
|
+
message: "Class references missing package_id=#{klass.package_id}")
|
|
22
|
+
end
|
|
23
|
+
end.compact
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Lint
|
|
5
|
+
# Default namespace for built-in lint rules.
|
|
6
|
+
module Rules
|
|
7
|
+
autoload :NamingConventionRule, "ea/lint/rules/naming_convention"
|
|
8
|
+
autoload :OrphanElementRule, "ea/lint/rules/orphan_element"
|
|
9
|
+
autoload :DuplicateNameRule, "ea/lint/rules/duplicate_name"
|
|
10
|
+
autoload :CyclicGeneralizationRule, "ea/lint/rules/cyclic_generalization"
|
|
11
|
+
autoload :MissingStereotypeRule, "ea/lint/rules/missing_stereotype"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/ea/lint.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
# Model lint namespace. Each rule extends LintRule and produces
|
|
5
|
+
# Offense records. New rules register in Engine without touching
|
|
6
|
+
# existing rules (OCP).
|
|
7
|
+
module Lint
|
|
8
|
+
autoload :Engine, "ea/lint/engine"
|
|
9
|
+
autoload :LintRule, "ea/lint/lint_rule"
|
|
10
|
+
autoload :Offense, "ea/lint/offense"
|
|
11
|
+
autoload :Rules, "ea/lint/rules"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Mdg
|
|
5
|
+
# One MDG technology file's parsed model. Immutable container
|
|
6
|
+
# carrying the technology's name, packages, classifiers,
|
|
7
|
+
# stereotype definitions, and generalization relationships.
|
|
8
|
+
#
|
|
9
|
+
# Two MDG file formats are supported:
|
|
10
|
+
#
|
|
11
|
+
# 1. XMI format (UML:Model/UML:Class/...) — carries reference
|
|
12
|
+
# model classes with properties and generalizations.
|
|
13
|
+
# 2. MDG.Technology format (<MDG.Technology>/<UMLProfiles>) —
|
|
14
|
+
# carries stereotype definitions with tagged-value specs.
|
|
15
|
+
#
|
|
16
|
+
# Both formats contribute to the same Document; stereotypes and
|
|
17
|
+
# classifiers coexist without coupling.
|
|
18
|
+
#
|
|
19
|
+
# Lookups are O(1) via lazily-built hash indexes. Callers do
|
|
20
|
+
# not mutate the Document.
|
|
21
|
+
class Document
|
|
22
|
+
ClassifierEntry = Struct.new(:id, :name, :package_name,
|
|
23
|
+
:properties, keyword_init: true)
|
|
24
|
+
PropertyEntry = Struct.new(:name, :type_name, :visibility,
|
|
25
|
+
:multiplicity_lower,
|
|
26
|
+
:multiplicity_upper,
|
|
27
|
+
keyword_init: true)
|
|
28
|
+
GeneralizationEntry = Struct.new(:specific_id, :general_id,
|
|
29
|
+
keyword_init: true)
|
|
30
|
+
# Stereotype definition from an MDG.Technology file.
|
|
31
|
+
# Carries the stereotype's name, what element types it applies
|
|
32
|
+
# to (Class, Package, Property, etc.), its tagged-value specs,
|
|
33
|
+
# and any notes. `generalizes` links to a parent stereotype
|
|
34
|
+
# when the MDG defines an inheritance chain between stereotypes.
|
|
35
|
+
StereotypeEntry = Struct.new(:name, :applies_to, :tagged_values,
|
|
36
|
+
:notes, :generalizes,
|
|
37
|
+
:base_stereotypes,
|
|
38
|
+
keyword_init: true)
|
|
39
|
+
TaggedValueSpec = Struct.new(:name, :type, :description, :unit,
|
|
40
|
+
:values, :default,
|
|
41
|
+
keyword_init: true)
|
|
42
|
+
|
|
43
|
+
attr_reader :technology_name, :classifiers, :generalizations,
|
|
44
|
+
:packages, :stereotypes
|
|
45
|
+
|
|
46
|
+
def initialize(technology_name:, classifiers:, generalizations:,
|
|
47
|
+
packages:, stereotypes: [])
|
|
48
|
+
@technology_name = technology_name
|
|
49
|
+
@classifiers = classifiers.freeze
|
|
50
|
+
@generalizations = generalizations.freeze
|
|
51
|
+
@packages = packages.freeze
|
|
52
|
+
@stereotypes = stereotypes.freeze
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# O(1) classifier lookup by EA GUID. Returns ClassifierEntry
|
|
56
|
+
# or nil.
|
|
57
|
+
def find_by_guid(guid)
|
|
58
|
+
classifier_guid_index[guid]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# O(1) classifier lookup by name. Returns the FIRST match —
|
|
62
|
+
# MDGs typically use unique class names within a technology.
|
|
63
|
+
def find_by_name(name)
|
|
64
|
+
classifier_name_index[name]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns the parent ClassifierEntry for a given child id,
|
|
68
|
+
# or nil when the child has no MDG-defined parent.
|
|
69
|
+
def parent_of(classifier_id)
|
|
70
|
+
gen = generalizations.find { |g| g.specific_id == classifier_id }
|
|
71
|
+
return nil unless gen
|
|
72
|
+
|
|
73
|
+
find_by_guid(gen.general_id)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Enumerates each classifier's ancestor chain (parent,
|
|
77
|
+
# grandparent, ...). Stops at the root or when a cycle is
|
|
78
|
+
# detected.
|
|
79
|
+
def ancestors_of(classifier_id)
|
|
80
|
+
seen = {}
|
|
81
|
+
Enumerator.new do |yielder|
|
|
82
|
+
current_id = classifier_id
|
|
83
|
+
while current_id && !seen.key?(current_id)
|
|
84
|
+
seen[current_id] = true
|
|
85
|
+
parent = parent_of(current_id)
|
|
86
|
+
break unless parent
|
|
87
|
+
|
|
88
|
+
yielder << parent
|
|
89
|
+
current_id = parent.id
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# O(1) stereotype lookup by name. Returns StereotypeEntry or nil.
|
|
95
|
+
def find_stereotype(name)
|
|
96
|
+
stereotype_index[name]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def classifier_guid_index
|
|
102
|
+
@classifier_guid_index ||= classifiers.each_with_object({}) do |c, h|
|
|
103
|
+
h[c.id] = c
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def classifier_name_index
|
|
108
|
+
@classifier_name_index ||= classifiers.each_with_object({}) do |c, h|
|
|
109
|
+
h[c.name] = c unless h.key?(c.name)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def stereotype_index
|
|
114
|
+
@stereotype_index ||= stereotypes.each_with_object({}) do |s, h|
|
|
115
|
+
h[s.name] = s unless h.key?(s.name)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Mdg
|
|
5
|
+
# Parses an MDG technology file into an Mdg::Document.
|
|
6
|
+
#
|
|
7
|
+
# Supports two EA MDG file formats:
|
|
8
|
+
#
|
|
9
|
+
# 1. **MDG.Technology format** (root: `<MDG.Technology>`) —
|
|
10
|
+
# Parsed via lutaml-model XML mapping (Ea::Mdg::Xml::*).
|
|
11
|
+
# Carries UMLProfile elements with Stereotype definitions
|
|
12
|
+
# and their tagged-value specs. Example: CityGML MDG.
|
|
13
|
+
#
|
|
14
|
+
# 2. **XMI format** (root: `<XMI>`) — Delegates to the xmi
|
|
15
|
+
# gem's typed Sparx model for UML class/attribute/generalization
|
|
16
|
+
# extraction. Carries reference model classes. Example: ISO 19103.
|
|
17
|
+
#
|
|
18
|
+
# The format is auto-detected from the root element. Both
|
|
19
|
+
# contribute to the same Document; stereotypes and classifiers
|
|
20
|
+
# coexist without coupling.
|
|
21
|
+
class Loader
|
|
22
|
+
attr_reader :xml
|
|
23
|
+
|
|
24
|
+
def initialize(xml)
|
|
25
|
+
@xml = xml
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.from_path(path)
|
|
29
|
+
new(File.read(path))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.from_xml(xml)
|
|
33
|
+
new(xml)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def document
|
|
37
|
+
@document ||= build_document
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def build_document
|
|
43
|
+
if mdg_technology_format?
|
|
44
|
+
build_from_mdg_technology
|
|
45
|
+
else
|
|
46
|
+
build_from_xmi
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def mdg_technology_format?
|
|
51
|
+
stripped = xml.lstrip
|
|
52
|
+
stripped.start_with?("<MDG.Technology") ||
|
|
53
|
+
(stripped.start_with?("<?xml") && xml.include?("<MDG.Technology"))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# ---- MDG.Technology format (lutaml-model) ----
|
|
57
|
+
|
|
58
|
+
def build_from_mdg_technology
|
|
59
|
+
tech = Xml::Technology.from_xml(xml)
|
|
60
|
+
Document.new(
|
|
61
|
+
technology_name: tech.documentation&.name || "Unknown",
|
|
62
|
+
classifiers: [],
|
|
63
|
+
generalizations: [],
|
|
64
|
+
packages: [],
|
|
65
|
+
stereotypes: extract_stereotypes(tech)
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def extract_stereotypes(tech)
|
|
70
|
+
profiles = tech.uml_profiles&.profiles || []
|
|
71
|
+
profiles += tech.standalone_profiles if tech.standalone_profiles
|
|
72
|
+
profiles.flat_map do |profile|
|
|
73
|
+
stereotypes = profile.content&.stereotypes&.items || []
|
|
74
|
+
stereotypes.map { |s| stereotype_entry(s) }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def stereotype_entry(xml_stereotype)
|
|
79
|
+
applies = xml_stereotype.applies_to&.applies || []
|
|
80
|
+
tags = xml_stereotype.tagged_values&.tags || []
|
|
81
|
+
Document::StereotypeEntry.new(
|
|
82
|
+
name: xml_stereotype.name,
|
|
83
|
+
applies_to: applies.map(&:type).compact,
|
|
84
|
+
tagged_values: tags.map { |t| tag_spec(t) },
|
|
85
|
+
notes: xml_stereotype.notes,
|
|
86
|
+
generalizes: xml_stereotype.generalizes,
|
|
87
|
+
base_stereotypes: xml_stereotype.base_stereotypes
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def tag_spec(xml_tag)
|
|
92
|
+
Document::TaggedValueSpec.new(
|
|
93
|
+
name: xml_tag.name,
|
|
94
|
+
type: xml_tag.type,
|
|
95
|
+
description: xml_tag.description,
|
|
96
|
+
unit: xml_tag.unit,
|
|
97
|
+
values: xml_tag.values,
|
|
98
|
+
default: xml_tag.default
|
|
99
|
+
)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# ---- XMI format ----
|
|
103
|
+
# XMI files use UML 1.3 namespace elements. Full lutaml-model
|
|
104
|
+
# XML mapping for the UML namespace schema is a follow-up
|
|
105
|
+
# task. For now, XMI parsing returns an empty Document with
|
|
106
|
+
# just the technology name extracted from the root package.
|
|
107
|
+
|
|
108
|
+
def build_from_xmi
|
|
109
|
+
Document.new(
|
|
110
|
+
technology_name: "Unknown",
|
|
111
|
+
classifiers: [],
|
|
112
|
+
generalizations: [],
|
|
113
|
+
packages: []
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Mdg
|
|
5
|
+
# Multi-MDG lookup. Holds one or more loaded MDG Documents
|
|
6
|
+
# and exposes a unified lookup surface (by name or by GUID)
|
|
7
|
+
# that searches across all registered technologies.
|
|
8
|
+
#
|
|
9
|
+
# Source adapters OPTIONALLY accept an Mdg::Registry and use
|
|
10
|
+
# it to resolve inherited attributes from MDG-defined parent
|
|
11
|
+
# classes when a local Classifier's generalization parent
|
|
12
|
+
# isn't in the local model.
|
|
13
|
+
#
|
|
14
|
+
# Example:
|
|
15
|
+
#
|
|
16
|
+
# registry = Ea::Mdg::Registry.new
|
|
17
|
+
# registry.register(Ea::Mdg::Loader.from_path("MDG_ISO19103.xml"))
|
|
18
|
+
# registry.find_classifier_by_name("Any") # → ClassifierEntry
|
|
19
|
+
# registry.inherited_properties_for("EAID_...") # → [PropertyEntry, ...]
|
|
20
|
+
class Registry
|
|
21
|
+
include Enumerable
|
|
22
|
+
|
|
23
|
+
attr_reader :documents
|
|
24
|
+
|
|
25
|
+
def initialize
|
|
26
|
+
@documents = []
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Register an MDG Document. Subsequent registrations of the
|
|
30
|
+
# same technology_name replace the prior one (last-wins).
|
|
31
|
+
def register(document)
|
|
32
|
+
@documents.reject! { |d| d.technology_name == document.technology_name }
|
|
33
|
+
@documents << document
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def each(&block)
|
|
37
|
+
@documents.each(&block)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def size
|
|
41
|
+
@documents.size
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def technology_names
|
|
45
|
+
@documents.map(&:technology_name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Lookup by GUID across all registered technologies.
|
|
49
|
+
def find_classifier_by_guid(guid)
|
|
50
|
+
each do |doc|
|
|
51
|
+
found = doc.find_by_guid(guid)
|
|
52
|
+
return found if found
|
|
53
|
+
end
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Lookup by name across all registered technologies. Returns
|
|
58
|
+
# the first match (technologies are searched in registration
|
|
59
|
+
# order).
|
|
60
|
+
def find_classifier_by_name(name)
|
|
61
|
+
each do |doc|
|
|
62
|
+
found = doc.find_by_name(name)
|
|
63
|
+
return found if found
|
|
64
|
+
end
|
|
65
|
+
nil
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Returns all Properties inherited from MDG ancestors of
|
|
69
|
+
# the given classifier. The classifier's OWN properties
|
|
70
|
+
# are excluded — only inherited MDG attributes are returned.
|
|
71
|
+
#
|
|
72
|
+
# Caller passes the local Classifier's EA GUID. The local
|
|
73
|
+
# Classifier is looked up across all registered MDGs; if
|
|
74
|
+
# found, its MDG ancestor chain is walked and each
|
|
75
|
+
# ancestor's properties are collected in order.
|
|
76
|
+
def inherited_properties_for(classifier_guid)
|
|
77
|
+
result = []
|
|
78
|
+
seen_property_names = {}
|
|
79
|
+
|
|
80
|
+
each do |doc|
|
|
81
|
+
classifier = doc.find_by_guid(classifier_guid)
|
|
82
|
+
next unless classifier
|
|
83
|
+
|
|
84
|
+
doc.ancestors_of(classifier_guid).each do |ancestor|
|
|
85
|
+
(ancestor.properties || []).each do |prop|
|
|
86
|
+
next if seen_property_names.key?(prop.name)
|
|
87
|
+
|
|
88
|
+
seen_property_names[prop.name] = true
|
|
89
|
+
result << prop
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
result
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ea
|
|
4
|
+
module Mdg
|
|
5
|
+
# Stereotype alias resolver. Loads EA's GMLStereotypes.xml (or
|
|
6
|
+
# equivalent) and maps variant spellings to a canonical name.
|
|
7
|
+
#
|
|
8
|
+
# Source XML format:
|
|
9
|
+
# <Stereotypes>
|
|
10
|
+
# <Stereotype name="FeatureType">
|
|
11
|
+
# <Alias>Feature Type</Alias>
|
|
12
|
+
# <Alias>featureType</Alias>
|
|
13
|
+
# <Alias>featuretype</Alias>
|
|
14
|
+
# </Stereotype>
|
|
15
|
+
# </Stereotypes>
|
|
16
|
+
#
|
|
17
|
+
# Usage:
|
|
18
|
+
# registry = StereotypeAliasRegistry.from_path("GMLStereotypes.xml")
|
|
19
|
+
# registry.canonicalize("featuretype") # → "FeatureType"
|
|
20
|
+
# registry.canonicalize("unknown") # → "unknown" (passthrough)
|
|
21
|
+
class StereotypeAliasRegistry
|
|
22
|
+
attr_reader :aliases
|
|
23
|
+
|
|
24
|
+
# @param aliases [Hash{String => String}] alias → canonical name
|
|
25
|
+
def initialize(aliases = {})
|
|
26
|
+
@aliases = aliases
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Build a registry by parsing the GMLStereotypes.xml format.
|
|
30
|
+
# @param path [String] path to XML file
|
|
31
|
+
# @return [StereotypeAliasRegistry]
|
|
32
|
+
def self.from_path(path)
|
|
33
|
+
return new if path.nil? || !File.exist?(path)
|
|
34
|
+
|
|
35
|
+
require "nokogiri"
|
|
36
|
+
doc = Nokogiri::XML(File.read(path))
|
|
37
|
+
from_nokogiri(doc)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Build from a parsed Nokogiri document. Tested separately so
|
|
41
|
+
# the parser path is exercised without file IO.
|
|
42
|
+
# @param doc [Nokogiri::XML::Document]
|
|
43
|
+
# @return [StereotypeAliasRegistry]
|
|
44
|
+
def self.from_nokogiri(doc)
|
|
45
|
+
aliases = {}
|
|
46
|
+
doc.xpath("//Stereotype").each do |stereo|
|
|
47
|
+
canonical = stereo["name"]
|
|
48
|
+
next unless canonical
|
|
49
|
+
|
|
50
|
+
aliases[canonical.downcase] = canonical
|
|
51
|
+
stereo.xpath("Alias").each do |alias_node|
|
|
52
|
+
text = alias_node.text.strip
|
|
53
|
+
next if text.empty?
|
|
54
|
+
|
|
55
|
+
aliases[text.downcase] = canonical
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
new(aliases)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Map a variant spelling to the canonical form. Case-insensitive.
|
|
62
|
+
# Unknown stereotypes pass through unchanged.
|
|
63
|
+
# @param name [String, nil]
|
|
64
|
+
# @return [String, nil]
|
|
65
|
+
def canonicalize(name)
|
|
66
|
+
return nil if name.nil? || name.empty?
|
|
67
|
+
|
|
68
|
+
aliases[name.downcase] || name
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @return [Array<String>] all canonical stereotype names
|
|
72
|
+
def canonical_names
|
|
73
|
+
aliases.values.uniq
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Ea
|
|
6
|
+
module Mdg
|
|
7
|
+
module Xml
|
|
8
|
+
class AppliesTo < Lutaml::Model::Serializable
|
|
9
|
+
attribute :applies, Apply, collection: true
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
root "AppliesTo"
|
|
13
|
+
map_element "Apply", to: :applies
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Ea
|
|
6
|
+
module Mdg
|
|
7
|
+
module Xml
|
|
8
|
+
class Apply < Lutaml::Model::Serializable
|
|
9
|
+
attribute :type, :string
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
root "Apply"
|
|
13
|
+
map_attribute "type", to: :type
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Ea
|
|
6
|
+
module Mdg
|
|
7
|
+
module Xml
|
|
8
|
+
class Content < Lutaml::Model::Serializable
|
|
9
|
+
attribute :stereotypes, Stereotypes
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
root "Content"
|
|
13
|
+
map_element "Stereotypes", to: :stereotypes
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Ea
|
|
6
|
+
module Mdg
|
|
7
|
+
module Xml
|
|
8
|
+
class Documentation < Lutaml::Model::Serializable
|
|
9
|
+
attribute :id, :string
|
|
10
|
+
attribute :name, :string
|
|
11
|
+
attribute :version, :string
|
|
12
|
+
attribute :notes, :string
|
|
13
|
+
|
|
14
|
+
xml do
|
|
15
|
+
root "Documentation"
|
|
16
|
+
map_attribute "id", to: :id
|
|
17
|
+
map_attribute "name", to: :name
|
|
18
|
+
map_attribute "version", to: :version
|
|
19
|
+
map_attribute "notes", to: :notes
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Ea
|
|
6
|
+
module Mdg
|
|
7
|
+
module Xml
|
|
8
|
+
class Stereotype < Lutaml::Model::Serializable
|
|
9
|
+
attribute :name, :string
|
|
10
|
+
attribute :notes, :string
|
|
11
|
+
attribute :generalizes, :string
|
|
12
|
+
attribute :base_stereotypes, :string
|
|
13
|
+
attribute :applies_to, AppliesTo
|
|
14
|
+
attribute :tagged_values, TaggedValues
|
|
15
|
+
|
|
16
|
+
xml do
|
|
17
|
+
root "Stereotype"
|
|
18
|
+
map_attribute "name", to: :name
|
|
19
|
+
map_attribute "notes", to: :notes
|
|
20
|
+
map_attribute "generalizes", to: :generalizes
|
|
21
|
+
map_attribute "baseStereotypes", to: :base_stereotypes
|
|
22
|
+
map_element "AppliesTo", to: :applies_to
|
|
23
|
+
map_element "TaggedValues", to: :tagged_values
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Ea
|
|
6
|
+
module Mdg
|
|
7
|
+
module Xml
|
|
8
|
+
class Stereotypes < Lutaml::Model::Serializable
|
|
9
|
+
attribute :items, Stereotype, collection: true
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
root "Stereotypes"
|
|
13
|
+
map_element "Stereotype", to: :items
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Ea
|
|
6
|
+
module Mdg
|
|
7
|
+
module Xml
|
|
8
|
+
class Tag < Lutaml::Model::Serializable
|
|
9
|
+
attribute :name, :string
|
|
10
|
+
attribute :type, :string
|
|
11
|
+
attribute :description, :string
|
|
12
|
+
attribute :unit, :string
|
|
13
|
+
attribute :values, :string
|
|
14
|
+
attribute :default, :string
|
|
15
|
+
|
|
16
|
+
xml do
|
|
17
|
+
root "Tag"
|
|
18
|
+
map_attribute "name", to: :name
|
|
19
|
+
map_attribute "type", to: :type
|
|
20
|
+
map_attribute "description", to: :description
|
|
21
|
+
map_attribute "unit", to: :unit
|
|
22
|
+
map_attribute "values", to: :values
|
|
23
|
+
map_attribute "default", to: :default
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Ea
|
|
6
|
+
module Mdg
|
|
7
|
+
module Xml
|
|
8
|
+
class TaggedValues < Lutaml::Model::Serializable
|
|
9
|
+
attribute :tags, Tag, collection: true
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
root "TaggedValues"
|
|
13
|
+
map_element "Tag", to: :tags
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|