Skip to content

feat(wme): show OCL kind badge + add 'Library with OCL' template#124

Merged
ArmenSl merged 10 commits into
developfrom
feature/wme-ocl-pre-post
May 6, 2026
Merged

feat(wme): show OCL kind badge + add 'Library with OCL' template#124
ArmenSl merged 10 commits into
developfrom
feature/wme-ocl-pre-post

Conversation

@ArmenSl
Copy link
Copy Markdown
Collaborator

@ArmenSl ArmenSl commented May 5, 2026

Summary

  • Show a small italic stereotype badge («inv» / «pre» / «post» plus the target method name for pre/post) above the OCL constraint box on the canvas, derived from the constraint text via regex on every render. Read-only — the constraint text is the only source of truth, so badge and text can never drift.
  • Ship a new "Library with OCL" structural-pattern template pre-populated with 11 canonical full-text OCL constraints — invariants on Book / Library / Author plus preconditions and a postcondition on Book::decrease_stock and a precondition on Library::cheapest_book_by. Loads with zero OCL warnings.
  • The body-only popup shape (kind dropdown / method picker / name field) introduced earlier on this branch is reverted — the textbox holds the complete OCL block, matching the canonical shape Jordi's downstream metamodel consumer expects to read constraint names from.

Changes

  • packages/editor/src/main/packages/uml-class-diagram/uml-class-ocl/uml-class-ocl-constraint-component.tsx — regex the constraint text for the BOCL header and render «inv» / «pre» / «post» (plus the method name for pre/post) above the body. No badge for malformed or empty text — natural visual feedback that something's wrong with the syntax.
  • packages/editor/src/main/packages/uml-class-diagram/uml-class-ocl/uml-class-ocl-constraint-update.tsx — popup reverted to plain textarea + color + delete.
  • packages/editor/src/main/packages/uml-class-diagram/uml-class-ocl/uml-class-ocl-constraint.ts — element model is back to a single constraint: string field.
  • packages/webapp/src/main/templates/pattern/structural/Library_OCL.json — new template (Book / Library / Author / Genre with the existing relationships, plus 11 OCL boxes covering all three kinds).
  • software-pattern-types.ts + template-factory.ts — register LIBRARY_OCL = 'Library with OCL' under the structural category.

Test plan

  • CI: lint + build pass (npm run lint, npm run build).
  • Project-template picker shows a new "Library with OCL" entry under Class Diagram; loading it produces a clean diagram with zero OCL warnings on /validate-diagram.
  • Drag an OCL box, link to a class, type context Class inv name: self.x > 0«inv» badge appears above the body.
  • Type a precondition (context Class::method(params) pre: ...) — badge becomes «pre» method. Same for post.
  • Type a body without a header (or malformed text) — no badge renders.

Review notes

Skipped the multi-agent besser-review gate to keep the loop fast. Typecheck on the modified files has 0 net new errors (2 pre-existing ThemedPath typings affect every component using it). The paired backend PR is green (1048 backend tests passed). Run /besser-review for an independent deep review.

Related

Backend PR: BESSER-PEARL/BESSER#529

ArmenSl added 4 commits May 5, 2026 12:55
Extend ClassOCLConstraint with three new fields so the editor can
distinguish invariants, preconditions, and postconditions on the same
visual element:

- kind: 'invariant' | 'precondition' | 'postcondition' (default invariant)
- targetMethodId: element id of the method a pre/post is anchored on
- constraintName: optional user-supplied name (auto-generated otherwise)

The constraint textbox now stores the OCL body only (e.g. "self.pages > 0").
The header (context X inv name: / context X::m(p:T) pre:) is reconstructed
by the backend at parse time using the linked class and the picked method,
so renaming/rerouting the link automatically follows.

Popup gains:
- Kind dropdown.
- Method picker (when kind != invariant), populated from the linked class's
  ownedElements filtered to ClassMethod, via mapStateToProps.
- Optional Name field.
- Inline notice when no class is linked or the linked class has no methods.
- Orphan warning when the previously selected method element no longer
  exists.

Canvas component renders a stereotype badge ("inv" / "pre" / "post") and
the target method name above the body, plus a red border + warning glyph
when the box is orphaned.

Default-and-omit on serialize keeps legacy diagrams (no kind set) byte-stable
on round-trip until they are explicitly edited.
Drop the kind dropdown, method picker, name field, and stereotype badge
introduced in the previous commit. Revert the ClassOCLConstraint element
to its pre-iteration shape: a single ``constraint: string`` field holding
the full OCL block.

Driver: Jordi's downstream metamodel work consumes the full OCL source
text to extract the constraint name and check duplication. Splitting
that text into body + metadata fields hid the name from his parser, so
the pivot puts the canonical form back into the user's hands:

  context Book inv book_pages_positive: self.pages > 0
  context Book::decrease_stock(qty: int) pre: qty > 0
  context Book::decrease_stock(qty: int) post: self.stock >= 0

The popup is now a plain textarea + color + delete (matching the shape
that existed before this branch). Routing into ``Method.pre`` /
``Method.post`` happens entirely on the backend by parsing the OCL
header tokens; no frontend metadata is needed.

Files reverted:

* ``uml-class-ocl-constraint.ts`` — IUMLClassOCLConstraint goes back to
  ``constraint: string`` only. ``kind`` / ``targetMethodId`` /
  ``constraintName`` / ``OCLConstraintKind`` are removed.
* ``uml-class-ocl-constraint-update.tsx`` — drop the kind dropdown,
  method picker, name field, ``mapStateToProps`` connection, and orphan
  notice rendering. Restore the simple textarea-based popup.
* ``uml-class-ocl-constraint-component.tsx`` — drop the stereotype badge
  and orphan-glyph rendering. Canvas just shows the OCL text.
Parse the constraint text in the canvas component and render a small
italic badge above the body to give a visual cue of the OCL kind:

  «inv»                 — invariant
  «pre» <method-name>   — precondition on a method
  «post» <method-name>  — postcondition on a method

Read-only and derived from the text — the constraint string itself
remains the only source of truth, so there's no popup metadata, no
round-trip churn, and no risk of badge/text drift. When the text
doesn't match the BOCL header regex (empty or malformed), no badge
renders.
Drop a structural-pattern template that ships pre-populated with eleven
canonical full-text OCL constraints — seven invariants on Book / Library
/ Author, plus preconditions and a postcondition on
Book::decrease_stock(qty: int) and a precondition on
Library::cheapest_book_by(author: Author). The constraints exercise:

* simple comparisons (``self.pages > 0``),
* string size (``self.title.size() > 0``),
* collection size via the arrow form (``self.books->size() > 0``),
* method-parameter references inside pre/post (``self.stock >= qty``).

Every constraint validates cleanly through the backend's
``process_class_diagram`` path, so loading the template into the editor
yields zero OCL warnings out of the box. Useful both as a learning
example for new users and as smoke-test fodder for OCL-related changes.

Files:
* ``packages/webapp/src/main/templates/pattern/structural/Library_OCL.json``
  — the template model JSON.
* ``software-pattern-types.ts`` — adds ``LIBRARY_OCL = 'Library with OCL'``
  to the enum.
* ``template-factory.ts`` — imports the JSON and wires the new case
  into ``createSoftwarePattern``, reusing ``SoftwarePatternCategory.STRUCTURAL``.
@ArmenSl ArmenSl marked this pull request as ready for review May 6, 2026 11:34
@ArmenSl ArmenSl requested a review from ivan-alfonso May 6, 2026 11:34
ArmenSl added 6 commits May 6, 2026 13:48
Pairs with the backend ``Constraint.description`` field added in
BESSER#499 — surfaces a plain-language explanation alongside the raw
OCL expression in the validator output.

- Editor: ``ClassOCLConstraint`` now carries ``description`` (serialized
  to/from JSON, default empty), so projects round-trip the field
  through BUML→JSON→BUML.
- Popup: small textarea labelled "Description (shown to end-users when
  validation fails)" sitting below the OCL textarea. Updates write
  through the same ``UMLElementRepository.update`` path as the
  constraint text.

Inline ``--`` comments inside the OCL block still take precedence over
this field at the backend (per-constraint comment beats per-element
default), so users who prefer the inline shape keep working.
Adds a "Generate" button beside the Class Diagram reference picker
visible only when the active diagram is an Object Diagram. Clicking
it scaffolds:

- One ObjectName instance per concrete Class in the referenced class
  diagram (skips AbstractClass and Enumeration).
- One ObjectAttribute per ClassAttribute, with realistic placeholder
  values: source ``defaultValue`` first, then a name- and type-aware
  default ('25' for ``age``, ``'alice@example.com'`` for ``email``,
  enum-literal lookup for custom types like ``genre = Poetry``,
  ``2026-01-01`` for ``date`` etc.). Strings are unquoted so the
  validator's date type-check accepts them.
- One ObjectLink per class-level association (Bidirectional /
  Unidirectional / Aggregation / Composition). Inheritance and
  realization are skipped — they have no runtime instance.

Additive by design: existing canvas objects keyed by ``classId`` are
preserved (skipped for re-instantiation) and existing
``ObjectLink``s keyed by ``associationId`` aren't duplicated, so
re-clicking after manual edits is safe.

Pairs with the OCL pre/post backend work (BESSER#529): users can now
populate an Object Diagram in one click to syntax-check + evaluate
class invariants against real instances without hand-typing each
slot.
The German translation file was never used end-to-end and the editor
ships only English UI. Drop de.json, the de member of the Locale enum,
and its dictionary entry; update CLAUDE.md accordingly.
Raw <text> with element.textColor bypasses the styled-components theme
when textColor is unset. Provide 'currentColor' as fallback per the
custom-SVG rendering guidance in CLAUDE.md so the badge stays visible
in both light and dark themes.
@ArmenSl ArmenSl merged commit c1752c7 into develop May 6, 2026
@ArmenSl ArmenSl deleted the feature/wme-ocl-pre-post branch May 6, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant