brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From drigod...@apache.org
Subject [1/2] brooklyn-server git commit: Fix type-coercion to/from arrays
Date Mon, 29 May 2017 08:00:07 GMT
Repository: brooklyn-server
Updated Branches:
  refs/heads/master e69da19f9 -> 6c7751d74


Fix type-coercion to/from arrays

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/7fbd734a
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/7fbd734a
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/7fbd734a

Branch: refs/heads/master
Commit: 7fbd734a98d4af9823888baa763ffd611c89d33c
Parents: 75e8cc8
Author: Aled Sage <aled.sage@gmail.com>
Authored: Thu May 25 12:55:50 2017 +0100
Committer: Aled Sage <aled.sage@gmail.com>
Committed: Thu May 25 12:55:50 2017 +0100

----------------------------------------------------------------------
 utils/common/pom.xml                            |  5 ++
 .../brooklyn/util/javalang/Reflections.java     | 11 +++++
 .../coerce/CommonAdaptorTryCoercions.java       | 40 +++++++++++++++
 .../javalang/coerce/TypeCoercerExtensible.java  | 17 ++++++-
 .../brooklyn/util/javalang/ReflectionsTest.java |  6 +++
 .../util/javalang/coerce/TypeCoercionsTest.java | 52 ++++++++++++++++++++
 6 files changed, 130 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7fbd734a/utils/common/pom.xml
----------------------------------------------------------------------
diff --git a/utils/common/pom.xml b/utils/common/pom.xml
index c35ba0f..e1d7475 100644
--- a/utils/common/pom.xml
+++ b/utils/common/pom.xml
@@ -74,6 +74,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.testng</groupId>
             <artifactId>testng</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7fbd734a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
index 6929dd7..bedcc54 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
@@ -32,6 +32,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
@@ -1099,4 +1100,14 @@ public class Reflections {
         return hasSpecialSerializationMethods(type.getSuperclass());
     }
 
+    public static List<?> arrayToList(Object input) {
+        // We can't just use Arrays.asList(), because that would return a list containing
the single
+        // value "input".
+        List<Object> result = new ArrayList<>();
+        int length = Array.getLength(input);
+        for (int i = 0; i < length; i++) {
+            result.add(Array.get(input, i));
+        }
+        return result;
+    }
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7fbd734a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java
b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java
index b0a494a..890b8b7 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java
@@ -18,6 +18,7 @@
  */
 package org.apache.brooklyn.util.javalang.coerce;
 
+import java.lang.reflect.Array;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.List;
@@ -25,8 +26,10 @@ import java.util.List;
 import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
+import org.apache.brooklyn.util.javalang.Reflections;
 import org.apache.brooklyn.util.text.Strings;
 
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.reflect.TypeToken;
 
@@ -45,6 +48,7 @@ public class CommonAdaptorTryCoercions {
     public CommonAdaptorTryCoercions registerAllAdapters() {
         registerAdapter(new TryCoercerWithFromMethod());
         registerAdapter(new TryCoercerToEnum());
+        registerAdapter(new TryCoercerToArray(coercer));
         registerAdapter(new TryCoercerForPrimitivesAndStrings());
         return this;
     }
@@ -101,6 +105,42 @@ public class CommonAdaptorTryCoercions {
         }
     }
 
+    protected static class TryCoercerToArray implements TryCoercer {
+        private final TypeCoercerExtensible coercer;
+        
+        public TryCoercerToArray(TypeCoercerExtensible coercer) {
+            this.coercer = coercer;
+        }
+        
+        @Override
+        @SuppressWarnings("unchecked")
+        public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> targetType)
{
+            if (!targetType.isArray()) return null;
+            
+            TypeToken<?> targetComponentType = targetType.getComponentType();
+            Iterable<?> castInput;
+            if (input.getClass().isArray()) {
+                castInput = Reflections.arrayToList(input);
+            } else if (Iterable.class.isAssignableFrom(input.getClass())) {
+                castInput = (Iterable<?>) input;
+            } else {
+                return null;
+            }
+            
+            Object result = Array.newInstance(targetComponentType.getRawType(), Iterables.size(castInput));
+            int index = 0;
+            for (Object member : castInput) {
+                Maybe<?> coercedMember = coercer.tryCoerce(member, targetComponentType);
+                if (coercedMember == null || coercedMember.isAbsent()) {
+                    RuntimeException cause = Maybe.Absent.getException(coercedMember);
+                    return Maybe.absent("Array member at index "+index+" cannot be coerced
to "+targetComponentType, cause);
+                }
+                Array.set(result, index++, coercedMember.get());
+            }
+            return (Maybe<T>) Maybe.of(result);
+        }
+    }
+
     protected static class TryCoercerForPrimitivesAndStrings implements TryCoercer {
         @Override
         public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> targetType)
{

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7fbd734a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
index 7aeb3fb..fdf1940 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
@@ -29,6 +29,7 @@ import java.util.Set;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.javalang.Boxing;
+import org.apache.brooklyn.util.javalang.Reflections;
 import org.apache.brooklyn.util.time.Duration;
 import org.apache.brooklyn.util.time.Time;
 import org.slf4j.Logger;
@@ -124,7 +125,16 @@ public class TypeCoercerExtensible implements TypeCoercer {
                 result = tryCoerceIterable(value, targetTypeToken, targetType);
                 
                 if (result != null && result.isAbsent() && targetType.isInstance(value))
{
-                    log.warn("Failed to coerce collection from " + value.getClass().getName()
+ " to " + targetTypeToken  
+                    log.warn("Failed to coerce iterable from " + value.getClass().getName()
+ " to " + targetTypeToken  
+                            + "; returning uncoerced result to preserve (deprecated) backwards
compatibility", 
+                            Maybe.getException(result));
+                }
+                
+            } else if (value.getClass().isArray() && Iterable.class.isAssignableFrom(targetType))
{
+                result = tryCoerceArray(value, targetTypeToken, targetType);
+                
+                if (result != null && result.isAbsent() && targetType.isInstance(value))
{
+                    log.warn("Failed to coerce array from " + value.getClass().getName()
+ " to " + targetTypeToken  
                             + "; returning uncoerced result to preserve (deprecated) backwards
compatibility", 
                             Maybe.getException(result));
                 }
@@ -234,6 +244,11 @@ public class TypeCoercerExtensible implements TypeCoercer {
         return Maybe.of((T) Maps.newLinkedHashMap(coerced));
     }
 
+    protected <T> Maybe<T> tryCoerceArray(Object value, TypeToken<T> targetTypeToken,
Class<? super T> targetType) {
+       List<?> listValue = Reflections.arrayToList(value);
+       return tryCoerceIterable(listValue, targetTypeToken, targetType);
+    }
+    
     /** tries to coerce a list;
      * returns null if it just doesn't apply, a {@link Maybe.Present} if it succeeded,
      * or {@link Maybe.Absent} with a good exception if it should have applied but couldn't
*/

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7fbd734a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
index ba4b1d3..201cd86 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
@@ -172,6 +172,12 @@ public class ReflectionsTest {
         Assert.assertFalse(Reflections.invokeConstructorFromArgs(CI1.class, new Object[]
{"wrong", "args"}).isPresent());
     }
 
+    @Test
+    public void testArrayToList() throws Exception {
+        assertEquals(Reflections.arrayToList(new String[] {"a", "b"}), ImmutableList.of("a",
"b"));
+        assertEquals(Reflections.arrayToList((Object) new String[] {"a", "b"}), ImmutableList.of("a",
"b"));
+    }
+    
     interface I { };
     interface J extends I { };
     interface K extends I, J { };

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7fbd734a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
index bd66c2e..e8ff59d 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
@@ -37,6 +37,7 @@ import java.util.TimeZone;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.text.StringPredicates;
+import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.codehaus.groovy.runtime.GStringImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -197,6 +198,57 @@ public class TypeCoercionsTest {
     }
     
     @Test
+    public void testArrayToListCoercion() {
+        @SuppressWarnings("serial")
+        List<?> s = coerce(new String[] {"1", "2"}, new TypeToken<List<String>>()
{ });
+        Assert.assertEquals(s, ImmutableList.of("1", "2"));
+    }
+    
+    @Test
+    public void testArrayEntryCoercion() {
+        @SuppressWarnings("serial")
+        Integer[] val = coerce(new String[] {"1", "2"}, new TypeToken<Integer[]>()
{ });
+        Assert.assertTrue(Arrays.equals(val, new Integer[] {1, 2}), "val="+Arrays.toString(val)+"
of type "+val.getClass());
+    }
+    
+    @Test
+    public void testArrayEntryInvalidCoercion() {
+        try {
+            @SuppressWarnings("serial")
+            Integer[] val = coerce(new String[] {"myWrongVal"}, new TypeToken<Integer[]>()
{ });
+            Asserts.shouldHaveFailedPreviously("val="+val);
+        } catch (ClassCoercionException e) {
+            Asserts.expectedFailureContains(e, "Cannot coerce", "myWrongVal", "to java.lang.Integer");
+        }
+    }
+    
+    @Test
+    public void testListToArrayInvalidCoercion() {
+        try {
+            @SuppressWarnings("serial")
+            Integer[] val = coerce(ImmutableList.of("myWrongVal"), new TypeToken<Integer[]>()
{ });
+            Asserts.shouldHaveFailedPreviously("val="+val);
+        } catch (ClassCoercionException e) {
+            Asserts.expectedFailureContains(e, "Cannot coerce", "myWrongVal", "to java.lang.Integer");
+        }
+    }
+    
+    @Test
+    public void testArrayMultiDimensionEntryCoercion() {
+        @SuppressWarnings("serial")
+        Integer[][] val = coerce(new String[][] {{"1", "2"}, {"3", "4"}}, new TypeToken<Integer[][]>()
{ });
+        Assert.assertTrue(EqualsBuilder.reflectionEquals(val, new Integer[][] {{1, 2}, {3,
4}}), 
+                "val="+Arrays.toString(val)+" of type "+val.getClass());
+    }
+    
+    @Test
+    public void testArrayEntryToListCoercion() {
+        @SuppressWarnings("serial")
+        List<?> s = coerce(new String[] {"1", "2"}, new TypeToken<List<Integer>>()
{ });
+        Assert.assertEquals(s, ImmutableList.of(1, 2));
+    }
+    
+    @Test
     public void testListToSetCoercion() {
         Set<?> s = coerce(ImmutableList.of(1), Set.class);
         Assert.assertEquals(s, ImmutableSet.of(1));


Mime
View raw message