Author: sseifert
Date: Mon Nov 28 22:42:33 2016
New Revision: 1771825
URL: http://svn.apache.org/viewvc?rev=1771825&view=rev
Log:
SLING-6338 support nested configuration classes when detecting configuration
metadata
Modified:
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationProxy.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/example/NestedConfig.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationProxyTest.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParserTest.java
sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadata.java
sling/trunk/contrib/extensions/contextaware-config/spi/src/test/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadataTest.java
Modified:
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationProxy.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationProxy.java?rev=1771825&r1=1771824&r2=1771825&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationProxy.java
(original)
+++
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationProxy.java
Mon Nov 28 22:42:33 2016
@@ -58,8 +58,8 @@ final class ConfigurationProxy {
public @Nonnull static <T> T get(@Nullable Resource resource, @Nonnull
Class<T> clazz, ChildResolver childResolver) {
// only annotation interface classes are supported
- if (!AnnotationClassParser.isContextAwareConfig(clazz)) {
- throw new ConfigurationResolveException("Annotation interface
class with @Configuration annotation expected: " + clazz.getName());
+ if (!clazz.isAnnotation()) {
+ throw new ConfigurationResolveException("Annotation interface
class expected: " + clazz.getName());
}
// create dynamic proxy for annotation class accessing underlying
resource properties
@@ -101,7 +101,7 @@ final class ConfigurationProxy {
if (isArray) {
componentType = targetType.getComponentType();
}
- if (AnnotationClassParser.isContextAwareConfig(componentType)) {
+ if (componentType.isAnnotation()) {
if (isArray) {
Collection<?> listItems =
childResolver.getChildren(propName, componentType);
return
listItems.toArray((Object[])Array.newInstance(componentType, listItems.size()));
Modified:
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java?rev=1771825&r1=1771824&r2=1771825&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java
(original)
+++
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java
Mon Nov 28 22:42:33 2016
@@ -128,22 +128,54 @@ public final class AnnotationClassParser
configMetadata.setCollection(configAnnotation.collection());
// property metadata
+
configMetadata.setPropertyMetadata(buildConfigurationMetadata_PropertyMetadata(clazz));
+
+ return configMetadata;
+ }
+
+ /**
+ * Build configuration metadata by parsing the given annotation interface
class which is used for nested configurations.
+ * @param clazz Configuration annotation class
+ * @return Configuration metadata
+ */
+ private static ConfigurationMetadata
buildConfigurationMetadata_Nested(Class<?> clazz) {
+ ConfigurationMetadata configMetadata = new ConfigurationMetadata("{" +
clazz.getName() + "}");
+
+ // property metadata
+
configMetadata.setPropertyMetadata(buildConfigurationMetadata_PropertyMetadata(clazz));
+
+ return configMetadata;
+ }
+
+ private static Map<String,PropertyMetadata<?>>
buildConfigurationMetadata_PropertyMetadata(Class<?> clazz) {
Map<String,PropertyMetadata<?>> propertyMetadataList = new HashMap<>();
Method[] propertyMethods = clazz.getDeclaredMethods();
for (Method propertyMethod : propertyMethods) {
PropertyMetadata<?> propertyMetadata =
buildPropertyMetadata(propertyMethod, propertyMethod.getReturnType());
propertyMetadataList.put(propertyMetadata.getName(),
propertyMetadata);
}
- configMetadata.setPropertyMetadata(propertyMetadataList);
-
- return configMetadata;
+ return propertyMetadataList;
}
@SuppressWarnings("unchecked")
private static <T> PropertyMetadata<T> buildPropertyMetadata(Method
propertyMethod, Class<T> type) {
String propertyName = getPropertyName(propertyMethod.getName());
- PropertyMetadata<T> propertyMetadata = new
PropertyMetadata<>(propertyName, type);
- propertyMetadata.setDefaultValue((T)propertyMethod.getDefaultValue());
+
+ PropertyMetadata propertyMetadata;
+ if (type.isArray() && type.getComponentType().isAnnotation()) {
+ ConfigurationMetadata nestedConfigMetadata =
buildConfigurationMetadata_Nested(type.getComponentType());
+ propertyMetadata = new PropertyMetadata<>(propertyName,
ConfigurationMetadata[].class);
+ propertyMetadata.setConfigurationMetadata(nestedConfigMetadata);
+ }
+ else if (type.isAnnotation()) {
+ ConfigurationMetadata nestedConfigMetadata =
buildConfigurationMetadata_Nested(type);
+ propertyMetadata = new PropertyMetadata<>(propertyName,
ConfigurationMetadata.class);
+ propertyMetadata.setConfigurationMetadata(nestedConfigMetadata);
+ }
+ else {
+ propertyMetadata = new PropertyMetadata<>(propertyName, type);
+
propertyMetadata.setDefaultValue((T)propertyMethod.getDefaultValue());
+ }
Property propertyAnnotation =
propertyMethod.getAnnotation(Property.class);
if (propertyAnnotation != null) {
Modified:
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/example/NestedConfig.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/example/NestedConfig.java?rev=1771825&r1=1771824&r2=1771825&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/example/NestedConfig.java
(original)
+++
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/example/NestedConfig.java
Mon Nov 28 22:42:33 2016
@@ -28,5 +28,7 @@ public @interface NestedConfig {
SimpleConfig subConfig();
ListConfig[] subListConfig();
+
+ WithoutAnnotationConfig subConfigWithoutAnnotation();
}
Modified:
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationProxyTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationProxyTest.java?rev=1771825&r1=1771824&r2=1771825&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationProxyTest.java
(original)
+++
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationProxyTest.java
Mon Nov 28 22:42:33 2016
@@ -46,6 +46,7 @@ import org.apache.sling.caconfig.example
import org.apache.sling.caconfig.example.NestedConfig;
import org.apache.sling.caconfig.example.SimpleConfig;
import org.apache.sling.caconfig.example.SpecialNamesConfig;
+import org.apache.sling.caconfig.example.WithoutAnnotationConfig;
import org.apache.sling.caconfig.impl.ConfigurationProxy.ChildResolver;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Rule;
@@ -154,7 +155,8 @@ public class ConfigurationProxyTest {
.resource("/test/subConfig", "stringParam", "v2", "intParam", 444,
"boolParam", true)
.resource("/test/subListConfig/1", "stringParam", "v3.1")
.resource("/test/subListConfig/2", "stringParam", "v3.2")
- .resource("/test/subListConfig/3", "stringParam", "v3.3");
+ .resource("/test/subListConfig/3", "stringParam", "v3.3")
+ .resource("/test/subConfigWithoutAnnotation", "stringParam", "v4");
Resource resource = context.resourceResolver().getResource("/test");
@@ -172,6 +174,9 @@ public class ConfigurationProxyTest {
assertEquals("v3.1", listConfig[0].stringParam());
assertEquals("v3.2", listConfig[1].stringParam());
assertEquals("v3.3", listConfig[2].stringParam());
+
+ WithoutAnnotationConfig subConfigWithoutAnnotation =
cfg.subConfigWithoutAnnotation();
+ assertEquals("v4", subConfigWithoutAnnotation.stringParam());
}
@Test(expected=ConfigurationResolveException.class)
Modified:
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParserTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParserTest.java?rev=1771825&r1=1771824&r2=1771825&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParserTest.java
(original)
+++
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParserTest.java
Mon Nov 28 22:42:33 2016
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertEqu
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.util.Collection;
@@ -33,6 +34,7 @@ import org.apache.commons.lang3.StringUt
import org.apache.sling.caconfig.example.AllTypesConfig;
import org.apache.sling.caconfig.example.ListConfig;
import org.apache.sling.caconfig.example.MetadataSimpleConfig;
+import org.apache.sling.caconfig.example.NestedConfig;
import org.apache.sling.caconfig.example.SimpleConfig;
import org.apache.sling.caconfig.example.WithoutAnnotationConfig;
import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
@@ -98,11 +100,14 @@ public class AnnotationClassParserTest {
assertTrue(propertyMetadata.getProperties().isEmpty());
assertEquals(5, propertyMetadata.getDefaultValue());
}
- else if (StringUtils.equals(propertyMetadata.getName(),
"booleanParam")) {
+ else if (StringUtils.equals(propertyMetadata.getName(),
"boolParam")) {
assertNull(propertyMetadata.getLabel());
assertNull(propertyMetadata.getDescription());
assertTrue(propertyMetadata.getProperties().isEmpty());
- assertFalse((Boolean)propertyMetadata.getDefaultValue());
+ assertNull(propertyMetadata.getDefaultValue());
+ }
+ else {
+ fail("Unexpected property name: " +
propertyMetadata.getName());
}
}
}
@@ -126,6 +131,43 @@ public class AnnotationClassParserTest {
assertEquals(20, metadata.getPropertyMetadata().size());
}
+ @Test
+ public void testBuildConfigurationMetadata_Nested() {
+ ConfigurationMetadata metadata =
buildConfigurationMetadata(NestedConfig.class);
+
+ assertEquals(NestedConfig.class.getName(), metadata.getName());
+
+ Collection<PropertyMetadata<?>> propertyMetadataList =
metadata.getPropertyMetadata().values();
+ assertEquals(4, propertyMetadataList.size());
+
+ for (PropertyMetadata<?> propertyMetadata : propertyMetadataList) {
+ if (StringUtils.equals(propertyMetadata.getName(), "stringParam"))
{
+ assertEquals(String.class, propertyMetadata.getType());
+ }
+ else if (StringUtils.equals(propertyMetadata.getName(),
"subConfig")) {
+ assertEquals(ConfigurationMetadata.class,
propertyMetadata.getType());
+
+ ConfigurationMetadata subConfigMetadata =
propertyMetadata.getConfigurationMetadata();
+ assertEquals(3,
subConfigMetadata.getPropertyMetadata().size());
+ }
+ else if (StringUtils.equals(propertyMetadata.getName(),
"subListConfig")) {
+ assertEquals(ConfigurationMetadata[].class,
propertyMetadata.getType());
+
+ ConfigurationMetadata subListConfigMetadata =
propertyMetadata.getConfigurationMetadata();
+ assertEquals(2,
subListConfigMetadata.getPropertyMetadata().size());
+ }
+ else if (StringUtils.equals(propertyMetadata.getName(),
"subConfigWithoutAnnotation")) {
+ assertEquals(ConfigurationMetadata.class,
propertyMetadata.getType());
+
+ ConfigurationMetadata subConfigWithoutAnnotationMetadata =
propertyMetadata.getConfigurationMetadata();
+ assertEquals(1,
subConfigWithoutAnnotationMetadata.getPropertyMetadata().size());
+ }
+ else {
+ fail("Unexpected property name: " +
propertyMetadata.getName());
+ }
+ }
+ }
+
@Test(expected = IllegalArgumentException.class)
public void testBuildConfigurationMetadata_IllegalClass() {
buildConfigurationMetadata(WithoutAnnotationConfig.class);
Modified:
sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadata.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadata.java?rev=1771825&r1=1771824&r2=1771825&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadata.java
(original)
+++
sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadata.java
Mon Nov 28 22:42:33 2016
@@ -52,6 +52,7 @@ public final class PropertyMetadata<T> e
private final Class<T> type;
private T defaultValue;
+ private ConfigurationMetadata configurationMetadata;
/**
* @param name Property name
@@ -122,6 +123,20 @@ public final class PropertyMetadata<T> e
public void setDefaultValue(T value) {
this.defaultValue = value;
}
+
+ /**
+ * @return Metadata for nested configuration
+ */
+ public ConfigurationMetadata getConfigurationMetadata() {
+ return configurationMetadata;
+ }
+
+ /**
+ * @param configurationMetadata Metadata for nested configuration
+ */
+ public void setConfigurationMetadata(ConfigurationMetadata
configurationMetadata) {
+ this.configurationMetadata = configurationMetadata;
+ }
@Override
public String toString() {
Modified:
sling/trunk/contrib/extensions/contextaware-config/spi/src/test/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadataTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/spi/src/test/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadataTest.java?rev=1771825&r1=1771824&r2=1771825&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/contextaware-config/spi/src/test/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadataTest.java
(original)
+++
sling/trunk/contrib/extensions/contextaware-config/spi/src/test/java/org/apache/sling/caconfig/spi/metadata/PropertyMetadataTest.java
Mon Nov 28 22:42:33 2016
@@ -19,6 +19,7 @@
package org.apache.sling.caconfig.spi.metadata;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
import java.util.Map;
@@ -40,10 +41,14 @@ public class PropertyMetadataTest {
Map<String,String> props = ImmutableMap.of("p1", "v1");
underTest.setProperties(props);
+ ConfigurationMetadata configMetadata = new
ConfigurationMetadata("test");
+ underTest.setConfigurationMetadata(configMetadata);
+
assertEquals("label1", underTest.getLabel());
assertEquals("desc1", underTest.getDescription());
assertEquals("value1", underTest.getDefaultValue());
assertEquals(props, underTest.getProperties());
+ assertSame(configMetadata, underTest.getConfigurationMetadata());
}
@Test