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,51 @@
|
|
|
1
|
+
# 28 - Extract XmlSanitizer (single-pass empty-element strip)
|
|
2
|
+
|
|
3
|
+
## Status: DONE → SUPERSEDED (2026-07-01)
|
|
4
|
+
|
|
5
|
+
The XmlSanitizer was extracted into its own class on this branch
|
|
6
|
+
and used as a post-processing pass on the Transformer output. It was
|
|
7
|
+
then deleted when the upstream fix (xmi gem VALUE_MAP) made it
|
|
8
|
+
unnecessary.
|
|
9
|
+
|
|
10
|
+
## History
|
|
11
|
+
|
|
12
|
+
### Step 1: extracted into its own class
|
|
13
|
+
Originally `Transformer#strip_empty_elements` was a 12-line
|
|
14
|
+
method on the transformer that worked around the xmi gem's
|
|
15
|
+
round-trip-oriented `VALUE_MAP`. The workaround used a while-loop
|
|
16
|
+
with Nokogiri XPath to remove truly-empty elements.
|
|
17
|
+
|
|
18
|
+
Extracted to `lib/ea/transformers/qea_to_xmi/xml_sanitizer.rb`
|
|
19
|
+
as a focused class with a single-pass depth-first post-order walk.
|
|
20
|
+
Spec at `spec/ea/transformers/qea_to_xmi/xml_sanitizer_spec.rb`
|
|
21
|
+
(95 LOC, 11 examples).
|
|
22
|
+
|
|
23
|
+
### Step 2: superseded by upstream VALUE_MAP fix
|
|
24
|
+
The xmi gem refactor (`refactor/owned-end-schema-gap`) changed
|
|
25
|
+
`Xmi::VALUE_MAP` to skip empty elements on serialization:
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
VALUE_MAP = {
|
|
29
|
+
from: { nil: :empty, empty: :empty, omitted: :empty },
|
|
30
|
+
to: { nil: :omitted, empty: :omitted, omitted: :omitted },
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
After this change, the ea transformer emits no `<child/>` empty
|
|
35
|
+
elements at all — the post-processing pass was unnecessary.
|
|
36
|
+
|
|
37
|
+
### Step 3: deleted
|
|
38
|
+
`lib/ea/transformers/qea_to_xmi/xml_sanitizer.rb` and its spec
|
|
39
|
+
were deleted. The transformer's `serialize` method now just calls
|
|
40
|
+
`build_root.to_xml(use_prefix: true)` with no sanitization.
|
|
41
|
+
|
|
42
|
+
## Verification
|
|
43
|
+
- Full ea suite: 2005 examples, 0 failures, 37 pending
|
|
44
|
+
- Output contains zero truly-empty elements (no `<generalization/>`,
|
|
45
|
+
no `<ownedEnd/>` without attributes).
|
|
46
|
+
- The transformation pipeline is now: build model graph →
|
|
47
|
+
`to_xml(use_prefix: true)` → return. One pass, no Nokogiri
|
|
48
|
+
re-parse, no element-mutation pass.
|
|
49
|
+
|
|
50
|
+
## Closes
|
|
51
|
+
TODO 21 §1 — "xmi gem empty-element rendering (architectural debt)".
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# 29 - OCP registry for QEA classifier builders
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-01)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
`Transformer#build_classifier` (transformer.rb:179-187) dispatches on
|
|
7
|
+
`obj.transformer_type` via a `case/when` statement:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
case kind
|
|
11
|
+
when :class then build_class(obj)
|
|
12
|
+
when :enumeration then build_enumeration(obj)
|
|
13
|
+
when :data_type then build_data_type(obj)
|
|
14
|
+
when :instance then build_instance(obj)
|
|
15
|
+
end
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
CLAUDE.md explicitly says "Registry pattern for OCP — new types are
|
|
19
|
+
added by registration, not by modifying `case/when`". With 4
|
|
20
|
+
branches the cost is low, but the project rule is the project rule.
|
|
21
|
+
|
|
22
|
+
TODO 21 defended the case statement by saying "polymorphism lives in
|
|
23
|
+
the xmi gem's xmi:type discriminator on PackagedElement". That is
|
|
24
|
+
true for *XMI rendering shape* (the xmi gem picks the right element
|
|
25
|
+
name + child set based on `xmi:type`). It is **not** true for the
|
|
26
|
+
decision of *which EA row maps to which builder* — that decision is
|
|
27
|
+
made by `EaObject#transformer_type` and dispatched here. Adding a
|
|
28
|
+
new builder (e.g., `:signal`, `:interface`) still requires modifying
|
|
29
|
+
this method.
|
|
30
|
+
|
|
31
|
+
## Fix
|
|
32
|
+
Replace the case statement with a frozen hash of lambdas. Builders
|
|
33
|
+
are looked up by `transformer_type` symbol; unknown kinds return nil
|
|
34
|
+
(preserving current "skip" behaviour).
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
CLASSIFIER_BUILDERS = {
|
|
38
|
+
class: ->(t, o) { t.build_class(o) },
|
|
39
|
+
enumeration: ->(t, o) { t.build_enumeration(o) },
|
|
40
|
+
data_type: ->(t, o) { t.build_data_type(o) },
|
|
41
|
+
instance: ->(t, o) { t.build_instance(o) },
|
|
42
|
+
}.freeze
|
|
43
|
+
|
|
44
|
+
def build_classifier(obj)
|
|
45
|
+
kind = obj.transformer_type || obj.object_type&.downcase&.to_sym
|
|
46
|
+
CLASSIFIER_BUILDERS[kind]&.call(self, obj)
|
|
47
|
+
end
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Adding a new kind now means adding one entry to the constant, no
|
|
51
|
+
method body change.
|
|
52
|
+
|
|
53
|
+
## Verification
|
|
54
|
+
- Behaviour unchanged: unknown kinds return nil (skipped downstream
|
|
55
|
+
via `compact`).
|
|
56
|
+
- Spec for `build_classifier` covers all 4 known kinds and the
|
|
57
|
+
unknown-kind fall-through.
|
|
58
|
+
- Project rule "Registry pattern for OCP" now satisfied.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 30 - Replace ad-hoc Hash return with Struct in build_association_end
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-01)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
`Transformer#build_association_end` (transformer.rb:326-344) returns
|
|
7
|
+
a two-key Hash:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
{ xmi_id: end_id, model: model }
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The caller (`build_association`) destructures it as
|
|
14
|
+
`dest_end[:xmi_id]`, `dest_end[:model]`. Ad-hoc Hash returns are
|
|
15
|
+
fragile — typos in keys (`[:xmii_id]`) fail silently as nil, and
|
|
16
|
+
the contract is invisible at the method signature.
|
|
17
|
+
|
|
18
|
+
## Fix
|
|
19
|
+
Define a frozen Struct for the return type:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
AssociationEnd = Struct.new(:xmi_id, :model)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`build_association_end` returns `AssociationEnd.new(end_id, model)`.
|
|
26
|
+
Caller uses `dest_end.xmi_id`, `dest_end.model` — typos now raise
|
|
27
|
+
NoMethodError at the call site.
|
|
28
|
+
|
|
29
|
+
The Struct lives in the QeaToXmi namespace
|
|
30
|
+
(`Ea::Transformers::QeaToXmi::AssociationEnd`) so it can be referenced
|
|
31
|
+
in specs and reused by future wire-up code.
|
|
32
|
+
|
|
33
|
+
## Verification
|
|
34
|
+
- `build_association` reads `dest_end.xmi_id` / `dest_end.model`
|
|
35
|
+
instead of hash keys.
|
|
36
|
+
- Spec covers `build_association_end` directly, asserting the Struct
|
|
37
|
+
shape and the synthesised IDs.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# 31 - Specs for IdAllocator
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-01)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
`Ea::Transformers::QeaToXmi::IdAllocator` is a public class with two
|
|
7
|
+
public methods (`allocate`, `for_multiplicity` at the time of the
|
|
8
|
+
audit; after TODO 23 it has just `allocate`). It has counter state,
|
|
9
|
+
seed-based memoisation, and prefix-based formatting. None of this
|
|
10
|
+
behaviour is directly tested — it is only exercised transitively via
|
|
11
|
+
the Transformer specs.
|
|
12
|
+
|
|
13
|
+
## Fix
|
|
14
|
+
New `spec/ea/transformers/qea_to_xmi/id_allocator_spec.rb`:
|
|
15
|
+
|
|
16
|
+
- `allocate` returns prefixed, zero-padded, monotonic IDs.
|
|
17
|
+
- Same seed → same ID (memoisation).
|
|
18
|
+
- Different seeds → different IDs.
|
|
19
|
+
- `nil` seed → still allocates (no memoisation).
|
|
20
|
+
- After TODO 25: parent GUID incorporation — `parent_guid` arg
|
|
21
|
+
produces the Sparx `EAID_LI000001_<guid_tail>` format.
|
|
22
|
+
- Multiple parents with the same counter values produce distinct
|
|
23
|
+
full IDs (GUID suffix disambiguates).
|
|
24
|
+
|
|
25
|
+
## Verification
|
|
26
|
+
File exists, runs cleanly with `bundle exec rspec`, and covers the
|
|
27
|
+
public `allocate` API exhaustively.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# 32 - Phase 2 sentinel specs (track xmi gem gaps)
|
|
2
|
+
|
|
3
|
+
## Status: ✅ DONE (2026-07-01) — sentinels flipped as xmi gem schema migrated
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
TODO 21 documented four attribute gaps the xmi gem didn't model.
|
|
7
|
+
The original spec suite did not assert the absence of these
|
|
8
|
+
attributes. When the xmi gem added support, nothing in the ea test
|
|
9
|
+
suite signaled that we should wire them up.
|
|
10
|
+
|
|
11
|
+
## Original fix (sentinels)
|
|
12
|
+
Added sentinel specs that explicitly asserted these attributes were
|
|
13
|
+
not emitted, with comments pointing at TODO 21. When the xmi gem
|
|
14
|
+
added support, the first PR to wire the attribute up would need to
|
|
15
|
+
flip the assertion to positive — making the wiring visible in code
|
|
16
|
+
review.
|
|
17
|
+
|
|
18
|
+
## Update after xmi gem schema migration
|
|
19
|
+
The xmi gem refactor branch `refactor/owned-end-schema-gap` landed
|
|
20
|
+
schema support for:
|
|
21
|
+
- `visibility` on Property / Operation / Parameter / OwnedEnd / Class
|
|
22
|
+
- `isAbstract` on packagedElement
|
|
23
|
+
- `aggregation` on OwnedEnd
|
|
24
|
+
- `classifier` on InstanceSpecification
|
|
25
|
+
- `upperValue`/`lowerValue` child models on OwnedEnd (TODO 26)
|
|
26
|
+
- `Slot`, `OpaqueExpression`, `InterfaceRealization` new models
|
|
27
|
+
|
|
28
|
+
The ea transformer was extended to wire up visibility, isAbstract,
|
|
29
|
+
aggregation (containment mapping), classifier (pdata1 mapping), and
|
|
30
|
+
the OwnedEnd child elements.
|
|
31
|
+
|
|
32
|
+
## Current spec state
|
|
33
|
+
The original "Phase 2 gaps" sentinel block has split into two:
|
|
34
|
+
|
|
35
|
+
### Phase 2 wiring (xmi gem schema migration landed)
|
|
36
|
+
Positive assertions for the four attributes now emitted:
|
|
37
|
+
- visibility on Property
|
|
38
|
+
- visibility on Operation
|
|
39
|
+
- isAbstract on packagedElement
|
|
40
|
+
- upperValue/lowerValue on ownedEnd
|
|
41
|
+
|
|
42
|
+
### Phase 2 gaps still deferred
|
|
43
|
+
Negative assertions for two attributes the basic.qea fixture does
|
|
44
|
+
not exercise (no data to wire against):
|
|
45
|
+
- aggregation on ownedEnd (no composite/shared containment in fixture)
|
|
46
|
+
- classifier on InstanceSpecification (no pdata1 set in fixture)
|
|
47
|
+
|
|
48
|
+
When a fixture with relevant data is available, these flip to positive.
|
|
49
|
+
|
|
50
|
+
## Verification
|
|
51
|
+
All qea_to_xmi specs pass (104 examples). Output now emits visibility
|
|
52
|
+
on all 102 attributes, isAbstract on all 65 classes, upperValue and
|
|
53
|
+
lowerValue on all 102 attributes + 80 association ends.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# 33 - normalize_lower was identity — fold into Cardinality module
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-01, folded into TODO 27)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
`Transformer#normalize_lower` (transformer.rb:474-476) was:
|
|
7
|
+
|
|
8
|
+
```ruby
|
|
9
|
+
def normalize_lower(raw)
|
|
10
|
+
raw.to_s
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Pure identity — does nothing. Either remove it (callers can `.to_s`
|
|
14
|
+
themselves) or implement actual normalisation matching how
|
|
15
|
+
`normalize_upper` handles the `*` token.
|
|
16
|
+
|
|
17
|
+
## Fix
|
|
18
|
+
Folded into the Cardinality extraction (TODO 27). The new
|
|
19
|
+
`Cardinality.normalize_lower` returns the default `"0"` for empty
|
|
20
|
+
input, matching how real Sparx XMI represents unspecified lower
|
|
21
|
+
bounds (always emits `<lowerValue value="0"/>`, never empty).
|
|
22
|
+
|
|
23
|
+
This change also supports TODO 26 (upperValue/lowerValue count gap)
|
|
24
|
+
— always emitting `lowerValue` requires a sane default for the
|
|
25
|
+
"no bound specified" case.
|
|
26
|
+
|
|
27
|
+
## Verification
|
|
28
|
+
- Old `normalize_lower` identity removed from transformer.
|
|
29
|
+
- `Cardinality.normalize_lower("")` returns `"0"`.
|
|
30
|
+
- `Cardinality.normalize_lower("1")` returns `"1"`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# 34 - Document member-end order + harmonise RT prefix
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-01)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
Two small clarity issues in `lib/ea/transformers/qea_to_xmi/transformer.rb`:
|
|
7
|
+
|
|
8
|
+
1. **Implicit member-end order.** `build_association` (line 314-324)
|
|
9
|
+
emits `dest_end` first, then `src_end`. EA round-trip depends on
|
|
10
|
+
this ordering but no comment explains why. A future contributor
|
|
11
|
+
re-ordering for "tidiness" would silently break round-trip
|
|
12
|
+
fidelity.
|
|
13
|
+
2. **Undocumented "RT" prefix.** `build_return_parameter` (line 400)
|
|
14
|
+
synthesises IDs with `prefix: "RT"`. The `IdAllocator` documents
|
|
15
|
+
well-known Sparx prefixes (LI, OE, SL, NL, DB) but not RT.
|
|
16
|
+
|
|
17
|
+
## Fix
|
|
18
|
+
|
|
19
|
+
1. Add a one-line comment at the member-end ordering site explaining
|
|
20
|
+
the Sparx convention. The ordering comes from how Sparx EA
|
|
21
|
+
serialises its `t_connector` rows: destination role first in
|
|
22
|
+
`<memberEnd>`, source role second.
|
|
23
|
+
2. Add `RETURN_PARAMETER = "RT"` to IdAllocator's well-known prefix
|
|
24
|
+
list with a comment explaining what it stands for. Update
|
|
25
|
+
`build_return_parameter` to reference the constant.
|
|
26
|
+
|
|
27
|
+
## Verification
|
|
28
|
+
- Diff shows the comment + constant addition; no behaviour change.
|
|
29
|
+
- Existing specs continue to pass.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# 35 - Walk t_object.RunState for instance specification slots
|
|
2
|
+
|
|
3
|
+
## Status: ✅ DONE (2026-07-03)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
`build_instance` originally emitted an empty `slot: []` array, which
|
|
7
|
+
silently dropped the run-state data that real Sparx XMI carries as
|
|
8
|
+
`<slot>` children of `<packagedElement type="uml:InstanceSpecification">`.
|
|
9
|
+
|
|
10
|
+
EA serialises run-state in `t_object.RunState` as a delimited string:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
@VAR;Variable=<name>;Value=<value>;Op=<op>;@ENDVAR;
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Multiple `@VAR` blocks concatenate directly. Each block maps to one
|
|
17
|
+
UML Slot.
|
|
18
|
+
|
|
19
|
+
## Fix
|
|
20
|
+
|
|
21
|
+
### RunState module
|
|
22
|
+
`lib/ea/transformers/qea_to_xmi/run_state.rb` is a pure-function
|
|
23
|
+
parser. Returns an array of `Binding` structs (`Struct.new(:variable,
|
|
24
|
+
:value, :op)`). The `Binding#body` method renders the Sparx wire form
|
|
25
|
+
(`Op==` + `Value=Alice` → `body="=Alice"`).
|
|
26
|
+
|
|
27
|
+
### Transformer wiring
|
|
28
|
+
- `slots_for(obj)` walks `RunState.parse(obj.runstate)` and emits one
|
|
29
|
+
`Xmi::Uml::Slot` per binding.
|
|
30
|
+
- `build_slot(instance, binding)` constructs the Slot with:
|
|
31
|
+
- `xmi:id` from `IdAllocator.allocate(prefix: SLOT, ...)`
|
|
32
|
+
- `definingFeature` resolved by looking up the named attribute on
|
|
33
|
+
the instance's classifier (via `t_object.classifier`)
|
|
34
|
+
- one `OpaqueExpression` value carrying the body
|
|
35
|
+
- `build_slot_value` builds the OpaqueExpression with `xmi:id` from
|
|
36
|
+
`IdAllocator.allocate(prefix: OPAQUE_EXPRESSION, ...)`.
|
|
37
|
+
- `defining_feature_for(instance, binding)` looks up the classifier
|
|
38
|
+
via `obj.classifier.to_i` (NOT `pdata1` as originally documented —
|
|
39
|
+
the live `t_object.classifier` column holds the ea_object_id of
|
|
40
|
+
the classifier directly).
|
|
41
|
+
|
|
42
|
+
### ID prefixes used
|
|
43
|
+
Both `SLOT` (`"SL"`) and `OPAQUE_EXPRESSION` (`"OE"`) are already on
|
|
44
|
+
`IdAllocator`'s well-known-prefix list — no constant additions.
|
|
45
|
+
|
|
46
|
+
## Discovery: t_object.classifier column
|
|
47
|
+
The original TODO 35 draft assumed `pdata1` held the classifier ID.
|
|
48
|
+
Investigation during implementation showed:
|
|
49
|
+
|
|
50
|
+
- `pdata1`: always `nil` for `Object`-type rows in basic.qea.
|
|
51
|
+
- `classifier`: an Integer column holding the classifier's
|
|
52
|
+
`ea_object_id` directly. Zero when no classifier is set.
|
|
53
|
+
|
|
54
|
+
This matches what real Sparx XMI emits: InstanceSpecification rows
|
|
55
|
+
without a classifier have no `classifier="..."` attribute on the
|
|
56
|
+
`<packagedElement>`; rows with a classifier do.
|
|
57
|
+
|
|
58
|
+
## Verification
|
|
59
|
+
- Output for basic.qea: 22 slots, 20 with `definingFeature` (the 2
|
|
60
|
+
without come from InstanceSpecifications that have no classifier).
|
|
61
|
+
This matches the reference `spec/fixtures/basic.xmi` exactly.
|
|
62
|
+
- Each slot carries one `<value>` child typed as
|
|
63
|
+
`uml:OpaqueExpression` with `body="=Value..."`.
|
|
64
|
+
- Slot IDs use the Sparx `EAID_SL<NN>__<guid>` format; OpaqueExpression
|
|
65
|
+
IDs use `EAID_OE<NN>__<guid>`.
|
|
66
|
+
- RunState module specs: 13 examples, 0 failures (pure-function
|
|
67
|
+
parser, edge cases covered).
|
|
68
|
+
- Slot emission specs in transformer_spec.rb: 4 new examples
|
|
69
|
+
asserting count, body shape, definingFeature presence, ID prefix.
|
|
70
|
+
|
|
71
|
+
## Sentinel flipped
|
|
72
|
+
The "Phase 2 gaps still deferred" sentinel block had a negative
|
|
73
|
+
assertion for `classifier on InstanceSpecification`. With this
|
|
74
|
+
wiring landed, the spec flipped to a positive assertion. The
|
|
75
|
+
`aggregation on ownedEnd` sentinel remains negative (basic.qea
|
|
76
|
+
carries no composite/shared containment examples).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# 36 - Wire interfaceRealization for Interface-implementing classes
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-02)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
Sparx XMI emits `<interfaceRealization>` as a child of the
|
|
7
|
+
implementing `<packagedElement type="uml:Class">`, not as a
|
|
8
|
+
package-level relationship. The ea transformer was not emitting
|
|
9
|
+
these at all — Realization connectors were silently dropped by
|
|
10
|
+
`package_level_relationships` (Realization is not in
|
|
11
|
+
`RELATIONSHIP_AT_PACKAGE_LEVEL`).
|
|
12
|
+
|
|
13
|
+
## Fix
|
|
14
|
+
|
|
15
|
+
### xmi gem
|
|
16
|
+
`Xmi::Uml::InterfaceRealization` model added in the xmi gem refactor
|
|
17
|
+
branch `refactor/owned-end-schema-gap`. `Xmi::Uml::PackagedElement`
|
|
18
|
+
declares `interface_realization` as a child-element collection.
|
|
19
|
+
|
|
20
|
+
### ea transformer
|
|
21
|
+
- New `interface_realizations_for(obj)` method on
|
|
22
|
+
`Ea::Transformers::QeaToXmi::Transformer`. Walks the realization
|
|
23
|
+
connectors where this class is the source (client) and emits one
|
|
24
|
+
`InterfaceRealization` model per connector.
|
|
25
|
+
- New `build_interface_realization(conn)` builder. Wires
|
|
26
|
+
`client` (this class), `supplier` and `contract` (the target
|
|
27
|
+
Interface — supplier and contract are the same when the target is
|
|
28
|
+
an Interface; if EA's data model ever distinguishes, this is the
|
|
29
|
+
single place to change).
|
|
30
|
+
- `build_class` now passes `interface_realization:
|
|
31
|
+
interface_realizations_for(obj)`.
|
|
32
|
+
- New `realization_connectors(obj)` helper — a specialization of
|
|
33
|
+
`inheritance_connectors(obj, "Realization")` for readability.
|
|
34
|
+
|
|
35
|
+
## Verification
|
|
36
|
+
- All 113 qea_to_xmi specs pass.
|
|
37
|
+
- `basic.qea` has 0 Realization connectors, so the output has 0
|
|
38
|
+
`<interfaceRealization>` elements. The path is exercised by the
|
|
39
|
+
xmi gem's `sparx-instance-specification.xmi` fixture (parser side)
|
|
40
|
+
and by structural round-trip — when the ea transformer is given an
|
|
41
|
+
EA database with Realization connectors, it will produce the
|
|
42
|
+
correct child elements.
|
|
43
|
+
|
|
44
|
+
## Sentinel
|
|
45
|
+
The Phase 2 sentinel spec block in
|
|
46
|
+
`spec/ea/transformers/qea_to_xmi/transformer_spec.rb` keeps two
|
|
47
|
+
negative sentinels for cases `basic.qea` doesn't exercise
|
|
48
|
+
(aggregation on ownedEnd, classifier on InstanceSpecification).
|
|
49
|
+
Realization does not need a sentinel because the wiring path is
|
|
50
|
+
already type-checked end-to-end.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 37 - Visibility.boolean_from_flag returns real Ruby booleans
|
|
2
|
+
|
|
3
|
+
## Status: DONE (2026-07-02)
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
`Ea::Transformers::QeaToXmi::Visibility.boolean_from_flag` returned
|
|
7
|
+
the strings `"true"` / `"false"` for EA's `"1"` / `"0"` flags. The
|
|
8
|
+
xmi gem's `is_*` attributes (`is_abstract`, `is_static`,
|
|
9
|
+
`is_ordered`, `is_derived`, `is_unique`, `is_id`, `is_read_only`,
|
|
10
|
+
`is_query`) were initially typed as `:string` so this worked — but
|
|
11
|
+
the xmi gem refactor migrated them to `:boolean` per UML 2.5 type
|
|
12
|
+
semantics.
|
|
13
|
+
|
|
14
|
+
After the migration, the ea-side `boolean_from_flag` returning
|
|
15
|
+
strings caused silent type coercion (Ruby `"true" == true` is
|
|
16
|
+
false; lutaml-model was lenient but the type contract was wrong).
|
|
17
|
+
|
|
18
|
+
## Fix
|
|
19
|
+
Return actual Ruby `true` / `false` (or `nil` when EA's field is
|
|
20
|
+
blank). Drop the ternary string coercion. Update the spec to assert
|
|
21
|
+
`be(true)` / `be(false)` instead of `eq("true")` / `eq("false")`.
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
def boolean_from_flag(raw)
|
|
25
|
+
return nil if raw.nil? || raw.to_s.strip.empty?
|
|
26
|
+
|
|
27
|
+
raw.to_s == "1"
|
|
28
|
+
end
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Verification
|
|
32
|
+
- visibility_spec.rb: 6 examples pass with the new boolean contract.
|
|
33
|
+
- Output `isAbstract="false"` count for basic.qea: 80 (one per
|
|
34
|
+
Class). All emit as lowercase XSD booleans per the xmi gem's
|
|
35
|
+
lutaml-model :boolean type.
|
|
36
|
+
- Full qea_to_xmi suite passes (113 examples).
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# diagram_styles.yml - Configurable EA Diagram Styling
|
|
2
|
+
# This file defines the default styling for LutaML diagram generation
|
|
3
|
+
|
|
4
|
+
# Global defaults - applied when no other configuration matches
|
|
5
|
+
defaults:
|
|
6
|
+
colors:
|
|
7
|
+
background: "#FFFFFF"
|
|
8
|
+
default_fill: "#E0E0E0"
|
|
9
|
+
default_stroke: "#000000"
|
|
10
|
+
text: "#000000"
|
|
11
|
+
|
|
12
|
+
fonts:
|
|
13
|
+
default:
|
|
14
|
+
family: "Carlito, Arial, sans-serif"
|
|
15
|
+
size: 9
|
|
16
|
+
weight: 400
|
|
17
|
+
style: normal
|
|
18
|
+
|
|
19
|
+
class_name:
|
|
20
|
+
family: "Carlito, Arial, sans-serif"
|
|
21
|
+
size: 9
|
|
22
|
+
weight: 700 # bold
|
|
23
|
+
style: normal
|
|
24
|
+
|
|
25
|
+
stereotype:
|
|
26
|
+
family: "Carlito, Arial, sans-serif"
|
|
27
|
+
size: 9
|
|
28
|
+
weight: 400
|
|
29
|
+
style: normal
|
|
30
|
+
|
|
31
|
+
attribute:
|
|
32
|
+
family: "Carlito, Arial, sans-serif"
|
|
33
|
+
size: 9
|
|
34
|
+
weight: 400
|
|
35
|
+
style: normal
|
|
36
|
+
|
|
37
|
+
operation:
|
|
38
|
+
family: "Carlito, Arial, sans-serif"
|
|
39
|
+
size: 9
|
|
40
|
+
weight: 400
|
|
41
|
+
style: normal
|
|
42
|
+
|
|
43
|
+
box:
|
|
44
|
+
stroke_width: 2
|
|
45
|
+
stroke_linecap: round
|
|
46
|
+
stroke_linejoin: bevel
|
|
47
|
+
corner_radius: 0
|
|
48
|
+
padding: 5
|
|
49
|
+
fill_opacity: 1.0
|
|
50
|
+
stroke_opacity: 1.0
|
|
51
|
+
|
|
52
|
+
text:
|
|
53
|
+
visibility_public: "+"
|
|
54
|
+
visibility_private: "-"
|
|
55
|
+
visibility_protected: "#"
|
|
56
|
+
visibility_package: "~"
|
|
57
|
+
cardinality_format: "[%s]"
|
|
58
|
+
stereotype_format: "«%s»"
|
|
59
|
+
|
|
60
|
+
# Stereotype-based styling
|
|
61
|
+
# These apply when elements have specific stereotypes
|
|
62
|
+
stereotypes:
|
|
63
|
+
DataType:
|
|
64
|
+
colors:
|
|
65
|
+
fill: "#FFCCFF" # Pink for i-UR DataTypes
|
|
66
|
+
stroke: "#000000"
|
|
67
|
+
fonts:
|
|
68
|
+
class_name:
|
|
69
|
+
weight: 700
|
|
70
|
+
style: italic
|
|
71
|
+
|
|
72
|
+
FeatureType:
|
|
73
|
+
colors:
|
|
74
|
+
fill: "#FFFFCC" # Yellow for CityGML FeatureTypes
|
|
75
|
+
stroke: "#000000"
|
|
76
|
+
|
|
77
|
+
GMLType:
|
|
78
|
+
colors:
|
|
79
|
+
fill: "#CCFFCC" # Green for GML Types
|
|
80
|
+
stroke: "#000000"
|
|
81
|
+
|
|
82
|
+
Interface:
|
|
83
|
+
colors:
|
|
84
|
+
fill: "#FFFFEE"
|
|
85
|
+
stroke: "#000000"
|
|
86
|
+
fonts:
|
|
87
|
+
class_name:
|
|
88
|
+
style: italic
|
|
89
|
+
|
|
90
|
+
Enumeration:
|
|
91
|
+
colors:
|
|
92
|
+
fill: "#FFE6CC"
|
|
93
|
+
stroke: "#000000"
|
|
94
|
+
|
|
95
|
+
Abstract:
|
|
96
|
+
fonts:
|
|
97
|
+
class_name:
|
|
98
|
+
style: italic
|
|
99
|
+
|
|
100
|
+
# Package-based styling (optional)
|
|
101
|
+
# Supports wildcards: "CityGML::*" matches any package starting with "CityGML::"
|
|
102
|
+
packages:
|
|
103
|
+
"CityGML::*":
|
|
104
|
+
colors:
|
|
105
|
+
fill: "#FFFFCC"
|
|
106
|
+
|
|
107
|
+
"i-UR::*":
|
|
108
|
+
colors:
|
|
109
|
+
fill: "#FFCCFF"
|
|
110
|
+
|
|
111
|
+
"gml::*":
|
|
112
|
+
colors:
|
|
113
|
+
fill: "#CCFFCC"
|
|
114
|
+
|
|
115
|
+
# Class-specific overrides (highest priority after EA data)
|
|
116
|
+
# These take precedence over package and stereotype styling
|
|
117
|
+
classes: {}
|
|
118
|
+
|
|
119
|
+
# Connector styling
|
|
120
|
+
connectors:
|
|
121
|
+
generalization:
|
|
122
|
+
arrow:
|
|
123
|
+
type: hollow_triangle
|
|
124
|
+
size: 10
|
|
125
|
+
line:
|
|
126
|
+
stroke_width: 1
|
|
127
|
+
stroke: "#000000"
|
|
128
|
+
fill: none
|
|
129
|
+
|
|
130
|
+
association:
|
|
131
|
+
arrow:
|
|
132
|
+
type: open_arrow
|
|
133
|
+
size: 8
|
|
134
|
+
line:
|
|
135
|
+
stroke_width: 1
|
|
136
|
+
stroke: "#000000"
|
|
137
|
+
labels:
|
|
138
|
+
show_role_names: true
|
|
139
|
+
show_cardinality: true
|
|
140
|
+
font:
|
|
141
|
+
family: "Carlito, Arial, sans-serif"
|
|
142
|
+
size: 8
|
|
143
|
+
|
|
144
|
+
dependency:
|
|
145
|
+
arrow:
|
|
146
|
+
type: open_arrow
|
|
147
|
+
size: 8
|
|
148
|
+
line:
|
|
149
|
+
stroke_width: 1
|
|
150
|
+
stroke: "#000000"
|
|
151
|
+
stroke_dasharray: "5,5"
|
|
152
|
+
|
|
153
|
+
aggregation:
|
|
154
|
+
arrow:
|
|
155
|
+
type: diamond
|
|
156
|
+
size: 10
|
|
157
|
+
fill: white
|
|
158
|
+
line:
|
|
159
|
+
stroke_width: 1
|
|
160
|
+
stroke: "#000000"
|
|
161
|
+
|
|
162
|
+
composition:
|
|
163
|
+
arrow:
|
|
164
|
+
type: filled_diamond
|
|
165
|
+
size: 10
|
|
166
|
+
fill: black
|
|
167
|
+
line:
|
|
168
|
+
stroke_width: 1
|
|
169
|
+
stroke: "#000000"
|
|
170
|
+
|
|
171
|
+
realization:
|
|
172
|
+
arrow:
|
|
173
|
+
type: hollow_triangle
|
|
174
|
+
size: 10
|
|
175
|
+
line:
|
|
176
|
+
stroke_width: 1
|
|
177
|
+
stroke: "#000000"
|
|
178
|
+
stroke_dasharray: "5,5"
|
|
179
|
+
|
|
180
|
+
# Legend configuration
|
|
181
|
+
legend:
|
|
182
|
+
enabled: true
|
|
183
|
+
position: bottom_right
|
|
184
|
+
title: "Legend"
|
|
185
|
+
box:
|
|
186
|
+
fill: "#FFFFFF"
|
|
187
|
+
stroke: "#000000"
|
|
188
|
+
stroke_width: 1
|
|
189
|
+
padding: 10
|
|
190
|
+
font:
|
|
191
|
+
family: "Carlito, Arial, sans-serif"
|
|
192
|
+
size: 9
|
|
193
|
+
weight: 400
|
|
194
|
+
entries:
|
|
195
|
+
- label: "i-UR DataTypes"
|
|
196
|
+
color: "#FFCCFF"
|
|
197
|
+
- label: "CityGML FeatureTypes"
|
|
198
|
+
color: "#FFFFCC"
|
|
199
|
+
- label: "GML Types"
|
|
200
|
+
color: "#CCFFCC"
|