You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2021/09/30 15:02:09 UTC

[brooklyn-server] 02/03: logic for looking at merger of typetokens

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

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit c8987208d507681b67c5d4323b87407fb67893b8
Author: Alex Heneveld <al...@cloudsoftcorp.com>
AuthorDate: Thu Sep 30 16:01:40 2021 +0100

    logic for looking at merger of typetokens
---
 .../org/apache/brooklyn/util/guava/TypeTokens.java | 36 ++++++++++++++++++++++
 .../apache/brooklyn/util/guava/TypeTokensTest.java |  7 +++++
 2 files changed, 43 insertions(+)

diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/TypeTokens.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/TypeTokens.java
index 28c1f1c..19ff464 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/guava/TypeTokens.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/TypeTokens.java
@@ -19,6 +19,7 @@
 package org.apache.brooklyn.util.guava;
 
 import com.fasterxml.jackson.databind.type.ArrayType;
+import com.google.common.annotations.Beta;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
@@ -185,4 +186,39 @@ public class TypeTokens {
         return getGenericParameterTypeTokensWhenUpcastToClass(t, (Class)clazz);
     }
 
+    /** find the lowest common ancestor of the two types, filling in generics info, and ignoring Object; but that's hard so this does some heuristics for common cases */
+    @Beta
+    public static TypeToken<?> union(TypeToken<?> t1, TypeToken<?> t2, boolean ignoreObject) {
+        if (t1.equals(t2)) return t1;
+
+        if (ignoreObject) {
+            if (t1.getRawType().equals(Object.class)) return t2;
+            if (t2.getRawType().equals(Object.class)) return t1;
+        }
+
+        if (t1.getRawType().equals(t2.getRawType())) {
+            // if equal, prefer one whose generics are more specific
+            TypeToken<?>[] tokens1 = getGenericParameterTypeTokens(t1);
+            TypeToken<?>[] tokens2 = getGenericParameterTypeTokens(t1);
+            if (tokens1.length>0 && tokens2.length>0) {
+                // just look at first one to see who wins
+                TypeToken<?> union0 = union(tokens1[0], tokens2[0], true);
+                if (union0==tokens2[0]) return t2;
+                return t1;
+            } else if (tokens2.length>0) {
+                return t2;
+            }
+            return t1;
+        }
+
+        // prefer an ancestor (ideally we'd infer generics if needed at the parent, but skip for now)
+        if (t1.isAssignableFrom(t2)) return t1;
+        if (t2.isAssignableFrom(t1)) return t2;
+        if (t1.getRawType().isAssignableFrom(t2.getRawType())) return t1;
+        if (t2.getRawType().isAssignableFrom(t1.getRawType())) return t2;
+
+        // can't figure anything out, just pick one
+        return t1;
+    }
+
 }
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/guava/TypeTokensTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/guava/TypeTokensTest.java
index edcf55d..ab63e51 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/guava/TypeTokensTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/guava/TypeTokensTest.java
@@ -24,6 +24,7 @@ import java.util.List;
 import java.util.Map;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.exceptions.UserFacingException;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -37,4 +38,10 @@ public class TypeTokensTest {
         Assert.assertEquals(genericArguments, MutableList.of(TypeToken.of(String.class), TypeToken.of(Integer.class)));
     }
 
+    @Test
+    public void testLowestCommonAncestor() {
+        TypeToken<?> map1 = new TypeToken<Map<String,Integer>>() {};
+        Assert.assertEquals( TypeTokens.union(TypeToken.of(MutableMap.class), map1, true), map1);
+    }
+
 }