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

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


The following commit(s) were added to refs/heads/v3 by this push:
     new c9f3923003f CAUSEWAY-3837: proper element-type detection for Map 'as 
collection'
c9f3923003f is described below

commit c9f3923003fc09de35158b6e9e3112822aa5c5e1
Author: andi-huber <[email protected]>
AuthorDate: Mon Dec 16 08:38:19 2024 +0100

    CAUSEWAY-3837: proper element-type detection for Map 'as collection'
---
 .../commons/internal/reflection/_GenericResolver.java   | 17 +++++++++--------
 .../causeway/commons/semantics/CollectionSemantics.java |  4 ++++
 .../facets/object/navchild/TreeTraversalTest.java       |  1 +
 .../core/metamodel/spec/TypeOfAnyCardinalityTest.java   | 17 +++++++++++++++++
 4 files changed, 31 insertions(+), 8 deletions(-)

diff --git 
a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_GenericResolver.java
 
b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_GenericResolver.java
index 711a4f04409..d0e8f049003 100644
--- 
a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_GenericResolver.java
+++ 
b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_GenericResolver.java
@@ -168,7 +168,7 @@ public class _GenericResolver {
                     .anyMatch(this::isReturnTypeATypeOf);
         }
         Class<?> resolveFirstGenericTypeArgumentOnParameter(int paramIndex);
-        Class<?> resolveFirstGenericTypeArgumentOnMethodReturn();
+        Class<?> resolveGenericTypeArgumentOnMethodReturn(int argumentIndex);
         /**
          * Is NOT compliant with the weak-sameness relation
          * {@link ResolvedMethod#methodsWeaklySame(ResolvedMethod, 
ResolvedMethod)}.
@@ -278,7 +278,7 @@ public class _GenericResolver {
         return CollectionSemantics.valueOf(methodReturn)
             .map(collectionSemantics->
                 ResolvedType.plural(
-                        
resolvedMethod.resolveFirstGenericTypeArgumentOnMethodReturn(),
+                        
resolvedMethod.resolveGenericTypeArgumentOnMethodReturn(collectionSemantics.genericTypeArgumentIndex()),
                         methodReturn,
                         collectionSemantics)
             )
@@ -351,13 +351,13 @@ public class _GenericResolver {
             return isResolved ? Optional.of(this) : Optional.empty();
         }
         @Override
-        public Class<?> resolveFirstGenericTypeArgumentOnMethodReturn() {
-            return genericTypeArg(ResolvableType.forMethodReturnType(method, 
implementationClass))
+        public Class<?> resolveGenericTypeArgumentOnMethodReturn(final int 
argumentIndex) {
+            return genericTypeArg(ResolvableType.forMethodReturnType(method, 
implementationClass), argumentIndex)
                     .toClass();
         }
         @Override
         public Class<?> resolveFirstGenericTypeArgumentOnParameter(final int 
paramIndex) {
-            return genericTypeArg(ResolvableType.forMethodParameter(method, 
paramIndex, implementationClass))
+            return genericTypeArg(ResolvableType.forMethodParameter(method, 
paramIndex, implementationClass), 0)
                     .toClass();
         }
         @Override
@@ -383,6 +383,7 @@ public class _GenericResolver {
             if(!_Reflect.hasGenericReturn(method)) return true; // skip check
             return !returnType.equals(Object.class);
         }
+
 //        private Try<SimpleResolvedMethod> adopt(final @NonNull ClassLoader 
classLoader) {
 //            return Try.call(()->{
 //                var ownerReloaded = 
Class.forName(implementationClass.getName(), true, classLoader);
@@ -413,7 +414,7 @@ public class _GenericResolver {
         }
         @Override
         public Class<?> resolveFirstGenericTypeArgumentOnParameter(final int 
paramIndex) {
-            return 
genericTypeArg(ResolvableType.forConstructorParameter(constructor, paramIndex, 
implementationClass))
+            return 
genericTypeArg(ResolvableType.forConstructorParameter(constructor, paramIndex, 
implementationClass), 0)
                     .toClass();
         }
         @Override
@@ -485,10 +486,10 @@ public class _GenericResolver {
                         m, a.method(), b.method()));
     }
 
-    private ResolvableType genericTypeArg(final ResolvableType pluralType){
+    private ResolvableType genericTypeArg(final ResolvableType pluralType, 
final int genericTypeArgumentIndex){
         var genericTypeArg = pluralType.isArray()
                 ? pluralType.getComponentType()
-                : pluralType.getGeneric(0);
+                : pluralType.getGeneric(genericTypeArgumentIndex);
         return genericTypeArg;
     }
 
diff --git 
a/commons/src/main/java/org/apache/causeway/commons/semantics/CollectionSemantics.java
 
b/commons/src/main/java/org/apache/causeway/commons/semantics/CollectionSemantics.java
index ee26b07ef16..043e1cace9d 100644
--- 
a/commons/src/main/java/org/apache/causeway/commons/semantics/CollectionSemantics.java
+++ 
b/commons/src/main/java/org/apache/causeway/commons/semantics/CollectionSemantics.java
@@ -178,6 +178,10 @@ public enum CollectionSemantics {
 
     protected abstract Object asContainerType(
             final Class<?> elementType, final @NonNull List<?> nonScalar);
+
+    public int genericTypeArgumentIndex() {
+        return isMap() ? 1 : 0;
+    }
 }
 
 //TODO perhaps needs an update to reflect Java 7->11 Language changes
diff --git 
a/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/facets/object/navchild/TreeTraversalTest.java
 
b/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/facets/object/navchild/TreeTraversalTest.java
index 7f26873b136..3b0f58fe442 100644
--- 
a/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/facets/object/navchild/TreeTraversalTest.java
+++ 
b/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/facets/object/navchild/TreeTraversalTest.java
@@ -79,6 +79,7 @@ extends FacetFactoryTestAbstract {
         var assocAC = specA.getAssociationElseFail("childrenC");
         assertTrue(assocAC.isCollection());
         assertTrue(assocAC.containsFacet(NavigableSubtreeSequenceFacet.class));
+        assertEquals(_TreeSample.C.class, 
assocAC.getElementType().getCorrespondingClass());
 
         // second: post-processor should generate NavigableSubtreeFacet
         assertTrue(specA.containsFacet(NavigableSubtreeFacet.class));
diff --git 
a/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/spec/TypeOfAnyCardinalityTest.java
 
b/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/spec/TypeOfAnyCardinalityTest.java
index 59c0c31f803..eb63da82511 100644
--- 
a/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/spec/TypeOfAnyCardinalityTest.java
+++ 
b/core/metamodel/src/test/java/org/apache/causeway/core/metamodel/spec/TypeOfAnyCardinalityTest.java
@@ -19,6 +19,7 @@
 package org.apache.causeway.core.metamodel.spec;
 
 import java.util.Collections;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 
@@ -122,6 +123,22 @@ class TypeOfAnyCardinalityTest {
                 Set.class, Set.class, SortedSet.class);
     }
 
+    // -- SCENARIO: MAP
+
+    static class M {
+        public Map<Integer, String> someStrings() {
+            return Map.of(1, "a");
+        }
+    }
+
+    @Test
+    void mapAsCollection() {
+        var method = _GenericResolver.testing.resolveMethod(M.class, 
"someStrings");
+        assertNotNull(method);
+        var elementType = 
_GenericResolver.forMethodReturn(method).elementType();
+        assertEquals(String.class, elementType);
+    }
+
     // -- HELPER
 
     @SneakyThrows

Reply via email to