You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by gr...@apache.org on 2014/10/06 00:44:27 UTC
[03/13] git commit: Add type coercion for parameterized collections
and their entries
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 <gr...@apache.org>
Authored: Sat Sep 20 23:25:13 2014 +0100
Committer: Andrew Kennedy <gr...@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() {