ea 0.1.0 → 0.1.4
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/CLAUDE.md +125 -0
- data/Rakefile +12 -4
- data/TODO.next/00-publish-blocking-bugs.md +74 -0
- data/TODO.next/01-standalone-ea-gem-identity.md +76 -0
- data/TODO.next/02-optional-lutaml-uml-dependency.md +47 -0
- data/TODO.next/03-slim-lutaml-uml.md +79 -0
- data/TODO.next/04-loader-registry-for-uml-repository.md +49 -0
- data/TODO.next/05-extract-shared-transformer-methods.md +14 -0
- data/TODO.next/06-deduplicate-stereotype-loading.md +17 -0
- data/TODO.next/07-transformer-registry-in-factory.md +20 -0
- data/TODO.next/08-connector-type-registry.md +27 -0
- data/TODO.next/09-element-renderer-registry.md +29 -0
- data/TODO.next/10-connector-renderer-lsp.md +18 -0
- data/TODO.next/11-consolidate-style-knowledge.md +33 -0
- data/TODO.next/12-data-driven-from-db-row.md +24 -0
- data/TODO.next/13-extract-duplicated-methods.md +17 -0
- data/TODO.next/14-remove-dead-code.md +10 -0
- data/TODO.next/15-narrow-exception-handling.md +39 -0
- data/TODO.next/16-repository-indexes.md +28 -0
- data/TODO.next/17-fix-spec-quality-and-coverage.md +32 -0
- data/TODO.next/18-xmi-tool-specific-parser-architecture.md +172 -0
- data/TODO.next/19-fix-ea-gemspec-dependency-declarations.md +56 -0
- data/TODO.next/20-ci-requires-unreleased-lutaml-uml.md +63 -0
- data/TODO.next/21-qeatoxmi-via-xmi-gem.md +340 -0
- data/TODO.next/22-strip-respond-to-from-qeatoxmi-specs.md +32 -0
- data/TODO.next/23-cleanup-idallocator.md +41 -0
- data/TODO.next/24-tighten-parity-specs.md +42 -0
- data/TODO.next/25-sparx-eaid-format-for-synthesized-ids.md +62 -0
- data/TODO.next/26-fix-uppervalue-lowervalue-count-gap.md +51 -0
- data/TODO.next/27-extract-cardinality-module.md +68 -0
- data/TODO.next/28-extract-xml-sanitizer.md +51 -0
- data/TODO.next/29-ocp-registry-for-classifier-builders.md +58 -0
- data/TODO.next/30-struct-return-for-association-end.md +37 -0
- data/TODO.next/31-idallocator-specs.md +27 -0
- data/TODO.next/32-phase2-gap-sentinel-specs.md +53 -0
- data/TODO.next/33-normalize-lower-cleanup.md +30 -0
- data/TODO.next/34-document-member-end-order-rt-prefix.md +29 -0
- data/TODO.next/35-walk-runstate-for-instance-slots.md +76 -0
- data/TODO.next/36-wire-interface-realization.md +50 -0
- data/TODO.next/37-visibility-returns-real-booleans.md +36 -0
- data/config/diagram_styles.yml +200 -0
- data/config/model_transformations.yml +266 -0
- data/config/qea_schema.yml +1024 -0
- data/docs/ea_to_uml_type_mapping.md +89 -0
- data/docs/xmi_qea_conversion_capabilities.md +99 -0
- data/examples/lur/20251010_current_plateau_v5.1.lur +0 -0
- data/examples/lur/basic.lur +0 -0
- data/examples/lur/test-output.lur +0 -0
- data/examples/lur/test.lur +0 -0
- data/examples/lur_basic_usage.rb +221 -0
- data/examples/lur_cli_workflow.rb +263 -0
- data/examples/lur_statistics.rb +326 -0
- data/examples/qea/20251010_current_plateau_v5.1.qea +0 -0
- data/examples/qea/ArcGISWorkspace_template.qea +0 -0
- data/examples/qea/README_qea_parser.adoc +230 -0
- data/examples/qea/UmlModel_template.qea +0 -0
- data/examples/qea/basic.qea +0 -0
- data/examples/qea/simple.qea +0 -0
- data/examples/qea/simple_example.qea +0 -0
- data/examples/qea/test.qea +0 -0
- data/examples/qea_standalone_query.rb +73 -0
- data/examples/qea_to_repository.rb +51 -0
- data/examples/smoke_test_real_qea.rb +81 -0
- data/exe/ea +7 -0
- data/lib/ea/cli/app.rb +72 -0
- data/lib/ea/cli/command/base.rb +80 -0
- data/lib/ea/cli/command/convert.rb +62 -0
- data/lib/ea/cli/command/diagrams.rb +81 -0
- data/lib/ea/cli/command/list.rb +61 -0
- data/lib/ea/cli/command/parse.rb +29 -0
- data/lib/ea/cli/command/stats.rb +20 -0
- data/lib/ea/cli/command/validate.rb +41 -0
- data/lib/ea/cli/command.rb +15 -0
- data/lib/ea/cli/error.rb +34 -0
- data/lib/ea/cli/output/formatter.rb +34 -0
- data/lib/ea/cli/output/json_formatter.rb +20 -0
- data/lib/ea/cli/output/table_formatter.rb +42 -0
- data/lib/ea/cli/output/yaml_formatter.rb +20 -0
- data/lib/ea/cli/output.rb +56 -0
- data/lib/ea/cli.rb +17 -0
- data/lib/ea/diagram/configuration.rb +379 -0
- data/lib/ea/diagram/element_renderers/base_renderer.rb +77 -0
- data/lib/ea/diagram/element_renderers/class_renderer.rb +323 -0
- data/lib/ea/diagram/element_renderers/connector_renderer.rb +41 -0
- data/lib/ea/diagram/element_renderers/package_renderer.rb +61 -0
- data/lib/ea/diagram/element_renderers.rb +43 -0
- data/lib/ea/diagram/extractor.rb +560 -0
- data/lib/ea/diagram/layout_engine.rb +170 -0
- data/lib/ea/diagram/path_builder.rb +202 -0
- data/lib/ea/diagram/style_parser.rb +42 -0
- data/lib/ea/diagram/style_resolver.rb +276 -0
- data/lib/ea/diagram/svg_renderer.rb +274 -0
- data/lib/ea/diagram/util.rb +73 -0
- data/lib/ea/diagram.rb +47 -0
- data/lib/ea/qea/benchmark.rb +210 -0
- data/lib/ea/qea/database.rb +308 -0
- data/lib/ea/qea/factory/association_builder.rb +203 -0
- data/lib/ea/qea/factory/association_transformer.rb +91 -0
- data/lib/ea/qea/factory/attribute_tag_transformer.rb +57 -0
- data/lib/ea/qea/factory/attribute_transformer.rb +93 -0
- data/lib/ea/qea/factory/base_transformer.rb +177 -0
- data/lib/ea/qea/factory/class_transformer.rb +116 -0
- data/lib/ea/qea/factory/constraint_transformer.rb +75 -0
- data/lib/ea/qea/factory/data_type_transformer.rb +77 -0
- data/lib/ea/qea/factory/diagram_transformer.rb +157 -0
- data/lib/ea/qea/factory/document_builder.rb +283 -0
- data/lib/ea/qea/factory/ea_to_uml_factory.rb +229 -0
- data/lib/ea/qea/factory/enum_transformer.rb +74 -0
- data/lib/ea/qea/factory/generalization_builder.rb +227 -0
- data/lib/ea/qea/factory/generalization_transformer.rb +98 -0
- data/lib/ea/qea/factory/instance_transformer.rb +68 -0
- data/lib/ea/qea/factory/object_property_transformer.rb +58 -0
- data/lib/ea/qea/factory/operation_transformer.rb +66 -0
- data/lib/ea/qea/factory/package_transformer.rb +145 -0
- data/lib/ea/qea/factory/reference_resolver.rb +99 -0
- data/lib/ea/qea/factory/stereotype_loader.rb +39 -0
- data/lib/ea/qea/factory/tagged_value_transformer.rb +38 -0
- data/lib/ea/qea/factory/transformer_registry.rb +80 -0
- data/lib/ea/qea/factory.rb +37 -0
- data/lib/ea/qea/file_detector.rb +178 -0
- data/lib/ea/qea/infrastructure/database_connection.rb +100 -0
- data/lib/ea/qea/infrastructure/schema_reader.rb +136 -0
- data/lib/ea/qea/infrastructure/table_reader.rb +224 -0
- data/lib/ea/qea/infrastructure.rb +12 -0
- data/lib/ea/qea/models/base_model.rb +59 -0
- data/lib/ea/qea/models/ea_attribute.rb +109 -0
- data/lib/ea/qea/models/ea_attribute_tag.rb +100 -0
- data/lib/ea/qea/models/ea_complexity_type.rb +79 -0
- data/lib/ea/qea/models/ea_connector.rb +160 -0
- data/lib/ea/qea/models/ea_connector_type.rb +60 -0
- data/lib/ea/qea/models/ea_constraint_type.rb +63 -0
- data/lib/ea/qea/models/ea_datatype.rb +104 -0
- data/lib/ea/qea/models/ea_diagram.rb +115 -0
- data/lib/ea/qea/models/ea_diagram_link.rb +78 -0
- data/lib/ea/qea/models/ea_diagram_object.rb +73 -0
- data/lib/ea/qea/models/ea_diagram_type.rb +56 -0
- data/lib/ea/qea/models/ea_document.rb +63 -0
- data/lib/ea/qea/models/ea_object.rb +223 -0
- data/lib/ea/qea/models/ea_object_constraint.rb +53 -0
- data/lib/ea/qea/models/ea_object_property.rb +87 -0
- data/lib/ea/qea/models/ea_object_type.rb +73 -0
- data/lib/ea/qea/models/ea_operation.rb +127 -0
- data/lib/ea/qea/models/ea_operation_param.rb +76 -0
- data/lib/ea/qea/models/ea_package.rb +78 -0
- data/lib/ea/qea/models/ea_script.rb +62 -0
- data/lib/ea/qea/models/ea_status_type.rb +66 -0
- data/lib/ea/qea/models/ea_stereotype.rb +57 -0
- data/lib/ea/qea/models/ea_tagged_value.rb +99 -0
- data/lib/ea/qea/models/ea_xref.rb +165 -0
- data/lib/ea/qea/models.rb +35 -0
- data/lib/ea/qea/repositories/base_repository.rb +225 -0
- data/lib/ea/qea/repositories/object_repository.rb +219 -0
- data/lib/ea/qea/repositories.rb +10 -0
- data/lib/ea/qea/services/configuration.rb +211 -0
- data/lib/ea/qea/services/database_loader.rb +191 -0
- data/lib/ea/qea/services.rb +10 -0
- data/lib/ea/qea/validation/association_validator.rb +73 -0
- data/lib/ea/qea/validation/attribute_validator.rb +91 -0
- data/lib/ea/qea/validation/base_validator.rb +331 -0
- data/lib/ea/qea/validation/class_validator.rb +121 -0
- data/lib/ea/qea/validation/database/circular_reference_validator.rb +109 -0
- data/lib/ea/qea/validation/database/orphan_validator.rb +153 -0
- data/lib/ea/qea/validation/database/referential_integrity_validator.rb +128 -0
- data/lib/ea/qea/validation/database.rb +16 -0
- data/lib/ea/qea/validation/diagram_validator.rb +112 -0
- data/lib/ea/qea/validation/formatters/json_formatter.rb +137 -0
- data/lib/ea/qea/validation/formatters/text_formatter.rb +235 -0
- data/lib/ea/qea/validation/formatters.rb +12 -0
- data/lib/ea/qea/validation/operation_validator.rb +71 -0
- data/lib/ea/qea/validation/package_validator.rb +111 -0
- data/lib/ea/qea/validation/validation_engine.rb +387 -0
- data/lib/ea/qea/validation/validation_message.rb +144 -0
- data/lib/ea/qea/validation/validation_result.rb +210 -0
- data/lib/ea/qea/validation/validator_registry.rb +134 -0
- data/lib/ea/qea/validation.rb +28 -0
- data/lib/ea/qea/verification/comparison_result.rb +264 -0
- data/lib/ea/qea/verification/document_normalizer.rb +169 -0
- data/lib/ea/qea/verification/document_verifier.rb +322 -0
- data/lib/ea/qea/verification/element_comparator.rb +277 -0
- data/lib/ea/qea/verification/structure_matcher.rb +287 -0
- data/lib/ea/qea/verification.rb +14 -0
- data/lib/ea/qea.rb +185 -0
- data/lib/ea/transformations/configuration.rb +333 -0
- data/lib/ea/transformations/format_registry.rb +366 -0
- data/lib/ea/transformations/parsers/base_parser.rb +482 -0
- data/lib/ea/transformations/parsers/qea_parser.rb +401 -0
- data/lib/ea/transformations/parsers/xmi_parser.rb +243 -0
- data/lib/ea/transformations/transformation_engine.rb +390 -0
- data/lib/ea/transformations.rb +85 -0
- data/lib/ea/transformers/qea_to_xmi/association_end.rb +19 -0
- data/lib/ea/transformers/qea_to_xmi/cardinality.rb +96 -0
- data/lib/ea/transformers/qea_to_xmi/context.rb +106 -0
- data/lib/ea/transformers/qea_to_xmi/guid_format.rb +56 -0
- data/lib/ea/transformers/qea_to_xmi/id_allocator.rb +92 -0
- data/lib/ea/transformers/qea_to_xmi/run_state.rb +107 -0
- data/lib/ea/transformers/qea_to_xmi/transformer.rb +607 -0
- data/lib/ea/transformers/qea_to_xmi/visibility.rb +73 -0
- data/lib/ea/transformers/qea_to_xmi.rb +29 -0
- data/lib/ea/transformers/uml_to_xmi/id_generator.rb +54 -0
- data/lib/ea/transformers/uml_to_xmi/transformer.rb +152 -0
- data/lib/ea/transformers/uml_to_xmi/writer.rb +96 -0
- data/lib/ea/transformers/uml_to_xmi.rb +16 -0
- data/lib/ea/transformers.rb +34 -0
- data/lib/ea/version.rb +1 -1
- data/lib/ea/xmi/liquid_drops/association_drop.rb +56 -0
- data/lib/ea/xmi/liquid_drops/attribute_drop.rb +72 -0
- data/lib/ea/xmi/liquid_drops/cardinality_drop.rb +35 -0
- data/lib/ea/xmi/liquid_drops/connector_drop.rb +54 -0
- data/lib/ea/xmi/liquid_drops/constraint_drop.rb +29 -0
- data/lib/ea/xmi/liquid_drops/data_type_drop.rb +63 -0
- data/lib/ea/xmi/liquid_drops/dependency_drop.rb +36 -0
- data/lib/ea/xmi/liquid_drops/diagram_drop.rb +34 -0
- data/lib/ea/xmi/liquid_drops/enum_drop.rb +49 -0
- data/lib/ea/xmi/liquid_drops/enum_owned_literal_drop.rb +25 -0
- data/lib/ea/xmi/liquid_drops/generalization_attribute_drop.rb +87 -0
- data/lib/ea/xmi/liquid_drops/generalization_drop.rb +127 -0
- data/lib/ea/xmi/liquid_drops/klass_drop.rb +191 -0
- data/lib/ea/xmi/liquid_drops/operation_drop.rb +29 -0
- data/lib/ea/xmi/liquid_drops/package_drop.rb +108 -0
- data/lib/ea/xmi/liquid_drops/root_drop.rb +34 -0
- data/lib/ea/xmi/liquid_drops/source_target_drop.rb +43 -0
- data/lib/ea/xmi/lookup_service.rb +89 -0
- data/lib/ea/xmi/parser.rb +919 -0
- data/lib/ea/xmi.rb +35 -0
- data/lib/ea.rb +10 -1
- metadata +382 -9
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# EA Object Type → UML Mapping
|
|
2
|
+
|
|
3
|
+
This document describes how `ea` maps Sparx EA object types (from the QEA
|
|
4
|
+
`t_object` table's `Object_Type` column) to UML model elements during the
|
|
5
|
+
`Ea::Qea.to_uml` transformation.
|
|
6
|
+
|
|
7
|
+
The mapping is implemented in
|
|
8
|
+
`Ea::Qea::Models::EaObject#transformer_type`, which returns a
|
|
9
|
+
`TransformerRegistry` key or `nil`.
|
|
10
|
+
|
|
11
|
+
## Principles
|
|
12
|
+
|
|
13
|
+
1. **Hub-and-spoke, not format-to-format.** Both QEA and XMI parse *into* a
|
|
14
|
+
common `Lutaml::Uml::Document`. There is no direct QEA↔XMI translator.
|
|
15
|
+
2. **Model elements only.** Only EA object types that correspond to genuine
|
|
16
|
+
UML model elements are transformed. Rendering hints and tool-internal
|
|
17
|
+
plumbing are dropped.
|
|
18
|
+
3. **Stereotype can override type.** A Class with stereotype `enumeration`
|
|
19
|
+
transforms as an Enum, not a Class.
|
|
20
|
+
|
|
21
|
+
## Mapping table
|
|
22
|
+
|
|
23
|
+
| EA `Object_Type` | UML element | Transformer key | Notes |
|
|
24
|
+
|--------------------|---------------------|-----------------|-------------------------------------------|
|
|
25
|
+
| `Class` | `UmlClass` | `:class` | |
|
|
26
|
+
| `Interface` | `UmlClass` | `:class` | |
|
|
27
|
+
| `Enumeration` | `Enum` | `:enumeration` | Also: Class with `<<enumeration>>` |
|
|
28
|
+
| `DataType` | `DataType` | `:data_type` | |
|
|
29
|
+
| `Instance`/`Object`| `Instance` | `:instance` | |
|
|
30
|
+
| `Package` | `Package` | `:package` | From `t_package`, not `t_object` |
|
|
31
|
+
| `Text` | _(dropped)_ | `nil` | See below |
|
|
32
|
+
| `Note` | _(dropped)_ | `nil` | See below |
|
|
33
|
+
| `ProxyConnector` | _(dropped)_ | `nil` | See below |
|
|
34
|
+
|
|
35
|
+
Connectors (`t_connector`) are handled separately from objects and map to
|
|
36
|
+
`Association`, `Generalization`, or `Dependency` depending on their type.
|
|
37
|
+
|
|
38
|
+
## Dropped types — rationale
|
|
39
|
+
|
|
40
|
+
### `Text`
|
|
41
|
+
|
|
42
|
+
A free-form text box placed on a diagram for labeling or annotation. It is a
|
|
43
|
+
**rendering hint**, not a model element — it has no semantic relationship to
|
|
44
|
+
the classes and packages in the model.
|
|
45
|
+
|
|
46
|
+
- **Current behavior:** dropped. Content is not preserved in the UML document.
|
|
47
|
+
- **Why not `UmlClass`:** Text has no attributes, operations, or type
|
|
48
|
+
semantics. Treating it as a class (the previous behavior) polluted the class
|
|
49
|
+
collection with non-classes and broke class counts.
|
|
50
|
+
- **Future:** map to `Lutaml::Uml::Comment`. This requires adding a `comments`
|
|
51
|
+
collection to `Lutaml::Uml::Package` (currently only `Document` has one, and
|
|
52
|
+
it is a flat string list). Until then, Text content is lost.
|
|
53
|
+
|
|
54
|
+
### `Note`
|
|
55
|
+
|
|
56
|
+
A note element on a diagram. Same category as `Text` — a rendering/annotation
|
|
57
|
+
hint, not a model element.
|
|
58
|
+
|
|
59
|
+
- **Current behavior:** dropped.
|
|
60
|
+
- **Future:** same as `Text` — map to `Comment` when the metamodel supports it.
|
|
61
|
+
|
|
62
|
+
### `ProxyConnector`
|
|
63
|
+
|
|
64
|
+
EA's internal stub representing a connector that crosses a package boundary.
|
|
65
|
+
When a connector in package A points at an element in package B, EA may insert
|
|
66
|
+
a `ProxyConnector` in one package as a stand-in for the foreign element.
|
|
67
|
+
|
|
68
|
+
- **Current behavior:** dropped.
|
|
69
|
+
- **Why:** it is structural plumbing. The actual relationship is already
|
|
70
|
+
captured by the real connector (in `t_connector`) and resolved by
|
|
71
|
+
`ReferenceResolver`. A `ProxyConnector` in `t_object` is a rendering/UX
|
|
72
|
+
artifact, not a second model element.
|
|
73
|
+
- **Future:** no plan to preserve. If diagram rendering needs the proxy
|
|
74
|
+
geometry, it should come from `t_diagram_objects`, not from treating the
|
|
75
|
+
proxy as a class.
|
|
76
|
+
|
|
77
|
+
## Verifying counts
|
|
78
|
+
|
|
79
|
+
After transformation:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
EA t_object (Class) = UML UmlClass count (in packages + orphan root)
|
|
83
|
+
EA t_object (Enumeration) = UML Enum count
|
|
84
|
+
EA t_object (DataType) = UML DataType count
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
If counts don't match, check for orphaned classes (objects whose `package_id`
|
|
88
|
+
has no row in `t_package`) — these surface at the document root via
|
|
89
|
+
`EaToUmlFactory#transform_orphan_classes`, not inside any package.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Format Conversion Capabilities: QEA, XMI, and UML
|
|
2
|
+
|
|
3
|
+
## Short answer
|
|
4
|
+
|
|
5
|
+
**No.** The `ea` gem cannot convert XMI→QEA or QEA→XMI. Neither direction
|
|
6
|
+
exists. Both formats are parsed *into* a common `Lutaml::Uml::Document`
|
|
7
|
+
(hub-and-spoke), but there is no write-back path to either native format.
|
|
8
|
+
|
|
9
|
+
## Current capability matrix
|
|
10
|
+
|
|
11
|
+
| From | To | Status | API |
|
|
12
|
+
|-------------------|----------------------|--------------|-------------------------------|
|
|
13
|
+
| `.qea` (SQLite) | `Ea::Qea::Database` | ✅ Full | `Ea::Qea.load(path)` |
|
|
14
|
+
| `.qea` | `Lutaml::Uml::Document` | ✅ Full | `Ea::Qea.parse(path)` / `to_uml(db)` |
|
|
15
|
+
| Sparx `.xmi` | `::Xmi::Sparx::Root` model | ✅ Full | `Ea::Xmi::Parser.parse(path)` |
|
|
16
|
+
| Sparx `.xmi` | Liquid drops (display) | ✅ Full | `Parser.serialize_to_liquid` |
|
|
17
|
+
| Sparx `.xmi` | `Lutaml::Uml::Document` | ❌ None | — |
|
|
18
|
+
| `Lutaml::Uml::Document` | Sparx `.xmi` | ❌ None | — |
|
|
19
|
+
| `Lutaml::Uml::Document` | `.qea` (SQLite) | ❌ None | — |
|
|
20
|
+
|
|
21
|
+
## Why neither direction exists
|
|
22
|
+
|
|
23
|
+
### QEA is read-only
|
|
24
|
+
|
|
25
|
+
`Ea::Qea::Infrastructure::DatabaseConnection` opens SQLite with
|
|
26
|
+
`readonly: true`. There is no `INSERT`/`UPDATE` path, no writer class, no
|
|
27
|
+
`to_qea`. Building one requires reverse-mapping a UML Document into EA's
|
|
28
|
+
~30 interrelated tables (`t_object`, `t_package`, `t_connector`, `t_attribute`,
|
|
29
|
+
`t_diagram`, `t_objectproperties`, `t_xref`, `t_taggedvalue`, …), generating
|
|
30
|
+
valid EA GUIDs and object_ids, and populating tool-specific columns
|
|
31
|
+
(style strings, diagram geometry, visibility flags) that have no UML source.
|
|
32
|
+
|
|
33
|
+
### XMI is parse-only
|
|
34
|
+
|
|
35
|
+
`Ea::Xmi::Parser` consumes Sparx XMI via `::Xmi::Sparx::Root.parse_xml` and
|
|
36
|
+
exposes the result through Liquid drops for *display* rendering (HTML/JSON
|
|
37
|
+
templates). The drops wrap XMI-derived data — they do not serialize a
|
|
38
|
+
`Lutaml::Uml::Document` back to XMI. There is no `UmlDocument → XMI`
|
|
39
|
+
serializer.
|
|
40
|
+
|
|
41
|
+
### The drops are display, not generation
|
|
42
|
+
|
|
43
|
+
`Ea::Xmi::LiquidDrops::*` are Liquid `Drop` wrappers around the parsed XMI
|
|
44
|
+
model. They exist to render XMI content in templates (for browsing,
|
|
45
|
+
documentation, HTML export). A Liquid drop reads from a model; it does not
|
|
46
|
+
write one. To generate XMI, you'd need XMI-schema-aware serialization
|
|
47
|
+
(`xmi:Documentation`, `xmi:Extension`, `EAStub`, profile application, etc.),
|
|
48
|
+
which is a separate, substantial piece of work.
|
|
49
|
+
|
|
50
|
+
## What "conversion" would actually require
|
|
51
|
+
|
|
52
|
+
### QEA → XMI (export)
|
|
53
|
+
|
|
54
|
+
1. Build a `Lutaml::Uml::Document → Sparx XMI` serializer.
|
|
55
|
+
2. Lossy: the UML Document does not carry EA-specific data (diagram layout,
|
|
56
|
+
style strings, tagged value geometry, t_xref cross-references). The
|
|
57
|
+
exported XMI would be semantically faithful but visually bare.
|
|
58
|
+
3. The Sparx XMI schema is documented but large; `::Xmi::Sparx::Root`
|
|
59
|
+
parses it but cannot (currently) serialize it.
|
|
60
|
+
|
|
61
|
+
### XMI → QEA (import)
|
|
62
|
+
|
|
63
|
+
1. Build `XMI → Lutaml::Uml::Document` (does not exist — `Ea::Xmi::Parser`
|
|
64
|
+
produces display drops, not a UML Document).
|
|
65
|
+
2. Build `Lutaml::Uml::Document → QEA SQLite` writer (does not exist —
|
|
66
|
+
see "QEA is read-only" above).
|
|
67
|
+
3. Highly lossy: EA's QEA schema has ~30 tables with tool-specific columns.
|
|
68
|
+
Sparx's own XMI import into QEA is lossy; reimplementing it faithfully
|
|
69
|
+
is a major project with marginal value (you'd produce a QEA that opens
|
|
70
|
+
in EA but has no diagrams, no layout, no EA-specific metadata).
|
|
71
|
+
|
|
72
|
+
## Recommendation
|
|
73
|
+
|
|
74
|
+
Do **not** position the gem as offering XMI↔QEA conversion. Instead:
|
|
75
|
+
|
|
76
|
+
- **Read both formats into UML** — this is the gem's core value.
|
|
77
|
+
- **Query and analyze** the resulting UML Document (directly or via
|
|
78
|
+
`Lutaml::UmlRepository::Repository.from_document`).
|
|
79
|
+
- **Export to neutral formats** — JSON, CSV, HTML (via Liquid drops),
|
|
80
|
+
`.lur` package (via Repository). These are one-way, lossy, and honest
|
|
81
|
+
about what they are.
|
|
82
|
+
|
|
83
|
+
If true XMI↔QEA round-trip is needed, the pragmatic path is to use Sparx EA
|
|
84
|
+
itself (which does both natively) and treat this gem as the
|
|
85
|
+
extract/query/analyze layer that sits alongside EA, not as a replacement
|
|
86
|
+
for its file-format converters.
|
|
87
|
+
|
|
88
|
+
## If we ever build write paths
|
|
89
|
+
|
|
90
|
+
The clean order would be:
|
|
91
|
+
|
|
92
|
+
1. **`Lutaml::Uml::Document → Sparx XMI`** — most useful, least schema
|
|
93
|
+
complexity. Reuses `::Xmi::Sparx::Root`'s type system if serialization
|
|
94
|
+
support is added upstream.
|
|
95
|
+
2. **`Lutaml::Uml::Document → .lur`** — already exists via
|
|
96
|
+
`Repository.export_to_package`. Neutral, lossless for the UML subset.
|
|
97
|
+
3. **`Lutaml::Uml::Document → .qea`** — last resort. Only if EA-native
|
|
98
|
+
interchange is a hard requirement and `.lur` + XMI export are
|
|
99
|
+
insufficient.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Example: Basic LUR Repository Operations
|
|
5
|
+
#
|
|
6
|
+
# This example demonstrates basic repository operations including:
|
|
7
|
+
# - Loading from XMI or LUR files
|
|
8
|
+
# - Finding packages and classes
|
|
9
|
+
# - Navigating inheritance hierarchies
|
|
10
|
+
# - Querying associations
|
|
11
|
+
|
|
12
|
+
# Load local development version
|
|
13
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
14
|
+
|
|
15
|
+
require "lutaml"
|
|
16
|
+
require "lutaml/uml_repository"
|
|
17
|
+
require "ea"
|
|
18
|
+
|
|
19
|
+
# Example 1: Load from XMI file
|
|
20
|
+
puts "=" * 80
|
|
21
|
+
puts "Example 1: Load from XMI"
|
|
22
|
+
puts "=" * 80
|
|
23
|
+
|
|
24
|
+
# Build repository from XMI (slow, 5-8 seconds for large models)
|
|
25
|
+
# repo = Lutaml::UmlRepository::Repository.from_xmi("model.xmi")
|
|
26
|
+
|
|
27
|
+
# Or use smart file detection (auto-detects .xmi or .lur)
|
|
28
|
+
# repo = Lutaml::UmlRepository::Repository.from_file("model.xmi")
|
|
29
|
+
|
|
30
|
+
# For this example, we'll show the API without actual file
|
|
31
|
+
puts "repo = Lutaml::UmlRepository::Repository.from_xmi('model.xmi')"
|
|
32
|
+
puts "# Builds indexes from XMI (5-8s for large models)"
|
|
33
|
+
puts
|
|
34
|
+
|
|
35
|
+
# Example 2: Load from LUR package (fast loading)
|
|
36
|
+
puts "=" * 80
|
|
37
|
+
puts "Example 2: Load from LUR package (< 100ms)"
|
|
38
|
+
puts "=" * 80
|
|
39
|
+
|
|
40
|
+
puts "repo = Lutaml::UmlRepository::Repository.from_package('model.lur')"
|
|
41
|
+
puts "# Fast loading from pre-indexed package"
|
|
42
|
+
puts
|
|
43
|
+
|
|
44
|
+
# Example 3: Smart caching
|
|
45
|
+
puts "=" * 80
|
|
46
|
+
puts "Example 3: Smart caching"
|
|
47
|
+
puts "=" * 80
|
|
48
|
+
|
|
49
|
+
puts "repo = Lutaml::UmlRepository::Repository.from_file_cached('model.xmi')"
|
|
50
|
+
puts "# Uses cached .lur if newer than .xmi, otherwise rebuilds"
|
|
51
|
+
puts
|
|
52
|
+
|
|
53
|
+
# For demonstration, let's use a QEA file if available
|
|
54
|
+
qea_file = Dir.glob("examples/qea/*.qea").first
|
|
55
|
+
puts "=" * 80
|
|
56
|
+
if qea_file
|
|
57
|
+
puts "Example 4: Loading from QEA file (10-20x faster than XMI)"
|
|
58
|
+
puts "=" * 80
|
|
59
|
+
puts "QEA file found: #{qea_file}"
|
|
60
|
+
|
|
61
|
+
# Parse QEA directly
|
|
62
|
+
document = Ea::Qea.parse(qea_file)
|
|
63
|
+
repo = Lutaml::UmlRepository::Repository.new(document: document)
|
|
64
|
+
|
|
65
|
+
puts "Loaded successfully!"
|
|
66
|
+
puts
|
|
67
|
+
|
|
68
|
+
# Example 5: Finding packages
|
|
69
|
+
puts "=" * 80
|
|
70
|
+
puts "Example 5: Finding packages"
|
|
71
|
+
puts "=" * 80
|
|
72
|
+
|
|
73
|
+
# Find root package
|
|
74
|
+
root = repo.find_package("ModelRoot")
|
|
75
|
+
if root
|
|
76
|
+
puts "Root package: #{root.name}"
|
|
77
|
+
puts "Root type: #{root.class}"
|
|
78
|
+
end
|
|
79
|
+
puts
|
|
80
|
+
|
|
81
|
+
# List top-level packages
|
|
82
|
+
packages = repo.list_packages("ModelRoot", recursive: false)
|
|
83
|
+
puts "Top-level packages (#{packages.size}):"
|
|
84
|
+
packages.first(5).each do |pkg|
|
|
85
|
+
puts " - #{pkg.name}"
|
|
86
|
+
end
|
|
87
|
+
puts " ..." if packages.size > 5
|
|
88
|
+
puts
|
|
89
|
+
|
|
90
|
+
# Example 6: Finding classes
|
|
91
|
+
puts "=" * 80
|
|
92
|
+
puts "Example 6: Finding classes"
|
|
93
|
+
puts "=" * 80
|
|
94
|
+
|
|
95
|
+
# Get all classes
|
|
96
|
+
all_classes = repo.classes_index
|
|
97
|
+
puts "Total classes: #{all_classes.size}"
|
|
98
|
+
puts
|
|
99
|
+
|
|
100
|
+
# Find by stereotype
|
|
101
|
+
if all_classes.any?
|
|
102
|
+
first_class = all_classes.first
|
|
103
|
+
puts "First class: #{first_class.name}"
|
|
104
|
+
if first_class.respond_to?(:stereotype) && first_class.stereotype
|
|
105
|
+
puts " Stereotype: #{first_class.stereotype}"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
puts
|
|
109
|
+
|
|
110
|
+
# Example 7: Working with associations
|
|
111
|
+
puts "=" * 80
|
|
112
|
+
puts "Example 7: Associations"
|
|
113
|
+
puts "=" * 80
|
|
114
|
+
|
|
115
|
+
associations = repo.associations_index
|
|
116
|
+
puts "Total associations: #{associations.size}"
|
|
117
|
+
|
|
118
|
+
if associations.any?
|
|
119
|
+
assoc = associations.first
|
|
120
|
+
puts "\nFirst association:"
|
|
121
|
+
member_end = assoc.member_end
|
|
122
|
+
if member_end.is_a?(Array) && member_end.any?
|
|
123
|
+
puts " Name: #{member_end.first&.name || 'unnamed'}"
|
|
124
|
+
elsif member_end.respond_to?(:name)
|
|
125
|
+
puts " Name: #{member_end.name}"
|
|
126
|
+
else
|
|
127
|
+
puts " Name: unnamed"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
member_end_type = assoc.member_end_type
|
|
131
|
+
if member_end_type.is_a?(Array) && member_end_type.any?
|
|
132
|
+
puts " Type: #{member_end_type.first}"
|
|
133
|
+
elsif member_end_type
|
|
134
|
+
puts " Type: #{member_end_type}"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
puts
|
|
138
|
+
|
|
139
|
+
# Example 8: Statistics
|
|
140
|
+
puts "=" * 80
|
|
141
|
+
puts "Example 8: Repository statistics"
|
|
142
|
+
puts "=" * 80
|
|
143
|
+
|
|
144
|
+
stats = repo.statistics
|
|
145
|
+
puts "Packages: #{stats[:total_packages]}"
|
|
146
|
+
puts "Classes: #{stats[:total_classes]}"
|
|
147
|
+
puts "Associations: #{stats[:total_associations]}"
|
|
148
|
+
puts "Diagrams: #{stats[:total_diagrams]}"
|
|
149
|
+
|
|
150
|
+
if stats[:classes_by_stereotype]
|
|
151
|
+
puts "\nClasses by stereotype:"
|
|
152
|
+
stats[:classes_by_stereotype].first(5).each do |stereotype, count|
|
|
153
|
+
puts " #{stereotype}: #{count}"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
puts
|
|
157
|
+
|
|
158
|
+
# Example 9: Search
|
|
159
|
+
puts "=" * 80
|
|
160
|
+
puts "Example 9: Search"
|
|
161
|
+
puts "=" * 80
|
|
162
|
+
|
|
163
|
+
# Search for elements
|
|
164
|
+
results = repo.search("Object", types: [:class])
|
|
165
|
+
puts "Search for 'Object' in class names:"
|
|
166
|
+
puts " Found #{results[:total]} matches"
|
|
167
|
+
if results[:classes]
|
|
168
|
+
puts " Classes (#{results[:classes].size}):"
|
|
169
|
+
results[:classes].first(3).each do |result|
|
|
170
|
+
puts " - #{result.element.name}"
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
puts
|
|
174
|
+
|
|
175
|
+
else
|
|
176
|
+
puts "No QEA files found in examples/qea/"
|
|
177
|
+
puts "=" * 80
|
|
178
|
+
puts
|
|
179
|
+
puts "To use this example:"
|
|
180
|
+
puts "1. Place a .qea or .xmi file in examples/qea/"
|
|
181
|
+
puts "2. Or modify the script to point to your model file"
|
|
182
|
+
puts
|
|
183
|
+
puts "Example API usage (without actual file):"
|
|
184
|
+
puts <<~RUBY
|
|
185
|
+
|
|
186
|
+
# Load repository
|
|
187
|
+
repo = Lutaml::UmlRepository::Repository.from_xmi("model.xmi")
|
|
188
|
+
|
|
189
|
+
# Find package
|
|
190
|
+
package = repo.find_package("ModelRoot::MyPackage")
|
|
191
|
+
|
|
192
|
+
# Find class
|
|
193
|
+
klass = repo.find_class("ModelRoot::MyPackage::MyClass")
|
|
194
|
+
|
|
195
|
+
# Get class attributes
|
|
196
|
+
klass.attributes.each do |attr|
|
|
197
|
+
puts "\#{attr.name}: \#{attr.type}"
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Find by stereotype
|
|
201
|
+
feature_types = repo.find_classes_by_stereotype("featureType")
|
|
202
|
+
|
|
203
|
+
# Get inheritance
|
|
204
|
+
parent = repo.supertype_of(klass)
|
|
205
|
+
children = repo.subtypes_of(klass)
|
|
206
|
+
|
|
207
|
+
# Get associations
|
|
208
|
+
assocs = repo.associations_of(klass)
|
|
209
|
+
|
|
210
|
+
# Search
|
|
211
|
+
results = repo.search("Building")
|
|
212
|
+
|
|
213
|
+
# Get statistics
|
|
214
|
+
stats = repo.statistics
|
|
215
|
+
puts "Total classes: \#{stats[:total_classes]}"
|
|
216
|
+
RUBY
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
puts "=" * 80
|
|
220
|
+
puts "Example complete!"
|
|
221
|
+
puts "=" * 80
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Example: CLI Workflow Patterns
|
|
5
|
+
#
|
|
6
|
+
# This example demonstrates common command-line workflow patterns for
|
|
7
|
+
# working with LUR packages, including building, validation, and export.
|
|
8
|
+
|
|
9
|
+
# Load local development version
|
|
10
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
11
|
+
|
|
12
|
+
require "lutaml"
|
|
13
|
+
require "lutaml/uml_repository"
|
|
14
|
+
require "ea"
|
|
15
|
+
require "fileutils"
|
|
16
|
+
|
|
17
|
+
puts "=" * 80
|
|
18
|
+
puts "LUR CLI Workflow Examples"
|
|
19
|
+
puts "=" * 80
|
|
20
|
+
puts
|
|
21
|
+
|
|
22
|
+
# Setup: Find a test file
|
|
23
|
+
qea_file = Dir.glob("examples/qea/*.qea").first
|
|
24
|
+
xmi_file = Dir.glob("examples/qea/*.xmi").first
|
|
25
|
+
test_file = qea_file || xmi_file
|
|
26
|
+
|
|
27
|
+
unless test_file
|
|
28
|
+
puts "No test files found in examples/qea/"
|
|
29
|
+
puts
|
|
30
|
+
puts "This example demonstrates CLI workflows. To run:"
|
|
31
|
+
puts " 1. Place a .qea or .xmi file in examples/qea/"
|
|
32
|
+
puts " 2. Or use the CLI commands directly:"
|
|
33
|
+
puts
|
|
34
|
+
puts "CLI command examples:"
|
|
35
|
+
puts <<~TEXT
|
|
36
|
+
# Build LUR package from XMI
|
|
37
|
+
$ lutaml uml build model.xmi -o model.lur
|
|
38
|
+
|
|
39
|
+
# Build from QEA (10-20x faster)
|
|
40
|
+
$ lutaml uml build model.qea -o model.lur
|
|
41
|
+
|
|
42
|
+
# Show package info
|
|
43
|
+
$ lutaml uml info model.lur
|
|
44
|
+
|
|
45
|
+
# List packages
|
|
46
|
+
$ lutaml uml ls model.lur
|
|
47
|
+
|
|
48
|
+
# Show package tree
|
|
49
|
+
$ lutaml uml tree model.lur --depth 3
|
|
50
|
+
|
|
51
|
+
# Search
|
|
52
|
+
$ lutaml uml search model.lur "Building"
|
|
53
|
+
|
|
54
|
+
# Find by stereotype
|
|
55
|
+
$ lutaml uml find model.lur --stereotype featureType
|
|
56
|
+
|
|
57
|
+
# Get statistics
|
|
58
|
+
$ lutaml uml stats model.lur
|
|
59
|
+
|
|
60
|
+
# Validate
|
|
61
|
+
$ lutaml uml validate model.lur
|
|
62
|
+
|
|
63
|
+
# Export to CSV
|
|
64
|
+
$ lutaml uml export model.lur --format csv -o classes.csv
|
|
65
|
+
|
|
66
|
+
# Generate documentation site
|
|
67
|
+
$ lutaml uml docs model.lur -o docs/
|
|
68
|
+
|
|
69
|
+
# Start interactive shell
|
|
70
|
+
$ lutaml uml repl model.lur
|
|
71
|
+
|
|
72
|
+
# Watch mode (auto-rebuild on changes)
|
|
73
|
+
$ lutaml uml watch model.xmi -o model.lur
|
|
74
|
+
TEXT
|
|
75
|
+
exit 0
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
puts "Test file found: #{test_file}"
|
|
79
|
+
puts "File size: #{File.size(test_file) / 1024}KB"
|
|
80
|
+
puts
|
|
81
|
+
|
|
82
|
+
# Workflow 1: Build LUR package
|
|
83
|
+
puts "=" * 80
|
|
84
|
+
puts "Workflow 1: Building LUR package"
|
|
85
|
+
puts "=" * 80
|
|
86
|
+
|
|
87
|
+
lur_output = "examples/workflow_test.lur"
|
|
88
|
+
FileUtils.rm_f(lur_output)
|
|
89
|
+
|
|
90
|
+
puts "Loading from: #{test_file}"
|
|
91
|
+
start_time = Time.now
|
|
92
|
+
|
|
93
|
+
# Parse the source file
|
|
94
|
+
if test_file.end_with?(".qea")
|
|
95
|
+
puts "Parsing QEA file (fast)..."
|
|
96
|
+
document = Ea::Qea.parse(test_file)
|
|
97
|
+
elsif test_file.end_with?(".xmi")
|
|
98
|
+
puts "Parsing XMI file..."
|
|
99
|
+
document = Lutaml::Parser.parse([File.new(test_file)]).first
|
|
100
|
+
else
|
|
101
|
+
puts "Unknown file type"
|
|
102
|
+
exit 1
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
parse_time = Time.now - start_time
|
|
106
|
+
puts "Parsed in #{parse_time.round(2)}s"
|
|
107
|
+
|
|
108
|
+
# Build repository
|
|
109
|
+
puts "Building repository..."
|
|
110
|
+
repo = Lutaml::UmlRepository::Repository.new(document: document)
|
|
111
|
+
build_time = Time.now - start_time - parse_time
|
|
112
|
+
puts "Built in #{build_time.round(2)}s"
|
|
113
|
+
|
|
114
|
+
# Export to LUR package
|
|
115
|
+
puts "Exporting to LUR package..."
|
|
116
|
+
export_start = Time.now
|
|
117
|
+
repo.export_to_package(lur_output,
|
|
118
|
+
name: "Test Model",
|
|
119
|
+
version: "1.0",
|
|
120
|
+
serialization_format: :marshal)
|
|
121
|
+
export_time = Time.now - export_start
|
|
122
|
+
puts "Exported in #{export_time.round(2)}s"
|
|
123
|
+
puts "Package created: #{lur_output} (#{File.size(lur_output) / 1024}KB)"
|
|
124
|
+
puts
|
|
125
|
+
|
|
126
|
+
# Workflow 2: Load from LUR (fast)
|
|
127
|
+
puts "=" * 80
|
|
128
|
+
puts "Workflow 2: Fast loading from LUR"
|
|
129
|
+
puts "=" * 80
|
|
130
|
+
|
|
131
|
+
load_start = Time.now
|
|
132
|
+
loaded_repo = Lutaml::UmlRepository::Repository.from_package(lur_output)
|
|
133
|
+
load_time = Time.now - load_start
|
|
134
|
+
puts "Loaded in #{load_time.round(2)}s (vs #{parse_time.round(2)}s for parsing)"
|
|
135
|
+
puts "Speedup: #{(parse_time / load_time).round(1)}x faster"
|
|
136
|
+
puts
|
|
137
|
+
|
|
138
|
+
# Workflow 3: Validation
|
|
139
|
+
puts "=" * 80
|
|
140
|
+
puts "Workflow 3: Model validation"
|
|
141
|
+
puts "=" * 80
|
|
142
|
+
|
|
143
|
+
result = loaded_repo.validate
|
|
144
|
+
puts "Validation result: #{result.valid? ? 'VALID ✓' : 'INVALID ✗'}"
|
|
145
|
+
puts "Errors: #{result.errors.size}"
|
|
146
|
+
puts "Warnings: #{result.warnings.size}"
|
|
147
|
+
|
|
148
|
+
if result.errors.any?
|
|
149
|
+
puts "\nFirst 3 errors:"
|
|
150
|
+
result.errors.first(3).each do |error|
|
|
151
|
+
puts " - #{error}"
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
if result.warnings.any?
|
|
156
|
+
puts "\nFirst 3 warnings:"
|
|
157
|
+
result.warnings.first(3).each do |warning|
|
|
158
|
+
puts " - #{warning}"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
puts
|
|
162
|
+
|
|
163
|
+
# Workflow 4: Statistics
|
|
164
|
+
puts "=" * 80
|
|
165
|
+
puts "Workflow 4: Model statistics"
|
|
166
|
+
puts "=" * 80
|
|
167
|
+
|
|
168
|
+
stats = loaded_repo.statistics
|
|
169
|
+
puts "Model overview:"
|
|
170
|
+
puts " Packages: #{stats[:total_packages]}"
|
|
171
|
+
puts " Classes: #{stats[:total_classes]}"
|
|
172
|
+
puts " Data types: #{stats[:total_data_types]}"
|
|
173
|
+
puts " Enumerations: #{stats[:total_enums]}"
|
|
174
|
+
puts " Associations: #{stats[:total_associations]}"
|
|
175
|
+
puts " Diagrams: #{stats[:total_diagrams]}"
|
|
176
|
+
|
|
177
|
+
if stats[:max_package_depth]
|
|
178
|
+
puts "\nPackage structure:"
|
|
179
|
+
puts " Max depth: #{stats[:max_package_depth]}"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
if stats[:classes_by_stereotype]
|
|
183
|
+
puts "\nTop stereotypes:"
|
|
184
|
+
stats[:classes_by_stereotype].first(5).each do |stereotype, count|
|
|
185
|
+
puts " #{stereotype}: #{count}"
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
puts
|
|
189
|
+
|
|
190
|
+
# Workflow 5: Query and export
|
|
191
|
+
puts "=" * 80
|
|
192
|
+
puts "Workflow 5: Query and export"
|
|
193
|
+
puts "=" * 80
|
|
194
|
+
|
|
195
|
+
# Find all classes
|
|
196
|
+
all_classes = loaded_repo.classes_index
|
|
197
|
+
puts "Found #{all_classes.size} classes"
|
|
198
|
+
|
|
199
|
+
if all_classes.any?
|
|
200
|
+
# Sample some classes
|
|
201
|
+
sample_classes = all_classes.first(5)
|
|
202
|
+
puts "\nSample classes:"
|
|
203
|
+
sample_classes.each do |klass|
|
|
204
|
+
puts " - #{klass.name}"
|
|
205
|
+
if klass.respond_to?(:stereotype) && klass.stereotype
|
|
206
|
+
puts " Stereotype: #{klass.stereotype}"
|
|
207
|
+
end
|
|
208
|
+
if klass.respond_to?(:attributes) && klass.attributes
|
|
209
|
+
puts " Attributes: #{klass.attributes.size}"
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Search example
|
|
214
|
+
puts "\nSearch for 'Object':"
|
|
215
|
+
results = loaded_repo.search("Object", types: [:class])
|
|
216
|
+
puts " Found #{results[:total]} matches in class names"
|
|
217
|
+
end
|
|
218
|
+
puts
|
|
219
|
+
|
|
220
|
+
# Workflow 6: Smart caching demonstration
|
|
221
|
+
puts "=" * 80
|
|
222
|
+
puts "Workflow 6: Smart caching"
|
|
223
|
+
puts "=" * 80
|
|
224
|
+
|
|
225
|
+
puts "Smart caching automatically uses LUR if newer than source:"
|
|
226
|
+
puts
|
|
227
|
+
puts "# First run - builds from source"
|
|
228
|
+
puts "repo = Repository.from_file_cached('#{test_file}')"
|
|
229
|
+
puts "# Creates #{test_file.sub(/\.(xmi|qea)$/, '.lur')}"
|
|
230
|
+
puts
|
|
231
|
+
puts "# Subsequent runs - loads from cache"
|
|
232
|
+
puts "repo = Repository.from_file_cached('#{test_file}')"
|
|
233
|
+
puts "# Uses cached .lur (< 100ms)"
|
|
234
|
+
puts
|
|
235
|
+
|
|
236
|
+
# Cleanup
|
|
237
|
+
puts "=" * 80
|
|
238
|
+
puts "Cleanup"
|
|
239
|
+
puts "=" * 80
|
|
240
|
+
FileUtils.rm_f(lur_output)
|
|
241
|
+
puts "Removed test file: #{lur_output}"
|
|
242
|
+
puts
|
|
243
|
+
|
|
244
|
+
puts "=" * 80
|
|
245
|
+
puts "Workflow examples complete!"
|
|
246
|
+
puts "=" * 80
|
|
247
|
+
puts
|
|
248
|
+
puts "Summary of CLI commands:"
|
|
249
|
+
puts " build - Build LUR package from XMI/QEA"
|
|
250
|
+
puts " info - Show package metadata"
|
|
251
|
+
puts " validate - Validate model integrity"
|
|
252
|
+
puts " ls - List elements"
|
|
253
|
+
puts " tree - Show package hierarchy"
|
|
254
|
+
puts " inspect - Show element details"
|
|
255
|
+
puts " search - Full-text search"
|
|
256
|
+
puts " find - Find by criteria"
|
|
257
|
+
puts " stats - Model statistics"
|
|
258
|
+
puts " export - Export to various formats"
|
|
259
|
+
puts " docs - Generate documentation site"
|
|
260
|
+
puts " serve - Start web UI"
|
|
261
|
+
puts " repl - Interactive shell"
|
|
262
|
+
puts
|
|
263
|
+
puts "Run 'lutaml uml --help' for full command reference"
|