You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2026/06/07 14:48:58 UTC

(causeway) 07/50: CAUSEWAY-4012: adds view model selector action proposal

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-4014
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 682ec1fd680a2f6d4c799c9a6e1cf4ae6f416442
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Sun Jun 7 06:36:59 2026 +0100

    CAUSEWAY-4012: adds view model selector action proposal
---
 .../.openspec.yaml                                 |  2 +
 .../allow-view-model-selector-actions/design.md    | 44 +++++++++++++
 .../allow-view-model-selector-actions/proposal.md  | 28 +++++++++
 .../parented-collection-selector-actions/spec.md   | 73 ++++++++++++++++++++++
 .../allow-view-model-selector-actions/tasks.md     | 16 +++++
 5 files changed, 163 insertions(+)

diff --git a/openspec/changes/allow-view-model-selector-actions/.openspec.yaml b/openspec/changes/allow-view-model-selector-actions/.openspec.yaml
new file mode 100644
index 00000000000..11967fcb6a7
--- /dev/null
+++ b/openspec/changes/allow-view-model-selector-actions/.openspec.yaml
@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-06-07
diff --git a/openspec/changes/allow-view-model-selector-actions/design.md b/openspec/changes/allow-view-model-selector-actions/design.md
new file mode 100644
index 00000000000..848d01fbf1b
--- /dev/null
+++ b/openspec/changes/allow-view-model-selector-actions/design.md
@@ -0,0 +1,44 @@
+## Context
+
+Parented collection selector actions are synthesized by `ObjectSpecificationAbstract.ParentedCollectionSelectorActionUtil` when command-log recording support is enabled.
+The current runtime eligibility rule permits entity-owned collections with entity, view model, or abstract element types.
+It only permits view-model-owned collections in unit tests, and then only when the element type is also a view model.
+This prevents selectors on useful runtime view models such as the PetClinic home page, whose collections return `PetOwner` and `Visit` entities.
+
+## Goals / Non-Goals
+
+**Goals:**
+
+- Allow selector action synthesis for view-model-owned collections at runtime.
+- Use the same element-type eligibility for entity and view-model owners.
+- Preserve the existing command-log recording support gate.
+- Preserve existing selector styling, naming, parameters, validation, invocation, and command publishing behavior.
+- Add regression coverage for view-model owners with entity elements.
+
+**Non-Goals:**
+
+- Change selector matching semantics.
+- Change which child properties become filter parameters.
+- Create selectors when command-log recording support is disabled.
+- Add application-specific logic for PetClinic or home page view models.
+- Add viewer rendering changes.
+
+## Decisions
+
+- Replace the owner-specific eligibility rule with a rule based on supported owner and element domain types.
+  Entity and view-model owners should both be eligible because the selector invocation already reads the collection from the supplied parent object and does not depend on persistence identity of the parent.
+- Keep element eligibility constrained to entity, view model, or abstract domain types.
+  This preserves the existing intent that selector actions navigate to a selected domain object rather than arbitrary scalar collection elements.
+- Remove the unit-test-only view-model exception instead of adding another special case.
+  The runtime behavior should be explicit and testable, and unit tests should follow the same eligibility rule as production.
+- Validate with metamodel tests that a view-model owner with entity collection elements receives a selector action.
+  Existing tests already cover entity owners and view-model element behavior.
+
+## Risks / Trade-offs
+
+- [Risk] More synthetic actions may appear in applications that have command-log recording support enabled and expose view-model collections.
+  → Mitigation: this only applies after the existing opt-in property is enabled, and generated actions use the reserved synthetic marker and deterministic id.
+- [Risk] Some view-model collections may be expensive to evaluate during selector invocation.
+  → Mitigation: selector invocation already evaluates the collection only when validating or invoking the action, matching existing entity-owned behavior.
+- [Risk] View-model-owned collections may not be semantically parented in every application.
+  → Mitigation: the existing feature already synthesizes only from metamodel collection associations and remains gated by the command-log recording support opt-in.
diff --git a/openspec/changes/allow-view-model-selector-actions/proposal.md b/openspec/changes/allow-view-model-selector-actions/proposal.md
new file mode 100644
index 00000000000..a2c156e5037
--- /dev/null
+++ b/openspec/changes/allow-view-model-selector-actions/proposal.md
@@ -0,0 +1,28 @@
+## Why
+
+Synthetic parented collection selector actions currently work for entity-owned collections but are unnecessarily restricted away from ordinary runtime view models.
+View models such as the PetClinic home page can expose entity collections that should be recordable and navigable using the same selector mechanism.
+
+## What Changes
+
+- Remove the runtime restriction that only entity-owned parented collections can receive synthetic selector actions.
+- Allow view-model-owned collections to receive selector actions when their element type is an entity, view model, or abstract domain type.
+- Preserve the existing command-log recording support opt-in, selector action styling, parameters, validation, invocation, and disabled-by-default behavior.
+- No breaking changes.
+
+## Capabilities
+
+### New Capabilities
+
+- None.
+
+### Modified Capabilities
+
+- `parented-collection-selector-actions`: selector action synthesis applies to eligible view-model-owned collections as well as entity-owned collections.
+
+## Impact
+
+- Affects selector action eligibility in the metamodel synthesis path.
+- Affects applications with command-log recording support enabled that expose eligible collections from view models.
+- Adds or updates metamodel tests for view-model-owned collections with entity or view-model elements.
+- Does not change public APIs, configuration properties, selector matching semantics, or viewer rendering logic.
diff --git a/openspec/changes/allow-view-model-selector-actions/specs/parented-collection-selector-actions/spec.md b/openspec/changes/allow-view-model-selector-actions/specs/parented-collection-selector-actions/spec.md
new file mode 100644
index 00000000000..ab8899f1cd8
--- /dev/null
+++ b/openspec/changes/allow-view-model-selector-actions/specs/parented-collection-selector-actions/spec.md
@@ -0,0 +1,73 @@
+## MODIFIED Requirements
+
+### Requirement: Framework synthesizes selector actions for parented collections
+The system SHALL provide the `causeway.extensions.command-log.recording-support` configuration property that controls command-log recording support behavior.
+The `recording-support` property SHALL be an enum with values `ENABLED` and `DISABLED`.
+The system SHALL default `recording-support` to `DISABLED`.
+When `recording-support` is `ENABLED`, the system SHALL synthesize a safe metamodel `ObjectAction` for each eligible parented collection association.
+When `recording-support` is `DISABLED`, the system MUST NOT synthesize parented collection selector actions.
+The system MUST NOT require or use a separate `causeway.extensions.command-log.parented-collection-selector-actions-enabled` boolean property to enable synthetic parented collection selector action creation.
+An eligible parented collection association SHALL be allowed when its owning type is an entity or view model and its element type is an entity, view model, or abstract domain type.
+The synthetic action SHALL represent navigation from the collection owner to one selected collection element.
+The synthetic action SHALL have a deterministic identifier that does not collide with developer-authored actions.
+The synthetic action identifier SHALL use the reserved prefix `__causeway_select_from_` followed by the associated parented collection id.
+The synthetic action SHALL be distinguishable from developer-authored actions by framework metadata.
+The synthetic action SHALL be associated with the parented collection through layout metadata equivalent to `@ActionLayout(associateWith=...)`.
+The synthetic action SHALL have the display name `Select` through name metadata equivalent to `@ActionLayout(named="Select")`.
+The synthetic action SHALL have action layout CSS class metadata equivalent to `@ActionLayout(cssClass="btn-outline-secondary")`.
+The synthetic action SHALL have action layout Font Awesome metadata equivalent to `@ActionLayout(cssClassFa="hand-point-left")`.
+
+#### Scenario: Synthetic action is not available by default
+- **GIVEN** a domain object type has a parented collection of child entities
+- **AND** command-log recording support is not configured
+- **WHEN** the framework fully introspects the domain object type
+- **THEN** the metamodel does not include a synthetic selector action for that collection
+
+#### Scenario: Synthetic action is available when recording support is enabled for an entity-owned parented collection
+- **GIVEN** an entity type has a parented collection of child entities
+- **AND** command-log recording support is `ENABLED`
+- **WHEN** the framework fully introspects the entity type
+- **THEN** the metamodel includes a synthetic safe action for selecting one element from that collection
+- **AND** the synthetic action is associated with the collection owner type
+
+#### Scenario: Synthetic action is available when recording support is enabled for a view-model-owned parented collection
+- **GIVEN** a view model type has a parented collection of child entities
+- **AND** command-log recording support is `ENABLED`
+- **WHEN** the framework fully introspects the view model type
+- **THEN** the metamodel includes a synthetic safe action for selecting one element from that collection
+- **AND** the synthetic action is associated with the collection owner type
+
+#### Scenario: Synthetic action id is deterministic
+- **GIVEN** the framework introspects the same parented collection in two application runs
+- **WHEN** the synthetic selector action is created in each run
+- **THEN** both actions have the same action identifier
+- **AND** the identifier uses the reserved prefix `__causeway_select_from_`
+- **AND** the identifier is reserved so it does not conflict with application action ids
+
+#### Scenario: Ordinary action lists can identify synthetic actions
+- **WHEN** a viewer or metamodel exporter enumerates actions for a type
+- **THEN** it can determine whether a listed action is a synthetic parented collection selector action
+
+#### Scenario: Synthetic action is associated with its parented collection
+- **GIVEN** an entity type `Lease` has a parented collection `items`
+- **AND** command-log recording support is `ENABLED`
+- **WHEN** the framework synthesizes the selector action for `items`
+- **THEN** the action has layout association metadata for collection id `items`
+
+#### Scenario: Synthetic action display name is Select
+- **GIVEN** an entity type `Lease` has a parented collection `items`
+- **AND** command-log recording support is `ENABLED`
+- **WHEN** the framework synthesizes the selector action for `items`
+- **THEN** the action display name is `Select`
+
+#### Scenario: Synthetic action uses secondary button styling
+- **GIVEN** an entity type `Lease` has a parented collection `items`
+- **AND** command-log recording support is `ENABLED`
+- **WHEN** the framework synthesizes the selector action for `items`
+- **THEN** the action has CSS class metadata of `btn-outline-secondary`
+
+#### Scenario: Synthetic action uses select navigation icon styling
+- **GIVEN** an entity type `Lease` has a parented collection `items`
+- **AND** command-log recording support is `ENABLED`
+- **WHEN** the framework synthesizes the selector action for `items`
+- **THEN** the action has Font Awesome metadata of `hand-point-left`
diff --git a/openspec/changes/allow-view-model-selector-actions/tasks.md b/openspec/changes/allow-view-model-selector-actions/tasks.md
new file mode 100644
index 00000000000..32d6ad587ab
--- /dev/null
+++ b/openspec/changes/allow-view-model-selector-actions/tasks.md
@@ -0,0 +1,16 @@
+## 1. Eligibility Rule
+
+- [ ] 1.1 Update selector action eligibility so entity and view-model owners are both supported at runtime.
+- [ ] 1.2 Keep selector action element eligibility constrained to entity, view model, or abstract domain types.
+- [ ] 1.3 Remove the unit-test-only view-model eligibility special case.
+
+## 2. Tests
+
+- [ ] 2.1 Add metamodel test coverage for a view-model owner with entity collection elements.
+- [ ] 2.2 Verify view-model-owned selector actions keep existing name, association, styling, parameter, validation, and invocation behavior through focused assertions where practical.
+- [ ] 2.3 Preserve existing entity-owner selector action coverage.
+
+## 3. Validation
+
+- [ ] 3.1 Run the focused `ParentedCollectionSelectorActionUtilTest` Maven test set.
+- [ ] 3.2 Run `openspec validate allow-view-model-selector-actions --strict`.