Repository: deltaspike
Updated Branches:
  refs/heads/master 5685edbf5 -> 7b55ff21d


DELTASPIKE-1303 List/Set support for @Configuration proxy based interfaces


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

Branch: refs/heads/master
Commit: 7b55ff21da633b11ac84a6526fce0b64473ca669
Parents: 5685edb
Author: Romain Manni-Bucau <rmannibu...@gmail.com>
Authored: Wed Nov 29 11:30:01 2017 +0100
Committer: Romain Manni-Bucau <rmannibu...@gmail.com>
Committed: Wed Nov 29 11:30:01 2017 +0100

----------------------------------------------------------------------
 .../core/api/config/ConfigResolver.java         |  13 +-
 .../config/ProxyConfigurationLifecycle.java     | 171 +++++++++++++++----
 .../core/api/config/injectable/ConfigBean.java  |   7 +
 .../InjectableConfigPropertyTest.java           |   3 +
 4 files changed, 159 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7b55ff21/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
 
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
index f3f8743..9082584 100644
--- 
a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
+++ 
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/config/ConfigResolver.java
@@ -915,7 +915,14 @@ public final class ConfigResolver
                         + keyOriginal);
             }
 
-            defaultValue = convert(value);
+            if (isList)
+            {
+                defaultValue = splitAndConvertListValue(value);
+            }
+            else
+            {
+                defaultValue = convert(value);
+            }
             withDefault = true;
             return this;
         }
@@ -1006,6 +1013,10 @@ public final class ConfigResolver
                         .setEvaluateVariables(evaluateVariables)
                         .setProjectStageAware(projectStageAware);
                 value = fallbackToDefaultIfEmpty(keyResolved, value, 
defaultValue, configResolverContext);
+                if (isList && String.class.isInstance(value))
+                {
+                    value = splitAndConvertListValue(String.class.cast(value));
+                }
             }
 
             if (logChanges && (value != null && !value.equals(lastValue) || 
(value == null && lastValue != null)) )

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7b55ff21/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java
 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java
index 13c687e..4387a11 100644
--- 
a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java
+++ 
b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/config/ProxyConfigurationLifecycle.java
@@ -29,7 +29,12 @@ import javax.enterprise.inject.spi.Bean;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
@@ -72,8 +77,8 @@ class ProxyConfigurationLifecycle implements 
ContextualLifecycle
         {
         };
 
-        private final ConcurrentMap<Method, ConfigResolver.TypedResolver<?>> 
resolvers =
-                new ConcurrentHashMap<Method, 
ConfigResolver.TypedResolver<?>>();
+        private final ConcurrentMap<Method, Supplier<?>> resolvers =
+                new ConcurrentHashMap<Method, Supplier<?>>();
         private final long cacheMs;
         private final String prefix;
 
@@ -98,8 +103,8 @@ class ProxyConfigurationLifecycle implements 
ContextualLifecycle
                 }
             }
 
-            ConfigResolver.TypedResolver<?> typedResolver = 
resolvers.get(method);
-            if (typedResolver == null)
+            Supplier<?> supplier = resolvers.get(method);
+            if (supplier == null)
             {
                 final ConfigProperty annotation = 
method.getAnnotation(ConfigProperty.class);
                 if (annotation == null)
@@ -109,52 +114,150 @@ class ProxyConfigurationLifecycle implements 
ContextualLifecycle
                 }
 
                 // handle primitive bridge there (cdi doesnt support 
primitives but no reason our proxies don't)
+                final Class<? extends ConfigResolver.Converter> converter = 
annotation.converter();
+
+                final Type genericReturnType = method.getGenericReturnType();
                 Class<?> returnType = method.getReturnType();
-                if (int.class == returnType)
-                {
-                    returnType = Integer.class;
-                }
-                else if (long.class == returnType)
-                {
-                    returnType = Long.class;
-                }
-                else if (boolean.class == returnType)
-                {
-                    returnType = Boolean.class;
-                }
-                else if (short.class == returnType)
-                {
-                    returnType = Short.class;
-                }
-                else if (byte.class == returnType)
-                {
-                    returnType = Byte.class;
-                }
-                else if (float.class == returnType)
+                final boolean list;
+                final boolean set;
+                if (converter == ConfigResolver.Converter.class &&
+                        ParameterizedType.class.isInstance(genericReturnType))
                 {
-                    returnType = Float.class;
+                    ParameterizedType pt = 
ParameterizedType.class.cast(genericReturnType);
+                    if (List.class == pt.getRawType() && 
pt.getActualTypeArguments().length == 1)
+                    {
+                        list = true;
+                        set = false;
+                        final Type arg = pt.getActualTypeArguments()[0];
+                        if (Class.class.isInstance(arg))
+                        {
+                            returnType = Class.class.cast(arg);
+                        }
+                    }
+                    else if (Set.class == pt.getRawType() && 
pt.getActualTypeArguments().length == 1)
+                    {
+                        list = false;
+                        set = true;
+                        final Type arg = pt.getActualTypeArguments()[0];
+                        if (Class.class.isInstance(arg))
+                        {
+                            returnType = Class.class.cast(arg);
+                        }
+                    }
+                    else
+                    {
+                        list = false;
+                        set = false;
+                    }
                 }
-                else if (double.class == returnType)
+                else
                 {
-                    returnType = Double.class;
+                    list = false;
+                    set = false;
+
+                    if (int.class == returnType)
+                    {
+                        returnType = Integer.class;
+                    }
+                    else if (long.class == returnType)
+                    {
+                        returnType = Long.class;
+                    }
+                    else if (boolean.class == returnType)
+                    {
+                        returnType = Boolean.class;
+                    }
+                    else if (short.class == returnType)
+                    {
+                        returnType = Short.class;
+                    }
+                    else if (byte.class == returnType)
+                    {
+                        returnType = Byte.class;
+                    }
+                    else if (float.class == returnType)
+                    {
+                        returnType = Float.class;
+                    }
+                    else if (double.class == returnType)
+                    {
+                        returnType = Double.class;
+                    }
                 }
 
-                typedResolver = delegate.asResolver(
-                        prefix + annotation.name(), annotation.defaultValue(), 
returnType,
-                        annotation.converter(), annotation.parameterizedBy(),
+                final String defaultValue = annotation.defaultValue();
+                ConfigResolver.TypedResolver<?> typedResolver = 
delegate.asResolver(
+                        prefix + annotation.name(), list || set ? 
ConfigProperty.NULL : defaultValue,
+                        returnType, converter, annotation.parameterizedBy(),
                         annotation.projectStageAware(), 
annotation.evaluateVariables());
+
                 if (cacheMs > 0)
                 {
                     typedResolver.cacheFor(MILLISECONDS, cacheMs);
                 }
 
-                final ConfigResolver.TypedResolver<?> existing = 
resolvers.putIfAbsent(method, typedResolver);
+                if (list || set)
+                {
+                    ConfigResolver.TypedResolver<? extends List<?>> 
listTypedResolver = typedResolver.asList();
+                    final ConfigResolver.TypedResolver<? extends List<?>> 
resolver;
+                    if (!ConfigProperty.NULL.equals(defaultValue))
+                    {
+                        resolver = 
listTypedResolver.withStringDefault(defaultValue);
+                    }
+                    else
+                    {
+                        resolver = listTypedResolver;
+                    }
+
+                    if (list)
+                    {
+                        supplier = new DefaultSupplier(resolver);
+                    }
+                    else
+                    {
+                        supplier = new Supplier<Set<?>>()
+                        {
+                            @Override
+                            public Set<?> get()
+                            {
+                                return new HashSet(resolver.getValue());
+                            }
+                        };
+                    }
+                }
+                else
+                {
+                    supplier = new DefaultSupplier(typedResolver);
+                }
+
+                final Supplier<?> existing = resolvers.putIfAbsent(method, 
supplier);
                 if (existing != null)
                 {
-                    typedResolver = existing;
+                    supplier = existing;
                 }
             }
-            return typedResolver.getValue();
+            return supplier.get();
+        }
+    }
+
+    private interface Supplier<T>
+    {
+        T get();
+    }
+
+    private static class DefaultSupplier<T> implements Supplier<T>
+    {
+        private final ConfigResolver.TypedResolver<T> delegate;
+
+        private DefaultSupplier(final ConfigResolver.TypedResolver<T> delegate)
+        {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public T get()
+        {
+            return delegate.getValue();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7b55ff21/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java
 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java
index 40bcb45..8157f26 100644
--- 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java
+++ 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/ConfigBean.java
@@ -23,6 +23,7 @@ import org.apache.deltaspike.core.api.config.Configuration;
 
 import java.net.URL;
 import java.util.List;
+import java.util.Set;
 
 @Configuration
 public interface ConfigBean
@@ -72,6 +73,12 @@ public interface ConfigBean
     @ConfigProperty(name = "testDbConfig")
     String dbConfig();
 
+    @ConfigProperty(name = "defaultList", defaultValue = 
"http://localhost,http://127.0.0.1";)
+    List<String> defaultListHandling();
+
+    @ConfigProperty(name = "defaultSet", defaultValue = "1,2")
+    Set<Integer> defaultSetHandling();
+
     @ConfigProperty(name = "urlList", converter = SettingsBean.UrlList.class, 
defaultValue = "http://localhost,http://127.0.0.1";)
     List<URL> urlList();
 

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7b55ff21/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
----------------------------------------------------------------------
diff --git 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
index 5009949..ec74c1a 100644
--- 
a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
+++ 
b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/config/injectable/InjectableConfigPropertyTest.java
@@ -20,6 +20,7 @@ package org.apache.deltaspike.test.core.api.config.injectable;
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.HashSet;
 
 import org.apache.deltaspike.core.api.provider.BeanProvider;
 import org.apache.deltaspike.test.category.SeCategory;
@@ -146,6 +147,8 @@ public class InjectableConfigPropertyTest
         assertEquals(Boolean.TRUE, settingsBean.booleanPropertyTrue7());
         assertEquals(Boolean.TRUE, settingsBean.booleanPropertyTrue8());
         assertEquals(asList(new URL("http://localhost";), new 
URL("http://127.0.0.1";)), settingsBean.urlList());
+        assertEquals(asList("http://localhost";, "http://127.0.0.1";), 
settingsBean.defaultListHandling());
+        assertEquals(new HashSet<Integer>(asList(1, 2)), 
settingsBean.defaultSetHandling());
         assertEquals(singletonList(new URL("http://127.0.0.2";)), 
settingsBean.urlListFromProperties());
         assertEquals("value", settingsBean.customSourceValue());
     }

Reply via email to