Skip to content

fix(intent/edm): the .edm must be a lossless source for the derived .model (#6826) - #6857

Open
NicoleNG18 wants to merge 5 commits into
eclipse-dirigible:masterfrom
NicoleNG18:fix/6826-edm-lossless-source
Open

fix(intent/edm): the .edm must be a lossless source for the derived .model (#6826)#6857
NicoleNG18 wants to merge 5 commits into
eclipse-dirigible:masterfrom
NicoleNG18:fix/6826-edm-lossless-source

Conversation

@NicoleNG18

Copy link
Copy Markdown
Contributor

Fixes #6826.

Problem

Intent Generate writes <name>.edm and a complete <name>.model together. But the .edm is also the file the Entity Modeler opens, and saving a diagram rebuilds the .model from the .edm (serializer.js rewrites <entities>, then transformer-on-save.js runs transform-edm.js). The generator skipped every structured (List/Map) entity/property value when rendering the .edm, so those values lived only in the .model twin and were silently dropped the moment the .edm was used to rebuild the .model — e.g. saving a sales-invoice diagram stripped its rollupGuard, and the payment-limit guard stopped firing.

Eight structured values were affected: entity-level rollupGuard, checks, labelParts, aggregateKeys, groupingKeys, relatedEntities, and property-level lookupColumns (plus uniqueConstraints — see below).

Fix

Represent each structured value as a JSON string in a flat XML attribute. A flat attribute survives mxGraph's codec untouched, so this is lossless through both the visual diagram editor open→save and the text-edit/regeneration path, with no editor.js/model.js/mxCodec changes:

  • EdmIntentGenerator — emit the structured values as JSON attributes in both the <entities> block and the <mxGraphModel> cell values (appendModelAttribute / appendStructuredAttribute, compact non-HTML-escaping Gson). Scalars unchanged; the cell value now carries every entity attribute (not a reduced allow-list) so a visual save preserves intent-era scalars too.
  • serializer.js — replace the hardcoded allow-list with generic own-property preservation (extraAttributes JSON-encodes object-valued fields), so intent-era attributes are never dropped on save.
  • transform-edm.jsJSON.parse the known structured keys back into objects when rebuilding the .model.

uniqueConstraints is deliberately excluded from this fix: the composite-unique-key modeler feature (already on master) owns it via a dedicated <constraints>/<uniqueKey> section that transformUniqueKey rebuilds. Handling it here too would write it twice and round-trip it as a duplicate.

Testing

  • EdmModelRoundTripIT (new, HTTP-only): generates from an intent exercising the structured values, captures the intent's .model as the oracle, saves the .edm back through the real ide-workspace-on-save transform, and asserts a structural diff — every entity/property key must survive intact. This makes "a structured attribute cannot ship without .edm serialization support" enforceable: a dropped attribute fails as a missing key, and a value written but not parsed back fails as a mismatch. (This diff caught groupingKeys during development.)
  • All existing EdmIntentGeneratorTest + IntentParserTest pass (162); javadoc (release profile) and formatter clean.

🤖 Generated with Claude Code

NicoleNG18 and others added 5 commits August 19, 2026 22:31
…el (eclipse-dirigible#6826)

The 7 structured (List/Map) entity/property values - rollupGuard, checks,
uniqueConstraints, labelParts, aggregateKeys, relatedEntities, and property-level
lookupColumns - were skipped when rendering the .edm (the Iterable/Map guard),
lived only in the .model twin, and vanished the moment the .edm was used to rebuild
the .model (opening a diagram and saving dropped rollupGuard etc.).

Represent each structured value as a JSON string in a flat XML attribute. A flat
attribute survives mxGraph's codec untouched, so this is lossless through BOTH the
visual diagram editor open->save and the text-edit/regeneration path, with no
editor.js/model.js/mxCodec changes:

- EdmIntentGenerator: emit the 7 as JSON attributes in both the <entities> block
  and the <mxGraphModel> cell values (appendModelAttribute / appendStructuredAttribute,
  compact non-HTML-escaping Gson; scalars unchanged, unknown non-scalars still skipped).
- serializer.js: replace the hardcoded allow-list with generic attribute preservation
  (extraAttributes JSON-encodes object-valued fields) so intent-era scalars AND the
  structured values are never dropped on save.
- transform-edm.js: JSON.parse the 7 known structured keys back into objects when
  building the .model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…m -> .model (eclipse-dirigible#6826)

Generates from an intent exercising the structured (List/Map) values that were being
dropped - labelParts, uniqueConstraints, relatedEntities, checks, rollupGuard,
lookupColumns - captures the intent's .model as the oracle, then saves the .edm back
through the workspace API (firing the same ide-workspace-on-save transform the editor's
save runs) and asserts each structured value survives intact in the regenerated .model.
A completeness walk fails on any attribute that reaches the .model as an unparsed JSON
string, so a future structured attribute cannot ship without transform-edm handling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ue (eclipse-dirigible#6826)

appendEntityValue wrote only a reduced allow-list of scalar attributes into the
<mxGraphModel> cell value, so a live EDM-editor open->save (serializer.js re-serializes
the DECODED cell, not the <entities> block) dropped every intent-era attribute not on
that list - the "drops the intent-era attributes wholesale" half of the issue. The cell
value now carries every entity attribute (scalars verbatim, structured values as JSON),
matching the <entities> block, while preserving the mxObjectCodec type/entityType markers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…raints (eclipse-dirigible#6826)

The composite-unique-key modeler feature now emits uniqueConstraints as a top-level
<constraints>/<uniqueKey> section that transform-edm rebuilds. Handling it as a JSON
attribute here too wrote it twice and round-tripped it as a duplicate. Drop
uniqueConstraints from this fix's structured-attribute set (Java + transform-edm), so it
is written and parsed once by the feature; this fix keeps the other six structured values
(rollupGuard, checks, labelParts, aggregateKeys, relatedEntities, lookupColumns). The
round-trip IT asserts uniqueConstraints survives exactly once (no duplication).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eclipse-dirigible#6826)

Address review findings on the round-trip test and one gap it exposed:

- Replace the JSON-string-pattern completeness walk with a structural diff of every
  entity/property key between the intent .model (oracle) and the one rebuilt from the
  .edm. This (a) removes the false positive on scalars that are legitimately JSON
  strings (e.g. widgetDependsOnValueCases) by comparing parsed values, and (b) actually
  enforces "a structured attribute cannot ship without .edm serialization" - a dropped
  attribute is caught as a missing key.
- That diff immediately caught a real drop: groupingKeys (a List<Map> emitted for an
  aggregate/rollup source) was not in the structured set, so it was skipped from the
  .edm and lost on round-trip. Add it to STRUCTURED_ATTRIBUTES (Java) and ENTITY_STRUCTURED
  (transform-edm.js).
- serializer.js extraAttributes: iterate OWN properties only (hasOwnProperty guard), so it
  no longer depends on ENTITY_HANDLED/PROPERTY_HANDLED being complete supersets of the
  model.js prototype defaults; annotate the empty-string skip.
- Cross-reference the coupled Java/JS structured lists in comments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant