feat(wme): show OCL kind badge + add 'Library with OCL' template#124
Merged
Conversation
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``.
4 tasks
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
«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.Book::decrease_stockand a precondition onLibrary::cheapest_book_by. Loads with zero OCL warnings.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 singleconstraint: stringfield.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— registerLIBRARY_OCL = 'Library with OCL'under the structural category.Test plan
npm run lint,npm run build)./validate-diagram.context Class inv name: self.x > 0—«inv»badge appears above the body.context Class::method(params) pre: ...) — badge becomes«pre» method. Same forpost.Review notes
Skipped the multi-agent
besser-reviewgate to keep the loop fast. Typecheck on the modified files has 0 net new errors (2 pre-existingThemedPathtypings affect every component using it). The paired backend PR is green (1048 backend tests passed). Run/besser-reviewfor an independent deep review.Related
Backend PR: BESSER-PEARL/BESSER#529