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/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new d8789c4954 ISIS-3327: fixes _ClassCache MethodKey clash handling
d8789c4954 is described below

commit d8789c4954ddbcacacbe46ef14cd401b18c77cef
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Thu Jan 19 11:25:03 2023 +0100

    ISIS-3327: fixes _ClassCache MethodKey clash handling
---
 .../commons/internal/reflection/_ClassCache.java   | 37 ++++++++++++++++++++--
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git 
a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java
 
b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java
index 7d310367dc..7280dec668 100644
--- 
a/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java
+++ 
b/commons/src/main/java/org/apache/causeway/commons/internal/reflection/_ClassCache.java
@@ -243,6 +243,7 @@ public final class _ClassCache implements AutoCloseable {
                 val declaredFields = type.getDeclaredFields();
                 val declaredMethods = //type.getDeclaredMethods(); ... cannot 
detect non overridden inherited methods
                         Can.ofStream(_Reflect.streamAllMethods(type, true));
+                val publicMethods = type.getMethods(); //XXX[ISIS-3327] order 
of methods returned might differ among JVM instances
 
                 val model = new ClassModel(
                         Can.ofArray(declaredFields),
@@ -273,11 +274,19 @@ public final class _ClassCache implements AutoCloseable {
                 }
 
                 // process public only
-                for(val method : type.getMethods()) {
+                for(val method : publicMethods) {
                     if(Modifier.isStatic(method.getModifiers())) continue;
 
                     val key = MethodKey.of(type, method);
-                    model.publicMethodsByKey.put(key, method);
+                    val methodWithSameKey = model.publicMethodsByKey.get(key);
+                    if(methodWithSameKey==null) {
+                        model.publicMethodsByKey.put(key, method);
+                    } else {
+                        // key-clash originating from one method overriding 
the other
+                        // we need to figure out which is the overriding one 
(not the overwritten one)
+                        model.publicMethodsByKey.put(key, 
whichIsOverridingTheOther(methodWithSameKey, method));
+                    }
+
                     model.nonPublicDeclaredMethodsByKey.remove(key);
                 }
 
@@ -379,6 +388,28 @@ public final class _ClassCache implements AutoCloseable {
         return _Strings.decapitalize(fieldName);
     }
 
-
+    /**
+     * If MethodKey(type, a) equals MethodKey(type, b), which one wins, that 
is,
+     * which one overrides the other?
+     * @implNote if both declaring type and return type are the same we don't 
care
+     */
+    private Method whichIsOverridingTheOther(final Method a, final Method b) {
+        val aType = a.getDeclaringClass();
+        val bType = b.getDeclaringClass();
+        if(aType.equals(bType)) {
+            val aReturn = a.getReturnType();
+            val bReturn = b.getReturnType();
+            if(aReturn.equals(bReturn)) {
+                // we should not care, arbitrarily picking b
+                return b;
+            }
+            return aReturn.isAssignableFrom(bReturn)
+                    ? b
+                    : a;
+        }
+        return aType.isAssignableFrom(bType)
+                ? b
+                : a;
+    }
 
 }

Reply via email to