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

ahuber pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/main by this push:
     new 01abce9d365 CAUSEWAY-3859: Java record refactoring (part 17)
01abce9d365 is described below

commit 01abce9d365dd5049989e00c678db8809ecca436
Author: Andi Huber <[email protected]>
AuthorDate: Wed Feb 19 09:25:10 2025 +0100

    CAUSEWAY-3859: Java record refactoring (part 17)
    
    - fixes custom value semantics not considered when rendering titles for
    members (as we allow customization via annotations)
---
 .../facets/object/title/TitleRenderRequest.java    | 11 +--
 .../title/parser/TitleFacetFromValueFacet.java     | 56 +++++----------
 .../metamodel/facets/object/value/ValueFacet.java  | 81 ++++++----------------
 .../facets/object/value/ValueFacetAbstract.java    | 46 ++----------
 .../interactions/managed/ActionInteraction.java    |  6 +-
 .../interactions/managed/_BindingUtil.java         | 12 ++--
 .../core/metamodel/object/MmTitleUtils.java        | 15 ++--
 .../services/title/TitleServiceDefault.java        | 25 +++----
 .../interaction/DomainObjectTesterFactory.java     |  8 +--
 .../value/ConverterBasedOnValueSemantics.java      | 10 +--
 .../model/value/OptionsBasedOnValueSemantics.java  |  7 +-
 11 files changed, 82 insertions(+), 195 deletions(-)

diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/TitleRenderRequest.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/TitleRenderRequest.java
index b7bfcbadb5c..02c9e1bffe8 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/TitleRenderRequest.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/TitleRenderRequest.java
@@ -21,15 +21,12 @@
 import java.util.function.Predicate;
 
 import org.jspecify.annotations.NonNull;
-import org.jspecify.annotations.Nullable;
 
 import org.apache.causeway.commons.internal.functions._Predicates;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
-import org.apache.causeway.core.metamodel.spec.feature.ObjectFeature;
 
 public record TitleRenderRequest(
     @NonNull ManagedObject object,
-    @Nullable ObjectFeature feature,
     /**
      * Provide a title for the target object, possibly abbreviated (according 
to supplied predicate)
      * <p>
@@ -42,13 +39,7 @@ public record TitleRenderRequest(
     @NonNull Predicate<ManagedObject> skipTitlePartEvaluator) {
 
     public static TitleRenderRequest forObject(final ManagedObject object) {
-        return new TitleRenderRequest(object, null);
-    }
-
-    public TitleRenderRequest(
-        @NonNull final ManagedObject object,
-        @Nullable final ObjectFeature feature) {
-        this(object, feature, _Predicates.alwaysFalse());
+        return new TitleRenderRequest(object,  _Predicates.alwaysFalse());
     }
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/parser/TitleFacetFromValueFacet.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/parser/TitleFacetFromValueFacet.java
index 16fea5e1b3b..e4282d389ba 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/parser/TitleFacetFromValueFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/parser/TitleFacetFromValueFacet.java
@@ -28,10 +28,6 @@
 import org.apache.causeway.core.metamodel.facets.object.title.TitleFacet;
 import 
org.apache.causeway.core.metamodel.facets.object.title.TitleRenderRequest;
 import org.apache.causeway.core.metamodel.facets.object.value.ValueFacet;
-import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
-import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
-
 import org.jspecify.annotations.NonNull;
 
 public final class TitleFacetFromValueFacet
@@ -52,13 +48,10 @@ private TitleFacetFromValueFacet(final ValueFacet<?> 
valueFacet, final FacetHold
 
     @Override
     public String title(final TitleRenderRequest renderRequest) {
-        if (renderRequest == null) {
-            return null;
-        }
+        if (renderRequest == null) return null;
+
         final Object pojo = renderRequest.object().getPojo();
-        if (pojo == null) {
-            return null;
-        }
+        if (pojo == null) return null;
 
         /* Enum values are treated special, that is, we honor @Title 
annotations
          * and alternatively object-support method 'title()',
@@ -68,32 +61,22 @@ public String title(final TitleRenderRequest renderRequest) 
{
             return Enums.getFriendlyNameOf((Enum<?>)pojo);
         }
 
+        var featureId = getFacetHolder().getFeatureIdentifier();
+        var feature = 
getSpecificationLoader().loadFeature(featureId).orElse(null);
+
         // support for qualified value semantics, requires a 'where' context, 
that is,
         // what property, collection, action return or action param this is to 
be rendered for ...
-        if(renderRequest.feature()!=null) {
-            switch(renderRequest.feature().getFeatureType()) {
-            case PROPERTY: {
-                var prop = (OneToOneAssociation)renderRequest.feature();
-                final Renderer renderer = valueFacet
-                        .selectRendererForPropertyElseFallback(prop);
-                return renderer
-                        .titlePresentation(valueFacet
-                                .createValueSemanticsContext(prop), pojo);
-            }
-            case COLLECTION: {
-                var coll = (OneToManyAssociation)renderRequest.feature();
+        if(feature!=null) {
+            switch(feature.getFeatureType()) {
+            case PROPERTY:
+            case COLLECTION:
+            case ACTION_PARAMETER_SINGULAR:
+            case ACTION_PARAMETER_PLURAL: {
                 final Renderer renderer = valueFacet
-                        .selectRendererForCollectionElseFallback(coll);
+                        
.selectRendererForParamOrPropOrCollOrElseFallback(feature);
                 return renderer
                         .titlePresentation(valueFacet
-                                .createValueSemanticsContext(coll), pojo);
-            }
-            case ACTION_PARAMETER_SINGULAR:
-            case ACTION_PARAMETER_PLURAL:{
-                var param = (ObjectActionParameter)renderRequest.feature();
-                final Renderer renderer = valueFacet
-                        .selectRendererForParameterElseFallback(param);
-                return 
renderer.titlePresentation(valueFacet.createValueSemanticsContext(param), pojo);
+                                .createValueSemanticsContext(feature), pojo);
             }
             default:
                 // fall through
@@ -102,14 +85,11 @@ public String title(final TitleRenderRequest 
renderRequest) {
 
         // fall back to default value semantics ...
 
-        var featureId = getFacetHolder().getFeatureIdentifier();
-        var feature = 
getSpecificationLoader().loadFeature(featureId).orElse(null);
-
         return valueFacet.selectDefaultRenderer()
-        .map(renderer->(Renderer) renderer)
-        
.map(renderer->renderer.titlePresentation(valueFacet.createValueSemanticsContext(feature),
 pojo))
-        .orElseGet(()->String.format("Value type %s has no value semantics for 
title rendering.",
-                
renderRequest.object().getSpecification().getCorrespondingClass()));
+            .map(renderer->(Renderer) renderer)
+            
.map(renderer->renderer.titlePresentation(valueFacet.createValueSemanticsContext(feature),
 pojo))
+            .orElseGet(()->String.format("Value type %s has no value semantics 
for title rendering.",
+                    
renderRequest.object().getSpecification().getCorrespondingClass()));
 
     }
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/ValueFacet.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/ValueFacet.java
index ad7d5f97090..8ab152a6efd 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/ValueFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/ValueFacet.java
@@ -21,6 +21,7 @@
 import java.util.Optional;
 import java.util.stream.Stream;
 
+import org.jspecify.annotations.NonNull;
 import org.jspecify.annotations.Nullable;
 
 import org.apache.causeway.applib.Identifier;
@@ -37,10 +38,7 @@
 import org.apache.causeway.core.metamodel.interactions.managed.ManagedProperty;
 import 
org.apache.causeway.core.metamodel.interactions.managed.ParameterNegotiationModel;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
-import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectFeature;
-import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.causeway.schema.common.v2.ValueType;
 
 /**
@@ -78,44 +76,27 @@ public interface ValueFacet<T>
 
     /** no qualifiers allowed on the default semantics provider*/
     Optional<DefaultsProvider<T>> selectDefaultDefaultsProvider();
-    Optional<DefaultsProvider<T>> selectDefaultsProviderForParameter(final 
ObjectActionParameter param);
-    Optional<DefaultsProvider<T>> selectDefaultsProviderForProperty(final 
OneToOneAssociation prop);
+    Optional<DefaultsProvider<T>> selectDefaultsProviderForAttribute(final 
@Nullable ObjectFeature feature);
 
     // -- PARSER
 
     /** no qualifiers allowed on the default semantics provider*/
     Optional<Parser<T>> selectDefaultParser();
-    Optional<Parser<T>> selectParserForParameter(final ObjectActionParameter 
param);
-    Optional<Parser<T>> selectParserForProperty(final OneToOneAssociation 
prop);
+    Optional<Parser<T>> selectParserForAttribute(@NonNull ObjectFeature 
feature);
 
     default Optional<Parser<T>> selectParserForFeature(final @Nullable 
ObjectFeature feature) {
-        if(feature==null) {
-            return selectDefaultParser();
-        }
-        switch(feature.getFeatureType()) {
-        case ACTION_PARAMETER_SINGULAR:
-            return selectParserForParameter((ObjectActionParameter)feature);
-        case PROPERTY:
-            return selectParserForProperty((OneToOneAssociation)feature);
-        default:
-            return selectDefaultParser();
-        }
+        return feature==null
+            ? selectDefaultParser()
+            : switch(feature.getFeatureType()) {
+                case ACTION_PARAMETER_SINGULAR, 
PROPERTY->selectParserForAttribute(feature);
+                default->selectDefaultParser();
+            };
     }
 
     Parser<T> fallbackParser(Identifier featureIdentifier);
 
-    default Parser<T> selectParserForParameterElseFallback(final 
ObjectActionParameter param) {
-        return selectParserForParameter(param)
-                .orElseGet(()->fallbackParser(param.getFeatureIdentifier()));
-    }
-
-    default Parser<T> selectParserForPropertyElseFallback(final 
OneToOneAssociation prop) {
-        return selectParserForProperty(prop)
-                .orElseGet(()->fallbackParser(prop.getFeatureIdentifier()));
-    }
-
-    default Parser<T> selectParserForFeatureElseFallback(final ObjectFeature 
feature) {
-        return selectParserForFeature(feature)
+    default Parser<T> selectParserForAttributeOrElseFallback(final @NonNull 
ObjectFeature feature) {
+        return selectParserForAttribute(feature)
                 .orElseGet(()->fallbackParser(feature.getFeatureIdentifier()));
     }
 
@@ -123,41 +104,23 @@ default Parser<T> 
selectParserForFeatureElseFallback(final ObjectFeature feature
 
     /** no qualifiers allowed on the default semantics provider*/
     Optional<Renderer<T>> selectDefaultRenderer();
-    Optional<Renderer<T>> selectRendererForParameter(final 
ObjectActionParameter param);
-    Optional<Renderer<T>> selectRendererForProperty(final OneToOneAssociation 
prop);
-    Optional<Renderer<T>> selectRendererForCollection(final 
OneToManyAssociation coll);
+    Optional<Renderer<T>> selectRendererForParamOrPropOrColl(@NonNull 
ObjectFeature param);
 
     Renderer<T> fallbackRenderer(Identifier featureIdentifier);
 
     default Optional<Renderer<T>> selectRendererForFeature(final @Nullable 
ObjectFeature feature) {
-        if(feature==null) {
-            return selectDefaultRenderer();
-        }
-        switch(feature.getFeatureType()) {
-        case ACTION_PARAMETER_SINGULAR:
-            return selectRendererForParameter((ObjectActionParameter)feature);
-        case PROPERTY:
-            return selectRendererForProperty((OneToOneAssociation)feature);
-        case COLLECTION:
-            return selectRendererForCollection((OneToManyAssociation)feature);
-        default:
-            return selectDefaultRenderer();
-        }
-    }
-
-    default Renderer<T> selectRendererForParameterElseFallback(final 
ObjectActionParameter param) {
-        return selectRendererForParameter(param)
-                .orElseGet(()->fallbackRenderer(param.getFeatureIdentifier()));
-    }
-
-    default Renderer<T> selectRendererForPropertyElseFallback(final 
OneToOneAssociation prop) {
-        return selectRendererForProperty(prop)
-                .orElseGet(()->fallbackRenderer(prop.getFeatureIdentifier()));
+        return feature==null
+            ? selectDefaultRenderer()
+            : switch(feature.getFeatureType()) {
+                case ACTION_PARAMETER_SINGULAR, PROPERTY, COLLECTION->
+                    selectRendererForParamOrPropOrColl(feature);
+                default->selectDefaultRenderer();
+            };
     }
 
-    default Renderer<T> selectRendererForCollectionElseFallback(final 
OneToManyAssociation coll) {
-        return selectRendererForCollection(coll)
-                .orElseGet(()->fallbackRenderer(coll.getFeatureIdentifier()));
+    default Renderer<T> selectRendererForParamOrPropOrCollOrElseFallback(final 
@NonNull ObjectFeature feature) {
+        return selectRendererForParamOrPropOrColl(feature)
+                
.orElseGet(()->fallbackRenderer(feature.getFeatureIdentifier()));
     }
 
     // -- TEMPORAL SUPPORT
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/ValueFacetAbstract.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/ValueFacetAbstract.java
index 2bbe3ce77bf..2d4ad2ac32b 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/ValueFacetAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/ValueFacetAbstract.java
@@ -51,11 +51,7 @@
 import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
 import org.apache.causeway.core.metamodel.spec.feature.MixedInAction;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
-import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectFeature;
-import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
-
 import lombok.Getter;
 import org.jspecify.annotations.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -182,16 +178,8 @@ public Optional<DefaultsProvider<T>> 
selectDefaultDefaultsProvider() {
     }
 
     @Override
-    public Optional<DefaultsProvider<T>> 
selectDefaultsProviderForParameter(final ObjectActionParameter param) {
-        return streamValueSemanticsHonoringQualifiers(param)
-                .map(ValueSemanticsProvider::getDefaultsProvider)
-                .filter(_NullSafe::isPresent)
-                .findFirst();
-    }
-
-    @Override
-    public Optional<DefaultsProvider<T>> 
selectDefaultsProviderForProperty(final OneToOneAssociation prop) {
-        return streamValueSemanticsHonoringQualifiers(prop)
+    public Optional<DefaultsProvider<T>> 
selectDefaultsProviderForAttribute(@Nullable final ObjectFeature feature) {
+        return streamValueSemanticsHonoringQualifiers(feature)
                 .map(ValueSemanticsProvider::getDefaultsProvider)
                 .filter(_NullSafe::isPresent)
                 .findFirst();
@@ -210,16 +198,8 @@ public Optional<Parser<T>> selectDefaultParser() {
     }
 
     @Override
-    public Optional<Parser<T>> selectParserForParameter(final 
ObjectActionParameter param) {
-        return streamValueSemanticsHonoringQualifiers(param)
-                .map(ValueSemanticsProvider::getParser)
-                .filter(_NullSafe::isPresent)
-                .findFirst();
-    }
-
-    @Override
-    public Optional<Parser<T>> selectParserForProperty(final 
OneToOneAssociation prop) {
-        return streamValueSemanticsHonoringQualifiers(prop)
+    public Optional<Parser<T>> selectParserForAttribute(@NonNull final 
ObjectFeature feature) {
+        return streamValueSemanticsHonoringQualifiers(feature)
                 .map(ValueSemanticsProvider::getParser)
                 .filter(_NullSafe::isPresent)
                 .findFirst();
@@ -243,29 +223,13 @@ public Optional<Renderer<T>> selectDefaultRenderer() {
     }
 
     @Override
-    public Optional<Renderer<T>> selectRendererForParameter(final 
ObjectActionParameter param) {
+    public Optional<Renderer<T>> selectRendererForParamOrPropOrColl(final 
@NonNull ObjectFeature param) {
         return streamValueSemanticsHonoringQualifiers(param)
                 .map(ValueSemanticsProvider::getRenderer)
                 .filter(_NullSafe::isPresent)
                 .findFirst();
     }
 
-    @Override
-    public Optional<Renderer<T>> selectRendererForProperty(final 
OneToOneAssociation prop) {
-        return streamValueSemanticsHonoringQualifiers(prop)
-                .map(ValueSemanticsProvider::getRenderer)
-                .filter(_NullSafe::isPresent)
-                .findFirst();
-    }
-
-    @Override
-    public Optional<Renderer<T>> selectRendererForCollection(final 
OneToManyAssociation coll) {
-        return streamValueSemanticsHonoringQualifiers(coll)
-                .map(ValueSemanticsProvider::getRenderer)
-                .filter(_NullSafe::isPresent)
-                .findFirst();
-    }
-
     @Override
     public Renderer<T> fallbackRenderer(final Identifier featureIdentifier) {
         return fallbackRenderer(getLogicalType(), featureIdentifier);
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ActionInteraction.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ActionInteraction.java
index f0725462a73..2a67403560b 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ActionInteraction.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ActionInteraction.java
@@ -102,7 +102,7 @@ public static ActionInteraction empty(final String 
actionId) {
      */
     @Getter
     private final Optional<ObjectAction> metamodel;
-    
+
     public final Optional<Identifier> getFeatureIdentifier() {
         return metamodel.map(ObjectAction::getFeatureIdentifier);
     }
@@ -219,7 +219,7 @@ public static ActionInteraction startAsBoundToProperty(
             var compositeValueNullable = prop.get(propertyOwner);
             var compositeValue =
                     ManagedObjects.nullOrEmptyToDefault(elementType, 
compositeValueNullable, ()->
-                        valueFacet.selectDefaultsProviderForProperty(prop)
+                        valueFacet.selectDefaultsProviderForAttribute(prop)
                             .orElseThrow(()->onMissingDefaultsProvider(prop))
                             .getDefaultValue());
 
@@ -257,7 +257,7 @@ public static ActionInteraction startAsBoundToParameter(
             var compositeValueNullable = 
parameterNegotiationModel.getParamValue(paramIndex);
             var compositeValue =
                     ManagedObjects.nullOrEmptyToDefault(elementType, 
compositeValueNullable, ()->
-                        
valueFacet.selectDefaultsProviderForParameter(param.getMetaModel())
+                        
valueFacet.selectDefaultsProviderForAttribute(param.getMetaModel())
                             
.orElseThrow(()->onMissingDefaultsProvider(param.getMetaModel()))
                             .getDefaultValue());
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/_BindingUtil.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/_BindingUtil.java
index 11401608e61..f9a7b8b0e0b 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/_BindingUtil.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/_BindingUtil.java
@@ -64,8 +64,8 @@ Observable<String> bindAsFormated(
         return spec.valueFacet()
         .map(valueFacet->{
             var eitherRendererOrParser = format.requiresRenderer()
-                ? Either.<Renderer, 
Parser>left(valueFacet.selectRendererForPropertyElseFallback(prop))
-                : Either.<Renderer, 
Parser>right(valueFacet.selectParserForPropertyElseFallback(prop));
+                ? Either.<Renderer, 
Parser>left(valueFacet.selectRendererForParamOrPropOrCollOrElseFallback(prop))
+                : Either.<Renderer, 
Parser>right(valueFacet.selectParserForAttributeOrElseFallback(prop));
             var ctx = valueFacet.createValueSemanticsContext(prop);
 
             return bindAsFormated(format, spec, bindablePropertyValue, 
eitherRendererOrParser, ctx);
@@ -93,8 +93,8 @@ Observable<String> bindAsFormated(
         return spec.valueFacet()
         .map(valueFacet->{
             var eitherRendererOrParser = format.requiresRenderer()
-                ? Either.<Renderer, 
Parser>left(valueFacet.selectRendererForParameterElseFallback(param))
-                : Either.<Renderer, 
Parser>right(valueFacet.selectParserForParameterElseFallback(param));
+                ? Either.<Renderer, 
Parser>left(valueFacet.selectRendererForParamOrPropOrCollOrElseFallback(param))
+                : Either.<Renderer, 
Parser>right(valueFacet.selectParserForAttributeOrElseFallback(param));
             var ctx = valueFacet.createValueSemanticsContext(param);
 
             return bindAsFormated(format, spec, bindableParamValue, 
eitherRendererOrParser, ctx);
@@ -113,7 +113,7 @@ Observable<String> bindAsFormated(
     boolean hasParser(final @NonNull OneToOneAssociation prop) {
         return prop.getElementType()
                 .valueFacet()
-                
.map(valueFacet->valueFacet.selectRendererForProperty(prop).isPresent())
+                
.map(valueFacet->valueFacet.selectRendererForParamOrPropOrColl(prop).isPresent())
                 .orElse(false);
     }
 
@@ -122,7 +122,7 @@ boolean hasParser(final @NonNull ObjectActionParameter 
param) {
                 ? false
                 : param.getElementType()
                     .valueFacet()
-                    
.map(valueFacet->valueFacet.selectRendererForParameter(param).isPresent())
+                    
.map(valueFacet->valueFacet.selectRendererForParamOrPropOrColl(param).isPresent())
                     .orElse(false);
     }
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmTitleUtils.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmTitleUtils.java
index b9353d9bdba..681126edbbc 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmTitleUtils.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmTitleUtils.java
@@ -49,7 +49,7 @@ public String getTitleHonoringTitlePartSkipping(
                 ? "(multiple objects)"
                 : managedObject != null
                     ? _InternalTitleUtil.titleString(
-                            new TitleRenderRequest(managedObject, null, 
skipTitlePart))
+                            new TitleRenderRequest(managedObject, 
skipTitlePart))
                     : "(no object)";
     }
 
@@ -65,14 +65,11 @@ public static String formatAnyCardinalityAsTitle(
                 .map(ts->ts.translate(TranslationContext.empty(), "entries 
of"))
                 .orElse("entries of");
 
-        switch (cardinality) {
-        case 0:
-            return "No " + nounTranslated;
-        case 1:
-            return "1 " + nounTranslated;
-        default:
-            return "" + cardinality + " " + entriesOfTranslated + " " + 
nounTranslated;
-        }
+        return switch (cardinality) {
+            case 0 -> "No " + nounTranslated;
+            case 1 -> "1 " + nounTranslated;
+            default -> "" + cardinality + " " + entriesOfTranslated + " " + 
nounTranslated;
+        };
     }
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
index c6715833ac2..5f5be4fb000 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
@@ -54,38 +54,31 @@ public class TitleServiceDefault implements TitleService {
     @Override
     public String titleOf(final Object domainObject) {
 
-        if(objectManager == null) { // simplified JUnit test support
-            return "" + domainObject;
-        }
+        if(objectManager == null) return "" + domainObject; // simplified 
JUnit test support
 
         var pojo = unwrapped(domainObject);
         var objectAdapter = objectManager.adapt(pojo);
 
-        if(ManagedObjects.isNullOrUnspecifiedOrEmpty(objectAdapter)) {
-            return "[UNSPECIFIED]";
-        }
+        if(ManagedObjects.isNullOrUnspecifiedOrEmpty(objectAdapter)) return 
"[UNSPECIFIED]";
 
-        if(MmEntityUtils.getEntityState(objectAdapter).isTransientOrRemoved()) 
{
+        return 
MmEntityUtils.getEntityState(objectAdapter).isTransientOrRemoved()
             // here we just mean NOT-ATTACHED (and not the concrete DETACHED 
entity state)
-            return "[DETACHED]";
-        } else {
-            return 
objectAdapter.getSpecification().getTitle(TitleRenderRequest.forObject(objectAdapter));
-        }
+            ? "[DETACHED]"
+            : 
objectAdapter.getSpecification().getTitle(TitleRenderRequest.forObject(objectAdapter));
     }
 
     @Override
     public String iconNameOf(final Object domainObject) {
 
-        if(objectManager == null) { // simplified JUnit test support
+        if(objectManager == null)  // simplified JUnit test support
             return domainObject!=null ? 
domainObject.getClass().getSimpleName() : "null";
-        }
 
         var pojo = unwrapped(domainObject);
         var objectAdapter = objectManager.adapt(pojo);
 
-        if(ManagedObjects.isNullOrUnspecifiedOrEmpty(objectAdapter)) return 
"unspecified";
-
-        return objectAdapter.getSpecification().getIconName(objectAdapter);
+        return ManagedObjects.isNullOrUnspecifiedOrEmpty(objectAdapter)
+            ? "unspecified"
+            : objectAdapter.getSpecification().getIconName(objectAdapter);
     }
 
     //-- HELPER
diff --git 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
index 5e0d6a270ad..8caf6f371ae 100644
--- 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
+++ 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
@@ -27,6 +27,8 @@
 
 import jakarta.inject.Inject;
 
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
 import org.junit.jupiter.api.function.ThrowingSupplier;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -35,7 +37,6 @@
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import org.jspecify.annotations.Nullable;
 import org.springframework.stereotype.Service;
 
 import org.apache.causeway.applib.Identifier;
@@ -82,7 +83,6 @@
 import 
org.apache.causeway.testing.integtestsupport.applib.validate.DomainModelValidator;
 
 import lombok.Getter;
-import org.jspecify.annotations.NonNull;
 import lombok.SneakyThrows;
 
 @Service
@@ -663,7 +663,7 @@ public DataTableTester tableTester(
         // -- HELPER
 
         @SuppressWarnings("unchecked")
-        static void updatePojo(final ManagedValue managedValue, final 
UnaryOperator replacer) {
+        static void updatePojo(final ManagedValue managedValue, 
@SuppressWarnings("rawtypes") final UnaryOperator replacer) {
             managedValue.update(v->ManagedObject.adaptSingular(
                     v.getSpecification(),
                     replacer.apply(v.getPojo())));
@@ -902,7 +902,7 @@ public String asParsebleText() {
             var context = valueFacet
                     .createValueSemanticsContext(prop);
 
-            return valueFacet.selectParserForPropertyElseFallback(prop)
+            return valueFacet.selectParserForAttributeOrElseFallback(prop)
                     .parseableTextRepresentation(context,
                             
MmUnwrapUtils.single(managedPropertyIfAny.get().getPropertyValue()));
         }
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/value/ConverterBasedOnValueSemantics.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/value/ConverterBasedOnValueSemantics.java
index 1d553383da0..b661ed6d74a 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/value/ConverterBasedOnValueSemantics.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/value/ConverterBasedOnValueSemantics.java
@@ -81,7 +81,7 @@ public final T convertToObject(final String text, final 
Locale locale) throws Co
                 .createValueSemanticsContext(feature);
 
         try {
-            return valueFacet.selectParserForFeatureElseFallback(feature)
+            return valueFacet.selectParserForAttributeOrElseFallback(feature)
                     .parseTextRepresentation(context, text);
         } catch (Exception e) {
             if(e instanceof ConversionException) {
@@ -107,13 +107,13 @@ public final String convertToString(final T value, final 
Locale locale) {
 
         switch(scalarRepresentation) {
         case EDITING:
-            return valueFacet.selectParserForFeatureElseFallback(feature)
+            return valueFacet.selectParserForAttributeOrElseFallback(feature)
                     .parseableTextRepresentation(context, value);
         case VIEWING:
             return propOrParam.fold(
-                    
prop->valueFacet.selectRendererForPropertyElseFallback(prop)
+                    
prop->valueFacet.selectRendererForParamOrPropOrCollOrElseFallback(prop)
                             .titlePresentation(context, value),
-                    
param->valueFacet.selectRendererForParameterElseFallback(param)
+                    
param->valueFacet.selectRendererForParamOrPropOrCollOrElseFallback(param)
                             .titlePresentation(context, value));
         }
 
@@ -125,7 +125,7 @@ public String getEditingPattern() {
         var valueFacet = valueFacet();
         var context = valueFacet
                 .createValueSemanticsContext(feature);
-        return valueFacet.selectParserForFeatureElseFallback(feature)
+        return valueFacet.selectParserForAttributeOrElseFallback(feature)
                 .getPattern(context);
     }
 
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/value/OptionsBasedOnValueSemantics.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/value/OptionsBasedOnValueSemantics.java
index 59c5eeeae16..5bd9b6652af 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/value/OptionsBasedOnValueSemantics.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/value/OptionsBasedOnValueSemantics.java
@@ -19,7 +19,6 @@
 package org.apache.causeway.viewer.wicket.model.value;
 
 import java.util.Optional;
-
 import org.apache.causeway.applib.value.semantics.Renderer;
 import org.apache.causeway.applib.value.semantics.Renderer.SyntaxHighlighter;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
@@ -45,9 +44,9 @@ public final Optional<Renderer<?>> lookupRenderer() {
         case EDITING:
             return Optional.empty();
         case VIEWING:
-            return Optional.of(propOrParam.fold(
-                    
prop->valueFacet.selectRendererForPropertyElseFallback(prop),
-                    
param->valueFacet.selectRendererForParameterElseFallback(param)));
+            return Optional.of(
+                
valueFacet.selectRendererForParamOrPropOrCollOrElseFallback(propOrParam
+                    .fold(ObjectFeature.class::cast, 
ObjectFeature.class::cast)));
         }
         throw _Exceptions.unmatchedCase(scalarRepresentation);
     }

Reply via email to