brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From grk...@apache.org
Subject [03/13] git commit: Add type coercion for parameterized collections and their entries
Date Sun, 05 Oct 2014 22:44:27 GMT
Add type coercion for parameterized collections and their entries


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/7744582f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/7744582f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/7744582f

Branch: refs/heads/master
Commit: 7744582f0440359c4e57b7826d024d42035d84fb
Parents: 6c1c3b2
Author: Andrew Kennedy <grkvlt@apache.org>
Authored: Sat Sep 20 23:25:13 2014 +0100
Committer: Andrew Kennedy <grkvlt@apache.org>
Committed: Sun Oct 5 19:45:53 2014 +0100

----------------------------------------------------------------------
 .../java/brooklyn/util/flags/TypeCoercions.java | 62 +++++++++++++++++---
 .../util/internal/TypeCoercionsTest.java        | 31 ++++++++++
 2 files changed, 84 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7744582f/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
index c71d8cc..82a0241 100644
--- a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
+++ b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
@@ -24,14 +24,14 @@ import groovy.time.TimeDuration;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.URI;
 import java.net.URL;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -43,6 +43,7 @@ import javax.annotation.concurrent.GuardedBy;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.testng.collections.Maps;
 
 import brooklyn.entity.basic.ClosureEntityFactory;
 import brooklyn.entity.basic.ConfigurableEntityFactory;
@@ -62,6 +63,7 @@ import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 import brooklyn.util.yaml.Yamls;
 
+import com.google.api.client.util.Lists;
 import com.google.common.base.CaseFormat;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
@@ -69,6 +71,7 @@ import com.google.common.base.Predicate;
 import com.google.common.collect.HashBasedTable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
 import com.google.common.collect.Table;
 import com.google.common.net.HostAndPort;
 import com.google.common.primitives.Primitives;
@@ -116,9 +119,43 @@ public class TypeCoercions {
     @SuppressWarnings({ "unchecked" })
     public static <T> T coerce(Object value, TypeToken<T> targetTypeToken) {
         if (value==null) return null;
-        // does not actually cast generified contents; that is left to the caller
         Class<? super T> targetType = targetTypeToken.getRawType();
 
+        //recursive coercion of parameterized collections and map entries
+        if (targetTypeToken.getType() instanceof ParameterizedType) {
+            if (value instanceof Iterable && Collection.class.isAssignableFrom(targetType))
{
+                Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments();
+                if (arguments.length != 1) {
+                    throw new IllegalStateException("Unexpected number of parameters in collection
type: " + arguments);
+                }
+                Collection coerced = Lists.newArrayList();
+                TypeToken<?> parameterType = TypeToken.of(arguments[0]);
+                for (Object entry : (Iterable<?>) value) {
+                    Maybe<?> result = tryCoerce(entry, parameterType);
+                    coerced.add(result.get());
+                }
+                if (Set.class.isAssignableFrom(targetType)) {
+                    return (T) Sets.newHashSet(coerced);
+                } else {
+                    return (T) coerced;
+                }
+            } else if (value instanceof Map && Map.class.isAssignableFrom(targetType))
{
+                Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments();
+                if (arguments.length != 2) {
+                    throw new IllegalStateException("Unexpected number of parameters in map
type: " + arguments);
+                }
+                Map coerced = Maps.newHashMap();
+                TypeToken<?> mapKeyType = TypeToken.of(arguments[0]);
+                TypeToken<?> mapValueType = TypeToken.of(arguments[1]);
+                for (Map.Entry entry : ((Map<?,?>) value).entrySet()) {
+                    Maybe<?> keyResult = tryCoerce(entry.getKey(), mapKeyType);
+                    Maybe<?> valueResult = tryCoerce(entry.getValue(), mapValueType);
+                    coerced.put(keyResult.get(), valueResult.get());
+                }
+                return (T) coerced;
+            }
+        }
+
         if (targetType.isInstance(value)) return (T) value;
 
         // TODO use registry first?
@@ -442,18 +479,25 @@ public class TypeCoercions {
                 return new String(input);
             }
         });
-        registerAdapter(Collection.class, Set.class, new Function<Collection,Set>()
{
+        registerAdapter(Iterable.class, Set.class, new Function<Iterable,Set>() {
+            @SuppressWarnings("unchecked")
+            @Override
+            public Set apply(Iterable input) {
+                return Sets.newLinkedHashSet(input);
+            }
+        });
+        registerAdapter(Iterable.class, List.class, new Function<Iterable,List>() {
             @SuppressWarnings("unchecked")
             @Override
-            public Set apply(Collection input) {
-                return new LinkedHashSet(input);
+            public List apply(Iterable input) {
+                return Lists.newArrayList(input);
             }
         });
-        registerAdapter(Collection.class, List.class, new Function<Collection,List>()
{
+        registerAdapter(Iterable.class, Collection.class, new Function<Iterable,Collection>()
{
             @SuppressWarnings("unchecked")
             @Override
-            public List apply(Collection input) {
-                return new ArrayList(input);
+            public Collection apply(Iterable input) {
+                return Lists.newArrayList(input);
             }
         });
         registerAdapter(String.class, InetAddress.class, new Function<String,InetAddress>()
{

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7744582f/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java b/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java
index 6efffa2..8ac1e9c 100644
--- a/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java
+++ b/core/src/test/java/brooklyn/util/internal/TypeCoercionsTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertEquals;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -183,6 +184,36 @@ public class TypeCoercionsTest {
         List<?> s = TypeCoercions.coerce(ImmutableSet.of(1), List.class);
         Assert.assertEquals(s, ImmutableList.of(1));
     }
+    
+    @Test
+    public void testListEntryCoercion() {
+        List<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer", "java.lang.Double"),
new TypeToken<List<Class<?>>>() { });
+        Assert.assertEquals(s, ImmutableList.of(Integer.class, Double.class));
+    }
+    
+    @Test
+    public void testListEntryToSetCoercion() {
+        Set<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer", "java.lang.Double"),
new TypeToken<Set<Class<?>>>() { });
+        Assert.assertEquals(s, ImmutableSet.of(Integer.class, Double.class));
+    }
+    
+    @Test
+    public void testListEntryToCollectionCoercion() {
+        Collection<?> s = TypeCoercions.coerce(ImmutableList.of("java.lang.Integer",
"java.lang.Double"), new TypeToken<Collection<Class<?>>>() { });
+        Assert.assertEquals(s, ImmutableList.of(Integer.class, Double.class));
+    }
+    
+    @Test
+    public void testMapValueCoercion() {
+        Map<?,?> s = TypeCoercions.coerce(ImmutableMap.of("int", "java.lang.Integer",
"double", "java.lang.Double"), new TypeToken<Map<String, Class<?>>>() {
});
+        Assert.assertEquals(s, ImmutableMap.of("int", Integer.class, "double", Double.class));
+    }
+    
+    @Test
+    public void testMapKeyCoercion() {
+        Map<?,?> s = TypeCoercions.coerce(ImmutableMap.of("java.lang.Integer", "int",
"java.lang.Double", "double"), new TypeToken<Map<Class<?>, String>>() {
});
+        Assert.assertEquals(s, ImmutableMap.of(Integer.class, "int", Double.class, "double"));
+    }
 
     @Test
     public void testStringToListCoercion() {


Mime
View raw message