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);
}