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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7bb864bb88 CAUSEWAY-3731: fixes corner case, where params don't got 
converted
7bb864bb88 is described below

commit 7bb864bb882083f8a4a4d4f7ddfcc097d9510eca
Author: andi-huber <[email protected]>
AuthorDate: Wed May 1 08:52:32 2024 +0200

    CAUSEWAY-3731: fixes corner case, where params don't got converted
---
 .../internal/reflection/_MethodFacades.java        | 44 ++++++++++++++++---
 .../core/metamodel/commons/CanonicalInvoker.java   | 37 +++++++++++-----
 ...ameterAdapter.java => ParameterConverters.java} | 49 ++++------------------
 .../facets/object/value/CompositeValueUpdater.java |  4 +-
 4 files changed, 77 insertions(+), 57 deletions(-)

diff --git 
a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_MethodFacades.java
 
b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_MethodFacades.java
index 630825222a..048fdcc1f5 100644
--- 
a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_MethodFacades.java
+++ 
b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_MethodFacades.java
@@ -24,7 +24,11 @@ import java.lang.reflect.Executable;
 import java.lang.reflect.Method;
 import java.util.Optional;
 
+import org.springframework.lang.Nullable;
+
+import org.apache.causeway.commons.internal._Constants;
 import org.apache.causeway.commons.internal.base._NullSafe;
+import org.apache.causeway.commons.internal.collections._Arrays;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import 
org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedConstructor;
 import 
org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod;
@@ -81,6 +85,35 @@ public class _MethodFacades {
         }
     }
 
+    /**
+     * Invocation helper, that converts a given object to a required type.
+     */
+    @FunctionalInterface
+    public interface ParameterConverter {
+        /**
+         * Replaces {@code parameterValue} (if required) to be conform with 
the {@code parameterType}.
+         */
+        <T> T convert(final Class<T> parameterType, Object parameterValue);
+        
+        // -- UTILITY
+
+        default Object[] convertAll(
+                final @NonNull Executable executable,
+                final @Nullable Object[] executionParameters) {
+            final int paramCount = executable.getParameterCount();
+            if(paramCount==0) {
+                return _Constants.emptyObjects;
+            }
+            val parameterTypes = executable.getParameterTypes();
+            val adaptedExecutionParameters = new Object[paramCount];
+            for(int i=0; i<paramCount; ++i) {
+                val origParam = _Arrays.get(executionParameters, 
i).orElse(null);
+                adaptedExecutionParameters[i] = convert(parameterTypes[i], 
origParam);
+            }
+            return adaptedExecutionParameters;
+        }
+    }
+    
     public static interface MethodFacade {
 
         Class<?>[] getParameterTypes();
@@ -110,7 +143,7 @@ public class _MethodFacades {
          */
         Executable asExecutable();
 
-        Object[] getArguments(Object[] executionParameters);
+        Object[] getArguments(Object[] executionParameters, ParameterConverter 
converter);
 
         <A extends Annotation> Optional<A> synthesize(final Class<A> 
annotationType);
         <A extends Annotation> Optional<A> synthesizeOnParameter(final 
Class<A> annotationType, int paramNum);
@@ -192,8 +225,8 @@ public class _MethodFacades {
                 final Class<A> annotationType, final int paramNum) {
             return 
_Annotations.synthesize(method.method().getParameters()[paramNum], 
annotationType);
         }
-        @Override public Object[] getArguments(final Object[] 
executionParameters) {
-            return executionParameters;
+        @Override public Object[] getArguments(final Object[] 
executionParameters, ParameterConverter converter) {
+            return converter.convertAll(method.method(), executionParameters);
         }
         @Override public boolean isAnnotatedAsNullable() {
             return _NullSafe.stream(method.method().getAnnotations())
@@ -248,9 +281,10 @@ public class _MethodFacades {
             return patConstructor.constructor();
         }
         @Override @SneakyThrows
-        public Object[] getArguments(final Object[] executionParameters) {
+        public Object[] getArguments(final Object[] executionParameters, 
ParameterConverter converter) {
+            var convertedArgs = 
converter.convertAll(patConstructor.constructor(), executionParameters);
             // converts input args into a single arg tuple type (PAT semantics)
-            return new Object[] 
{patConstructor.constructor().newInstance(executionParameters)};
+            return new Object[] 
{patConstructor.constructor().newInstance(convertedArgs)};
         }
         @Override public <A extends Annotation> Optional<A> synthesize(final 
Class<A> annotationType) {
             return _Annotations.synthesize(method.method(), annotationType);
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/CanonicalInvoker.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/CanonicalInvoker.java
index 64d34e70d8..3eb0102d8e 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/CanonicalInvoker.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/CanonicalInvoker.java
@@ -50,33 +50,50 @@ public class CanonicalInvoker {
     // -- CONSTRUCT
 
     public <T> T construct(final Constructor<T> constructor, final @Nullable 
Object... executionParameters) {
-        val adaptedExecutionParameters = 
ParameterAdapter.DEFAULT.adaptAll(constructor, executionParameters);
-        val t = _Reflect.invokeConstructor(constructor, 
adaptedExecutionParameters)
-                .mapFailure(ex->toVerboseException(ex, constructor, 
adaptedExecutionParameters))
+        val convertedExecutionParameters = 
+                ParameterConverters.DEFAULT.convertAll(constructor, 
executionParameters);
+        val t = _Reflect.invokeConstructor(constructor, 
convertedExecutionParameters)
+                .mapFailure(ex->toVerboseException(ex, constructor, 
convertedExecutionParameters))
                 .valueAsNonNullElseFail();
         return _Casts.uncheckedCast(t);
     }
 
     // -- INVOKE
 
-    public Object invoke(final MethodFacade methodFacade, final Object 
targetPojo, final Object[] executionParameters) {
-        return invoke(
-                methodFacade.asMethodForIntrospection().method(), targetPojo, 
methodFacade.getArguments(executionParameters));
+    public Object invoke(
+            final MethodFacade methodFacade, 
+            final Object targetPojo, 
+            final Object[] executionParameters) {
+        var method = methodFacade.asMethodForIntrospection().method();
+        var args = methodFacade.getArguments(executionParameters, 
ParameterConverters.DEFAULT);
+        return invokeWithConvertedArgs(method, targetPojo, args);
     }
 
     public void invokeAll(final Iterable<Method> methods, final Object object) 
{
-        methods.forEach(method->invoke(method, object));
+        // invokes with no args, no conversion needed
+        methods.forEach(method->invokeWithConvertedArgs(method, object));
     }
 
     public Object invoke(
             final Method method,
             final Object targetPojo,
             final @Nullable Object ... executionParameters) {
-        val adaptedExecutionParameters = 
ParameterAdapter.DEFAULT.adaptAll(method, executionParameters);
-        return _Reflect.invokeMethodOn(method, targetPojo, 
adaptedExecutionParameters)
+        var convertedExecutionParameters = 
ParameterConverters.DEFAULT.convertAll(method, executionParameters);
+        return _Reflect.invokeMethodOn(method, targetPojo, 
convertedExecutionParameters)
+            .mapFailure(ex->toVerboseException(ex,
+                    method,
+                    convertedExecutionParameters))
+            .valueAsNullableElseFail();
+    }
+    
+    public Object invokeWithConvertedArgs(
+            final Method method,
+            final Object targetPojo,
+            final @Nullable Object ... convertedExecutionParameters) {
+        return _Reflect.invokeMethodOn(method, targetPojo, 
convertedExecutionParameters)
             .mapFailure(ex->toVerboseException(ex,
                     method,
-                    adaptedExecutionParameters))
+                    convertedExecutionParameters))
             .valueAsNullableElseFail();
     }
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/ParameterAdapter.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/ParameterConverters.java
similarity index 53%
rename from 
core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/ParameterAdapter.java
rename to 
core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/ParameterConverters.java
index 0d794cbc30..2317a7e5e4 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/ParameterAdapter.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/commons/ParameterConverters.java
@@ -18,57 +18,24 @@
  */
 package org.apache.causeway.core.metamodel.commons;
 
-import java.lang.reflect.Executable;
-
-import org.springframework.lang.Nullable;
-
-import org.apache.causeway.commons.internal._Constants;
 import org.apache.causeway.commons.internal.base._Casts;
-import org.apache.causeway.commons.internal.collections._Arrays;
+import 
org.apache.causeway.commons.internal.reflection._MethodFacades.ParameterConverter;
 import org.apache.causeway.commons.semantics.CollectionSemantics;
 
-import lombok.NonNull;
-import lombok.val;
+import lombok.experimental.UtilityClass;
 
 /**
- * Helper interface for {@link CanonicalInvoker}.
+ * Helper for {@link CanonicalInvoker}.
  */
-@FunctionalInterface
-public interface ParameterAdapter {
-
-    // -- INTERFACE
-
-    /**
-     * Replaces {@code parameterValue} (if required) to be conform with the 
{@code parameterType}.
-     */
-    <T> T adaptToType(final Class<T> parameterType, Object parameterValue);
-
-    // -- UTILITY
-
-    default Object[] adaptAll(
-            final @NonNull Executable executable,
-            final @Nullable Object[] executionParameters) {
-        final int paramCount = executable.getParameterCount();
-        if(paramCount==0) {
-            return _Constants.emptyObjects;
-        }
-        val parameterTypes = executable.getParameterTypes();
-        val adaptedExecutionParameters = new Object[paramCount];
-        for(int i=0; i<paramCount; ++i) {
-            val origParam = _Arrays.get(executionParameters, i).orElse(null);
-            adaptedExecutionParameters[i] = adaptToType(parameterTypes[i], 
origParam);
-        }
-        return adaptedExecutionParameters;
-    }
-
-    // -- DEFAULT IMPL
+@UtilityClass
+public class ParameterConverters {
 
-    static ParameterAdapter DEFAULT = new Default();
+    public static ParameterConverter DEFAULT = new Default();
 
-    static class Default implements ParameterAdapter {
+    static class Default implements ParameterConverter {
 
         @Override
-        public <T> T adaptToType(final Class<T> parameterType, final Object 
parameterValue) {
+        public <T> T convert(final Class<T> parameterType, final Object 
parameterValue) {
             return _Casts.uncheckedCast(_adaptToType(parameterType, 
parameterValue));
         }
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/CompositeValueUpdater.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/CompositeValueUpdater.java
index 9f57446d30..4d20fe3386 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/CompositeValueUpdater.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/CompositeValueUpdater.java
@@ -22,6 +22,7 @@ import org.apache.causeway.applib.Identifier;
 import org.apache.causeway.applib.annotation.Where;
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.core.metamodel.commons.CanonicalInvoker;
+import org.apache.causeway.core.metamodel.commons.ParameterConverters;
 import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.causeway.core.metamodel.interactions.InteractionHead;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
@@ -85,7 +86,8 @@ public abstract class CompositeValueUpdater {
         val method = methodFacade.asMethodForIntrospection();
 
         val resultPojo = CanonicalInvoker
-                .invoke(method.method(), targetPojo, 
methodFacade.getArguments(executionParameters));
+                .invokeWithConvertedArgs(method.method(), targetPojo, 
+                        methodFacade.getArguments(executionParameters, 
ParameterConverters.DEFAULT));
 
         return ManagedObject.value(delegate.getReturnType(), resultPojo);
     }

Reply via email to