From e5e5f65835312bc2744f1a6d75ce5ecb39edede7 Mon Sep 17 00:00:00 2001 From: Eran Landau Date: Mon, 15 Aug 2016 23:16:45 -0700 Subject: [PATCH] Support single values in maps (not just proxied interfaces) --- .../netflix/archaius/ConfigProxyFactory.java | 38 ++++++++++++------- .../netflix/archaius/ProxyFactoryTest.java | 25 ++++++++++++ 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/archaius2-core/src/main/java/com/netflix/archaius/ConfigProxyFactory.java b/archaius2-core/src/main/java/com/netflix/archaius/ConfigProxyFactory.java index f76740a65..43ccb5b90 100644 --- a/archaius2-core/src/main/java/com/netflix/archaius/ConfigProxyFactory.java +++ b/archaius2-core/src/main/java/com/netflix/archaius/ConfigProxyFactory.java @@ -183,7 +183,7 @@ T newProxy(final Class type, final String initialPrefix, boolean immutabl invokers.put(m, createMapProperty(propName, (ParameterizedType)m.getGenericReturnType(), immutable)); } else if (returnType.isInterface()) { invokers.put(m, createInterfaceProperty(propName, newProxy(returnType, propName, immutable))); - } else if (m.getParameterTypes().length > 0) { + } else if (m.getParameterTypes() != null && m.getParameterTypes().length > 0) { invokers.put(m, createParameterizedProperty(returnType, propName, nameAnnot.name(), defaultValue)); } else if (immutable) { invokers.put(m, createImmutablePropertyWithDefault(m.getReturnType(), propName, defaultValue)); @@ -233,18 +233,30 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl @SuppressWarnings("unchecked") private MethodInvoker createMapProperty(final String propName, final ParameterizedType type, final boolean immutable) { final Class valueType = (Class)type.getActualTypeArguments()[1]; - Map map = new ReadOnlyMap() { - Map lookup = new ConcurrentHashMap(); - @Override - public Object get(final Object key) { - return lookup.computeIfAbsent((String) key, new Function() { - @Override - public Object apply(String key) { - return newProxy(valueType, propName + "." + key, immutable); - } - }); - } - }; + Map map; + // This is a map for String -> Interface so create a proxy for any value + if (valueType.isInterface()) { + map = new ReadOnlyMap() { + Map lookup = new ConcurrentHashMap(); + @Override + public Object get(final Object key) { + return lookup.computeIfAbsent((String) key, new Function() { + @Override + public Object apply(String key) { + return newProxy(valueType, propName + "." + key, immutable); + } + }); + } + }; + } else { + // This is a map of String -> DecodableType (i.e. String, Long, etc...) + map = new ReadOnlyMap() { + @Override + public Object get(final Object key) { + return config.get(valueType, propName + "." + key); + } + }; + } return (MethodInvoker) createInterfaceProperty(propName, map); } diff --git a/archaius2-core/src/test/java/com/netflix/archaius/ProxyFactoryTest.java b/archaius2-core/src/test/java/com/netflix/archaius/ProxyFactoryTest.java index 96d872579..f455af07e 100644 --- a/archaius2-core/src/test/java/com/netflix/archaius/ProxyFactoryTest.java +++ b/archaius2-core/src/test/java/com/netflix/archaius/ProxyFactoryTest.java @@ -206,4 +206,29 @@ public void testWithMap() { config.setProperty("children.2.str", "value3"); Assert.assertEquals("value3", sub2.str()); } + + public static interface ConfigWithLongMap { + Map getChildren(); + } + + @Test + public void testWithLongMap() { + SettableConfig config = new DefaultSettableConfig(); + config.setProperty("children.1", "123"); + config.setProperty("children.2", "456"); + + PropertyFactory factory = DefaultPropertyFactory.from(config); + ConfigProxyFactory proxy = new ConfigProxyFactory(config, config.getDecoder(), factory); + ConfigWithLongMap withArgs = proxy.newProxy(ConfigWithLongMap.class); + + long sub1 = withArgs.getChildren().get("1"); + long sub2 = withArgs.getChildren().get("2"); + + Assert.assertEquals(123, sub1); + Assert.assertEquals(456, sub2); + + config.setProperty("children.2", "789"); + sub2 = withArgs.getChildren().get("2"); + Assert.assertEquals(789, sub2); + } }