You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2016/11/30 15:34:44 UTC

svn commit: r1772057 - in /sling/trunk/contrib/extensions/contextaware-config: impl/src/main/java/org/apache/sling/caconfig/impl/ impl/src/main/java/org/apache/sling/caconfig/impl/def/ impl/src/main/java/org/apache/sling/caconfig/impl/metadata/ impl/sr...

Author: sseifert
Date: Wed Nov 30 15:34:44 2016
New Revision: 1772057

URL: http://svn.apache.org/viewvc?rev=1772057&view=rev
Log:
SLING-6338 refactor and fix handling of nested configurations in Management API and ConfigurationResourceResolver

Modified:
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.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/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexer.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategyTest.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/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerTest.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy.java
    sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationPersistenceStrategy.java

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java Wed Nov 30 15:34:44 2016
@@ -202,7 +202,7 @@ class ConfigurationBuilderImpl implement
         public T convert(final Resource resource, final Class<T> clazz, final String name) {
             return ConfigurationProxy.get(resource, clazz, new ChildResolver() {
                 private ConfigurationBuilder getConfiguration(String configName) {
-                    String childName = name + "/" + configName;
+                    String childName = configurationPersistenceStrategy.getResourcePath(name) + "/" + configName;
                     return configurationResolver.get(contentResource).name(childName);
                 }
                 @Override

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java Wed Nov 30 15:34:44 2016
@@ -74,6 +74,14 @@ public class DefaultConfigurationPersist
     }
 
     @Override
+    public String getResourcePath(String resourcePath) {
+        if (!config.enabled()) {
+            return null;
+        }
+        return resourcePath;
+    }
+
+    @Override
     public boolean persist(ResourceResolver resourceResolver, String configResourcePath, Map<String,Object> properties) {
         if (!config.enabled()) {
             return false;

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=1772057&r1=1772056&r2=1772057&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 Wed Nov 30 15:34:44 2016
@@ -138,8 +138,8 @@ public final class AnnotationClassParser
      * @param clazz Configuration annotation class
      * @return Configuration metadata
      */
-    private static ConfigurationMetadata buildConfigurationMetadata_Nested(Class<?> clazz) {
-        ConfigurationMetadata configMetadata = new ConfigurationMetadata("{" + clazz.getName() + "}");
+    private static ConfigurationMetadata buildConfigurationMetadata_Nested(Class<?> clazz, String configName) {
+        ConfigurationMetadata configMetadata = new ConfigurationMetadata(configName);
 
         // property metadata
         configMetadata.setPropertyMetadata(buildConfigurationMetadata_PropertyMetadata(clazz));
@@ -163,12 +163,12 @@ public final class AnnotationClassParser
         
         PropertyMetadata propertyMetadata;
         if (type.isArray() && type.getComponentType().isAnnotation()) {
-            ConfigurationMetadata nestedConfigMetadata = buildConfigurationMetadata_Nested(type.getComponentType());
+            ConfigurationMetadata nestedConfigMetadata = buildConfigurationMetadata_Nested(type.getComponentType(), propertyName);
             propertyMetadata = new PropertyMetadata<>(propertyName, ConfigurationMetadata[].class);
             propertyMetadata.setConfigurationMetadata(nestedConfigMetadata);
         }
         else if (type.isAnnotation()) {
-            ConfigurationMetadata nestedConfigMetadata = buildConfigurationMetadata_Nested(type);
+            ConfigurationMetadata nestedConfigMetadata = buildConfigurationMetadata_Nested(type, propertyName);
             propertyMetadata = new PropertyMetadata<>(propertyName, ConfigurationMetadata.class);
             propertyMetadata.setConfigurationMetadata(nestedConfigMetadata);
         }

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java Wed Nov 30 15:34:44 2016
@@ -19,6 +19,7 @@
 package org.apache.sling.caconfig.management.impl;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -35,20 +36,25 @@ import org.apache.sling.api.wrappers.Val
 import org.apache.sling.caconfig.impl.def.ConfigurationDefNameConstants;
 import org.apache.sling.caconfig.impl.override.ConfigurationOverrideManager;
 import org.apache.sling.caconfig.management.ConfigurationData;
+import org.apache.sling.caconfig.management.ConfigurationManager;
 import org.apache.sling.caconfig.management.ValueInfo;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
 import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
 import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
 
 final class ConfigurationDataImpl implements ConfigurationData {
     
-    private final ConfigurationMetadata configMetadata;
+    private ConfigurationMetadata configMetadata;
     private final Resource resolvedConfigurationResource;
     private final Resource writebackConfigurationResource;
     private final List<Resource> configurationResourceInheritanceChain;
     private final Resource contextResource;
     private final String configName;
+    private final ConfigurationManager configurationManager;
     private final ConfigurationOverrideManager configurationOverrideManager;
+    private final ConfigurationPersistenceStrategy configurationPersistenceStrategy;
     private final boolean configResourceCollection;
+    private final String collectionItemName;
     
     private Set<String> propertyNamesCache;
     private ValueMap valuesCache;
@@ -64,8 +70,10 @@ final class ConfigurationDataImpl implem
     public ConfigurationDataImpl(ConfigurationMetadata configMetadata,
             Resource resolvedConfigurationResource, Resource writebackConfigurationResource,
             Iterator<Resource> configurationResourceInheritanceChain,
-            Resource contextResource, String configName, ConfigurationOverrideManager configurationOverrideManager,
-            boolean configResourceCollection) {
+            Resource contextResource, String configName,
+            ConfigurationManager configurationManager, ConfigurationOverrideManager configurationOverrideManager,
+            ConfigurationPersistenceStrategy configurationPersistenceStrategy,
+            boolean configResourceCollection, String collectionItemName) {
         this.configMetadata = configMetadata;
         this.resolvedConfigurationResource = resolvedConfigurationResource;
         this.writebackConfigurationResource = writebackConfigurationResource;
@@ -73,16 +81,27 @@ final class ConfigurationDataImpl implem
                 ? IteratorUtils.toList(configurationResourceInheritanceChain) : null;
         this.contextResource = contextResource;
         this.configName = configName;
+        this.configurationManager = configurationManager;
         this.configurationOverrideManager = configurationOverrideManager;
+        this.configurationPersistenceStrategy = configurationPersistenceStrategy;
         this.configResourceCollection = configResourceCollection;
+        this.collectionItemName = collectionItemName;
     }
 
     public ConfigurationDataImpl(ConfigurationMetadata configMetadata,
-            Resource contextResource, String configName, ConfigurationOverrideManager configurationOverrideManager,
+            Resource contextResource, String configName,
+            ConfigurationManager configurationManager, ConfigurationOverrideManager configurationOverrideManager,
+            ConfigurationPersistenceStrategy configurationPersistenceStrategy,
             boolean configResourceCollection) {
         this(configMetadata, null, null, null,
-                contextResource, configName, configurationOverrideManager,
-                configResourceCollection);
+                contextResource, configName,
+                configurationManager, configurationOverrideManager,
+                configurationPersistenceStrategy,
+                configResourceCollection, "*");
+    }
+    
+    void setConfigMetadata(ConfigurationMetadata configMetadata) {
+        this.configMetadata = configMetadata;
     }
     
     @Override
@@ -92,8 +111,7 @@ final class ConfigurationDataImpl implem
 
     @Override
     public String getCollectionItemName() {
-        return (configResourceCollection && resolvedConfigurationResource != null)
-                ? resolvedConfigurationResource.getName() : null;
+        return collectionItemName;
     }
 
     @Override
@@ -117,7 +135,7 @@ final class ConfigurationDataImpl implem
             if (resolvedConfigurationResource != null) {
                 propertyNamesCache.addAll(ResourceUtil.getValueMap(resolvedConfigurationResource).keySet());
             }
-            propertyNamesCache.removeAll(PROPERTIES_TO_IGNORE);
+            removeIgnoredProperties(propertyNamesCache);
         }
         return propertyNamesCache;
     }
@@ -130,6 +148,7 @@ final class ConfigurationDataImpl implem
                 props.putAll( ResourceUtil.getValueMap(writebackConfigurationResource));
             }
             removeIgnoredProperties(props);
+            resolveNestedConfigs(props);
             valuesCache = new ValueMapDecorator(props);
         }
         return valuesCache;
@@ -150,21 +169,58 @@ final class ConfigurationDataImpl implem
                 props.putAll(ResourceUtil.getValueMap(resolvedConfigurationResource));
             }
             removeIgnoredProperties(props);
+            resolveNestedConfigs(props);
             effectiveValuesCache = new ValueMapDecorator(props);
         }
         return effectiveValuesCache;
     }
     
+    private void removeIgnoredProperties(Set<String> propertyNames) {
+        propertyNames.removeAll(PROPERTIES_TO_IGNORE);
+    }
+
     private void removeIgnoredProperties(Map<String,Object> props) {
         for (String propertyName : PROPERTIES_TO_IGNORE) {
             props.remove(propertyName);
         }
     }
+    
+    private void resolveNestedConfigs(Map<String,Object> props) {
+        if (configMetadata == null) {
+            return;
+        }
+        for (PropertyMetadata<?> propertyMetadata : configMetadata.getPropertyMetadata().values()) {
+            ConfigurationMetadata nestedConfigMetadata = propertyMetadata.getConfigurationMetadata();
+            if (nestedConfigMetadata != null) {
+                String nestedConfigName;
+                if (configResourceCollection) {
+                    nestedConfigName = configurationPersistenceStrategy.getResourcePath(configName + "/" + getCollectionItemName()) + "/" + nestedConfigMetadata.getName();
+                }
+                else {
+                    nestedConfigName = configurationPersistenceStrategy.getResourcePath(configName) + "/" + nestedConfigMetadata.getName();
+                }
+                if (propertyMetadata.getType().equals(ConfigurationMetadata.class)) {
+                    ConfigurationData configData = configurationManager.get(contextResource, nestedConfigName);
+                    if (configData != null) {
+                        ((ConfigurationDataImpl)configData).setConfigMetadata(nestedConfigMetadata);
+                    }
+                    props.put(propertyMetadata.getName(), configData);
+                }
+                else if (propertyMetadata.getType().equals(ConfigurationMetadata[].class)) {
+                    Collection<ConfigurationData> configDatas = configurationManager.getCollection(contextResource, nestedConfigName);
+                    for (ConfigurationData configData : configDatas) {
+                        ((ConfigurationDataImpl)configData).setConfigMetadata(nestedConfigMetadata);
+                    }
+                    props.put(propertyMetadata.getName(), configDatas.toArray(new ConfigurationData[configDatas.size()]));
+                }
+            }
+        }
+    }
 
     @SuppressWarnings("unchecked")
     @Override
     public ValueInfo<?> getValueInfo(String propertyName) {
-        PropertyMetadata propertyMetadata = configMetadata != null ? configMetadata.getPropertyMetadata().get(propertyName) : null;
+        PropertyMetadata<?> propertyMetadata = getPropertyMetadata(propertyName);
         Object value;
         Object effectiveValue;
         if (propertyMetadata != null) {
@@ -183,5 +239,14 @@ final class ConfigurationDataImpl implem
                 configName,
                 configurationOverrideManager);
     }
+    
+    private PropertyMetadata<?> getPropertyMetadata(String propertyName) {
+        if (configMetadata == null) {
+            return null;
+        }
+        else {
+            return configMetadata.getPropertyMetadata().get(propertyName);
+        }
+    }
 
 }

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java Wed Nov 30 15:34:44 2016
@@ -81,13 +81,13 @@ public class ConfigurationManagerImpl im
                 resettableConfigResourceInheritanceChain.reset();
                 return new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
                         applyPersistence(resettableConfigResourceInheritanceChain),
-                        resource, configName, configurationOverrideManager, false);
+                        resource, configName, this, configurationOverrideManager, configurationPersistenceStrategy, false, null);
             }
         }
         if (configMetadata != null) {
             // if no config resource found but config metadata exist return empty config data with default values
             return new ConfigurationDataImpl(configMetadata,
-                    resource, configName, configurationOverrideManager, false);
+                    resource, configName, this, configurationOverrideManager, configurationPersistenceStrategy, false);
         }
         return null;
     }
@@ -105,12 +105,12 @@ public class ConfigurationManagerImpl im
             for (Iterator<Resource> configResourceInheritanceChain : configResourceInheritanceChains) {
                 ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
                 Resource configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
+                resettableConfigResourceInheritanceChain.reset();
+                Resource untransformedConfigResource = (Resource)resettableConfigResourceInheritanceChain.next();
                 if (configResource != null) {
                     // get writeback resource for "reverse inheritance detection"
                     Resource writebackConfigResource = null;
                     if (writebackConfigResourceCollectionParentPath != null) {
-                        resettableConfigResourceInheritanceChain.reset();
-                        Resource untransformedConfigResource = (Resource)resettableConfigResourceInheritanceChain.next();
                         writebackConfigResource = configResource.getResourceResolver().getResource(
                                 writebackConfigResourceCollectionParentPath + "/" + untransformedConfigResource.getName());
                         if (writebackConfigResource != null) {
@@ -120,7 +120,8 @@ public class ConfigurationManagerImpl im
                     resettableConfigResourceInheritanceChain.reset();
                     configData.add(new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
                             applyPersistence(resettableConfigResourceInheritanceChain),
-                            resource, configName, configurationOverrideManager, true));
+                            resource, configName, this, configurationOverrideManager, configurationPersistenceStrategy,
+                            true, untransformedConfigResource.getName()));
                 }
             }
         }
@@ -183,7 +184,7 @@ public class ConfigurationManagerImpl im
         ConfigurationMetadata configMetadata = configurationMetadataProvider.getConfigurationMetadata(configName);
         if (configMetadata != null) {
             return new ConfigurationDataImpl(configMetadata,
-                    resource, configName, configurationOverrideManager, true);
+                    resource, configName, this, configurationOverrideManager, configurationPersistenceStrategy, true);
         }
         return null;
     }

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexer.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexer.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexer.java Wed Nov 30 15:34:44 2016
@@ -70,6 +70,17 @@ public class ConfigurationPersistenceStr
         return null;
     }
 
+    @Override
+    public String getResourcePath(String resourcePath) {
+        for (ConfigurationPersistenceStrategy item : items) {
+            String result = item.getResourcePath(resourcePath);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
     /**
      * Persist configuration data with the first implementation that accepts it.
      */

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java Wed Nov 30 15:34:44 2016
@@ -140,15 +140,15 @@ public class ConfigurationResolverCustom
     @Test
     public void testConfig_Nested() {
         context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.NestedConfig")
-            .siblingsMode()
             .resource("jcr:content", "stringParam", "configValue3")
-            .resource("subConfig/jcr:content", "stringParam", "configValue4", "intParam", 444, "boolParam", true)
-            .hierarchyMode()
-            .resource("subListConfig")
-            .siblingsMode()
-                .resource("1/jcr:content", "stringParam", "configValue2.1")
-                .resource("2/jcr:content", "stringParam", "configValue2.2")
-                .resource("3/jcr:content", "stringParam", "configValue2.3");
+                .siblingsMode()
+                .resource("subConfig/jcr:content", "stringParam", "configValue4", "intParam", 444, "boolParam", true)
+                .hierarchyMode()
+                .resource("subListConfig")
+                    .siblingsMode()
+                    .resource("1/jcr:content", "stringParam", "configValue2.1")
+                    .resource("2/jcr:content", "stringParam", "configValue2.2")
+                    .resource("3/jcr:content", "stringParam", "configValue2.3");
 
         NestedConfig cfg = underTest.get(site1Page1).as(NestedConfig.class);
 

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategyTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategyTest.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategyTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategyTest.java Wed Nov 30 15:34:44 2016
@@ -51,6 +51,15 @@ public class DefaultConfigurationPersist
     }
 
     @Test
+    public void testGetResourcePath() {
+        ConfigurationPersistenceStrategy underTest = context.registerInjectActivateService(new DefaultConfigurationPersistenceStrategy());
+        
+        String path = "/conf/test";
+        String result = underTest.getResourcePath(path);
+        assertEquals(path, result);
+    }
+
+    @Test
     public void testPersist() throws Exception {
         ConfigurationPersistenceStrategy underTest = context.registerInjectActivateService(new DefaultConfigurationPersistenceStrategy());
         
@@ -106,6 +115,7 @@ public class DefaultConfigurationPersist
         
         Resource resource = context.create().resource("/conf/test");
         assertNull(underTest.getResource(resource));
+        assertNull(underTest.getResourcePath(resource.getPath()));
 
         assertFalse(underTest.persist(context.resourceResolver(), "/conf/test", ImmutableMap.<String,Object>of()));
         assertFalse(underTest.persistCollection(context.resourceResolver(), "/conf/test", ImmutableList.<ResourceCollectionItem>of()));

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=1772057&r1=1772056&r2=1772057&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 Wed Nov 30 15:34:44 2016
@@ -148,18 +148,21 @@ public class AnnotationClassParserTest {
                 assertEquals(ConfigurationMetadata.class, propertyMetadata.getType());
                 
                 ConfigurationMetadata subConfigMetadata = propertyMetadata.getConfigurationMetadata();
+                assertEquals("subConfig", subConfigMetadata.getName());
                 assertEquals(3, subConfigMetadata.getPropertyMetadata().size());
             }
             else if (StringUtils.equals(propertyMetadata.getName(), "subListConfig")) {
                 assertEquals(ConfigurationMetadata[].class, propertyMetadata.getType());
 
                 ConfigurationMetadata subListConfigMetadata = propertyMetadata.getConfigurationMetadata(); 
+                assertEquals("subListConfig", subListConfigMetadata.getName());
                 assertEquals(2, subListConfigMetadata.getPropertyMetadata().size());
             }
             else if (StringUtils.equals(propertyMetadata.getName(), "subConfigWithoutAnnotation")) {
                 assertEquals(ConfigurationMetadata.class, propertyMetadata.getType());
 
                 ConfigurationMetadata subConfigWithoutAnnotationMetadata = propertyMetadata.getConfigurationMetadata(); 
+                assertEquals("subConfigWithoutAnnotation", subConfigWithoutAnnotationMetadata.getName());
                 assertEquals(1, subConfigWithoutAnnotationMetadata.getPropertyMetadata().size());
             }
             else {

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java Wed Nov 30 15:34:44 2016
@@ -24,9 +24,12 @@ import static org.junit.Assert.assertTru
 
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.caconfig.impl.def.DefaultConfigurationPersistenceStrategy;
 import org.apache.sling.caconfig.impl.override.ConfigurationOverrideManager;
 import org.apache.sling.caconfig.management.ConfigurationData;
+import org.apache.sling.caconfig.management.ConfigurationManager;
 import org.apache.sling.caconfig.management.ValueInfo;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
 import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
 import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
 import org.apache.sling.testing.mock.sling.junit.SlingContext;
@@ -49,12 +52,17 @@ public class ConfigurationDataImplTest {
     private Resource contextResource;
     @Mock
     private ConfigurationOverrideManager configurationOverrideManager;
+    @Mock
+    private ConfigurationManager configurationManager;
+    private ConfigurationPersistenceStrategy configurationPersistenceStrategy;
     
     private Resource configResource;
     private ConfigurationMetadata configMetadata;
     
     @Before
     public void setUp() {
+        configurationPersistenceStrategy = context.registerInjectActivateService(new DefaultConfigurationPersistenceStrategy());
+        
         configResource = context.create().resource("/conf/test",
                 "prop1", "value1",
                 "prop4", true);
@@ -68,10 +76,11 @@ public class ConfigurationDataImplTest {
     @Test
     public void testWithResourceMetadata() {
         ConfigurationData underTest = new ConfigurationDataImpl(configMetadata, configResource, configResource, null,
-                contextResource, "test", configurationOverrideManager, true);
+                contextResource, "test", configurationManager, configurationOverrideManager, configurationPersistenceStrategy,
+                true, "item1");
         
         assertEquals("test", underTest.getConfigName());
-        assertEquals(configResource.getName(), underTest.getCollectionItemName());
+        assertEquals("item1", underTest.getCollectionItemName());
         
         assertEquals(configResource.getPath(), underTest.getResourcePath());
         assertEquals(ImmutableSet.of("prop1", "prop2", "prop3", "prop4"), underTest.getPropertyNames());
@@ -107,7 +116,8 @@ public class ConfigurationDataImplTest {
     @Test
     public void testWithResourceOnly() {
         ConfigurationData underTest = new ConfigurationDataImpl(null, configResource, configResource, null,
-                contextResource, "test", configurationOverrideManager, false);
+                contextResource, "test", configurationManager, configurationOverrideManager, configurationPersistenceStrategy,
+                false, null);
         
         assertEquals("test", underTest.getConfigName());
         assertNull(underTest.getCollectionItemName());
@@ -136,10 +146,11 @@ public class ConfigurationDataImplTest {
     @Test
     public void testMetadataOnly() {
         ConfigurationData underTest = new ConfigurationDataImpl(configMetadata,
-                contextResource, "test", configurationOverrideManager, false);
+                contextResource, "test", configurationManager, configurationOverrideManager, configurationPersistenceStrategy,
+                false);
         
         assertEquals("test", underTest.getConfigName());
-        assertNull(underTest.getCollectionItemName());
+        assertEquals("*", underTest.getCollectionItemName());
         
         assertEquals(ImmutableSet.of("prop1", "prop2", "prop3"), underTest.getPropertyNames());
         
@@ -170,7 +181,8 @@ public class ConfigurationDataImplTest {
                 "sling:resourceType", "my/type");
 
         ConfigurationData underTest = new ConfigurationDataImpl(null, resource, resource, null,
-                contextResource, "test", configurationOverrideManager, false);
+                contextResource, "test", configurationManager, configurationOverrideManager, configurationPersistenceStrategy,
+                false, null);
         
         assertEquals(ImmutableSet.of("prop1", "prop4"), underTest.getPropertyNames());
         

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java Wed Nov 30 15:34:44 2016
@@ -38,7 +38,7 @@ public class ConfigurationManagerImplCus
     }
 
     @Override
-    protected String getConfigPropertiesPath(String path) {
+    protected String getConfigPropsPath(String path) {
         return path + "/jcr:content";
     }
 

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java Wed Nov 30 15:34:44 2016
@@ -71,10 +71,10 @@ public class ConfigurationManagerImplTes
     private Resource contextResourceLevel2;
     private Resource contextResourceLevel3;
     private Resource contextResourceNoConfig;
-    private ConfigurationMetadata configMetadata;
     
     private static final String CONFIG_NAME = "testConfig";
     private static final String CONFIG_COL_NAME = "testConfigCol";
+    private static final String CONFIG_NESTED_NAME = "testConfigNested";
    
     @Before
     public void setUp() {
@@ -92,49 +92,91 @@ public class ConfigurationManagerImplTes
         contextResourceNoConfig = context.create().resource("/content/testNoConfig",
                 PROPERTY_CONFIG_REF, "/conf/testNoConfig");
         
-        context.create().resource(getConfigPropertiesPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME),
+        context.create().resource(getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME),
                 "prop1", "value1",
                 "prop4", true);
-        context.create().resource(getConfigPropertiesPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1"),
+        context.create().resource(getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1"),
                 "prop1", "value1");
-        context.create().resource(getConfigPropertiesPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/2"),
+        context.create().resource(getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/2"),
                 "prop4", true);
         
         // test fixture with resource collection inheritance on level 2
         context.create().resource("/conf/test/level2/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME,
                 PROPERTY_CONFIG_COLLECTION_INHERIT, true);
-        context.create().resource(getConfigPropertiesPath("/conf/test/level2/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1"),
+        context.create().resource(getConfigPropsPath("/conf/test/level2/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1"),
                 "prop1", "value1_level2");
         
         // test fixture with property inheritance and resource collection inheritance on level 3
-        context.create().resource(getConfigPropertiesPath("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME),
+        context.create().resource(getConfigPropsPath("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME),
                 "prop4", false,
                 "prop5", "value5_level3",
                 PROPERTY_CONFIG_PROPERTY_INHERIT, true);
         context.create().resource("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME,
                 PROPERTY_CONFIG_COLLECTION_INHERIT, true);
-        context.create().resource(getConfigPropertiesPath("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1"),
+        context.create().resource(getConfigPropsPath("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1"),
                 "prop4", false,
                 "prop5", "value5_level3",
                 PROPERTY_CONFIG_PROPERTY_INHERIT, true);
 
-        configMetadata = new ConfigurationMetadata(CONFIG_NAME);
+        // test fixture nested configuration
+        context.create().resource(getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NESTED_NAME),
+                "prop1", "value1",
+                "prop4", true);
+        context.create().resource(getConfigPropsPath(getConfigPropsPath("/conf/global/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NESTED_NAME) + "/propSub"),
+                "prop1", "propSubValue1",
+                "prop4", true);
+        context.create().resource(getConfigPropsPath(getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NESTED_NAME) + "/propSubList/item1"),
+                "prop1", "propSubListValue1.1");
+        context.create().resource(getConfigPropsPath(getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NESTED_NAME) + "/propSubList/item2"),
+                "prop1", "propSubListValue1.2");
+        context.create().resource(getConfigPropsPath(getConfigPropsPath(getConfigPropsPath("/conf/global/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NESTED_NAME) + "/propSubList/item1") + "/propSub"),
+                "prop1", "propSubList1_proSubValue1",
+                "prop4", true);
+        
+        
+        // config metadata singleton config
+        ConfigurationMetadata configMetadata = new ConfigurationMetadata(CONFIG_NAME);
         configMetadata.setPropertyMetadata(ImmutableMap.<String,PropertyMetadata<?>>of(
                 "prop1", new PropertyMetadata<>("prop1", "defValue"),
                 "prop2", new PropertyMetadata<>("prop2", String.class),
                 "prop3", new PropertyMetadata<>("prop3", 5)));
         when(configurationMetadataProvider.getConfigurationMetadata(CONFIG_NAME)).thenReturn(configMetadata);
 
+        // config metadata config collection
         configMetadata = new ConfigurationMetadata(CONFIG_COL_NAME);
         configMetadata.setPropertyMetadata(ImmutableMap.<String,PropertyMetadata<?>>of(
                 "prop1", new PropertyMetadata<>("prop1", "defValue"),
                 "prop2", new PropertyMetadata<>("prop2", String.class),
                 "prop3", new PropertyMetadata<>("prop3", 5)));
         when(configurationMetadataProvider.getConfigurationMetadata(CONFIG_COL_NAME)).thenReturn(configMetadata);
-        when(configurationMetadataProvider.getConfigurationNames()).thenReturn(ImmutableSortedSet.of(CONFIG_NAME, CONFIG_COL_NAME));
+
+        // config metadata nested config
+        configMetadata = new ConfigurationMetadata(CONFIG_NESTED_NAME);
+        configMetadata.setPropertyMetadata(ImmutableMap.<String,PropertyMetadata<?>>of(
+                "prop1", new PropertyMetadata<>("prop1", "defValue"),
+                "propSub", new PropertyMetadata<>("propSub", ConfigurationMetadata.class),
+                "propSubList", new PropertyMetadata<>("propSubList", ConfigurationMetadata[].class)));
+        ConfigurationMetadata propSubMetadata = new ConfigurationMetadata("propSub");
+        propSubMetadata.setPropertyMetadata(ImmutableMap.<String,PropertyMetadata<?>>of(
+                "prop1", new PropertyMetadata<>("prop1", "defValue"),
+                "prop2", new PropertyMetadata<>("prop2", String.class),
+                "prop3", new PropertyMetadata<>("prop3", 5)));
+        ConfigurationMetadata propSubListMetadata = new ConfigurationMetadata("propSubList");
+        propSubListMetadata.setPropertyMetadata(ImmutableMap.<String,PropertyMetadata<?>>of(
+                "prop1", new PropertyMetadata<>("prop1", String.class),
+                "propSub", new PropertyMetadata<>("propSub", ConfigurationMetadata.class)));
+        configMetadata.getPropertyMetadata().get("propSub").setConfigurationMetadata(propSubMetadata);
+        configMetadata.getPropertyMetadata().get("propSubList").setConfigurationMetadata(propSubListMetadata);
+        propSubListMetadata.getPropertyMetadata().get("propSub").setConfigurationMetadata(propSubMetadata);
+
+        when(configurationMetadataProvider.getConfigurationNames()).thenReturn(ImmutableSortedSet.of(CONFIG_NAME, CONFIG_COL_NAME, CONFIG_NESTED_NAME));
+        
+        
+        when(configurationMetadataProvider.getConfigurationMetadata(CONFIG_NESTED_NAME)).thenReturn(configMetadata);
+
     }
     
-    protected String getConfigPropertiesPath(String path) {
+    protected String getConfigPropsPath(String path) {
         return path;
     }
     
@@ -161,7 +203,7 @@ public class ConfigurationManagerImplTes
         assertEquals("value1", configData.getEffectiveValues().get("prop1", String.class));
         assertEquals((Integer)5, configData.getEffectiveValues().get("prop3", 0));
 
-        String configPath = getConfigPropertiesPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME);
+        String configPath = getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME);
         assertEquals(configPath, configData.getValueInfo("prop1").getConfigSourcePath());
         assertTrue(configData.getValueInfo("prop1").isInherited());
         assertFalse(configData.getValueInfo("prop3").isInherited());
@@ -186,8 +228,8 @@ public class ConfigurationManagerImplTes
         assertFalse(configData.getEffectiveValues().get("prop4", Boolean.class));
         assertEquals("value5_level3", configData.getEffectiveValues().get("prop5", String.class));
 
-        String configPath = getConfigPropertiesPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME);
-        String configPathLevel3 = getConfigPropertiesPath("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME);
+        String configPath = getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME);
+        String configPathLevel3 = getConfigPropsPath("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME);
         assertTrue(configData.getValueInfo("prop1").isInherited());
         assertEquals(configPath, configData.getValueInfo("prop1").getConfigSourcePath());
         assertFalse(configData.getValueInfo("prop2").isInherited());
@@ -261,6 +303,7 @@ public class ConfigurationManagerImplTes
         assertEquals(2, configDatas.size());
 
         ConfigurationData configData1 = configDatas.get(0);
+        assertEquals("1", configData1.getCollectionItemName());
         assertEquals(ImmutableSet.of("prop1", "prop2", "prop3"), configData1.getPropertyNames());
         assertEquals("value1", configData1.getValues().get("prop1", String.class));
         assertEquals((Integer)5, configData1.getEffectiveValues().get("prop3", 0));
@@ -269,6 +312,7 @@ public class ConfigurationManagerImplTes
         assertFalse(configData1.getValueInfo("prop3").isInherited());
         
         ConfigurationData configData2 = configDatas.get(1);
+        assertEquals("2", configData2.getCollectionItemName());
         assertEquals(ImmutableSet.of("prop1", "prop2", "prop3", "prop4"), configData2.getPropertyNames());
         assertNull(configData2.getValues().get("prop1", String.class));
         assertEquals((Integer)5, configData2.getEffectiveValues().get("prop3", 0));
@@ -288,7 +332,7 @@ public class ConfigurationManagerImplTes
         assertEquals("value1_level2", configData1.getEffectiveValues().get("prop1", String.class));
         assertEquals((Integer)5, configData1.getEffectiveValues().get("prop3", 0));
 
-        String configPath1 = getConfigPropertiesPath("/conf/test/level2/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1");
+        String configPath1 = getConfigPropsPath("/conf/test/level2/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1");
         assertFalse(configData1.getValueInfo("prop1").isInherited());
         assertEquals(configPath1, configData1.getValueInfo("prop1").getConfigSourcePath());
         assertFalse(configData1.getValueInfo("prop3").isInherited());
@@ -299,7 +343,7 @@ public class ConfigurationManagerImplTes
         assertNull(configData2.getValues().get("prop1", String.class));
         assertEquals((Integer)5, configData2.getEffectiveValues().get("prop3", 0));
 
-        String configPath2 = getConfigPropertiesPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/2");
+        String configPath2 = getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/2");
         assertTrue(configData2.getValueInfo("prop4").isInherited());
         assertEquals(configPath2, configData2.getValueInfo("prop4").getConfigSourcePath());
         assertFalse(configData2.getValueInfo("prop3").isInherited());
@@ -327,8 +371,8 @@ public class ConfigurationManagerImplTes
         assertFalse(configData1.getEffectiveValues().get("prop4", Boolean.class));
         assertEquals("value5_level3", configData1.getEffectiveValues().get("prop5", String.class));
 
-        String configPathLevel2 = getConfigPropertiesPath("/conf/test/level2/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1");
-        String configPathLevel3 = getConfigPropertiesPath("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1");
+        String configPathLevel2 = getConfigPropsPath("/conf/test/level2/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1");
+        String configPathLevel3 = getConfigPropsPath("/conf/test/level2/level3/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1");
         assertTrue(configData1.getValueInfo("prop1").isInherited());
         assertEquals(configPathLevel2, configData1.getValueInfo("prop1").getConfigSourcePath());
         assertFalse(configData1.getValueInfo("prop2").isInherited());
@@ -345,7 +389,7 @@ public class ConfigurationManagerImplTes
         assertNull(configData2.getValues().get("prop1", String.class));
         assertEquals((Integer)5, configData2.getEffectiveValues().get("prop3", 0));
 
-        String configPath2 = getConfigPropertiesPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/2");
+        String configPath2 = getConfigPropsPath("/conf/test/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/2");
         assertTrue(configData2.getValueInfo("prop4").isInherited());
         assertEquals(configPath2, configData2.getValueInfo("prop4").getConfigSourcePath());
         assertFalse(configData2.getValueInfo("prop3").isInherited());
@@ -427,7 +471,7 @@ public class ConfigurationManagerImplTes
                 ImmutableMap.<String, Object>of("prop1", "value1"));
         context.resourceResolver().commit();
 
-        String configPath = getConfigPropertiesPath("/conf/testNoConfig/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME);
+        String configPath = getConfigPropsPath("/conf/testNoConfig/" + CONFIGS_PARENT_NAME + "/" + CONFIG_NAME);
         ValueMap props = context.resourceResolver().getResource(configPath).getValueMap();
         assertEquals("value1", props.get("prop1"));
     }
@@ -440,11 +484,11 @@ public class ConfigurationManagerImplTes
         ));
         context.resourceResolver().commit();
 
-        String configPath0 = getConfigPropertiesPath("/conf/testNoConfig/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/0");
+        String configPath0 = getConfigPropsPath("/conf/testNoConfig/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/0");
         ValueMap props0 = context.resourceResolver().getResource(configPath0).getValueMap();
         assertEquals("value1", props0.get("prop1"));
 
-        String configPath1 = getConfigPropertiesPath("/conf/testNoConfig/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1");
+        String configPath1 = getConfigPropsPath("/conf/testNoConfig/" + CONFIGS_PARENT_NAME + "/" + CONFIG_COL_NAME + "/1");
         ValueMap props1 = context.resourceResolver().getResource(configPath1).getValueMap();
         assertEquals((Integer)5, props1.get("prop2"));
     }
@@ -466,12 +510,58 @@ public class ConfigurationManagerImplTes
 
     @Test
     public void testGetConfigurationNames() {
-        assertEquals(ImmutableSortedSet.of(CONFIG_NAME, CONFIG_COL_NAME), underTest.getConfigurationNames());
+        assertEquals(ImmutableSortedSet.of(CONFIG_NAME, CONFIG_COL_NAME, CONFIG_NESTED_NAME), underTest.getConfigurationNames());
     }
 
     @Test
-    public void testGetConfigurationMetadata() throws Exception {
+    public void testGetConfigurationMetadata() {
         assertEquals(CONFIG_NAME, underTest.getConfigurationMetadata(CONFIG_NAME).getName());
     }
 
+    @Test
+    public void testGetNested() {
+        ConfigurationData configData = underTest.get(contextResource, CONFIG_NESTED_NAME);
+        assertNotNull(configData);
+
+        assertEquals(ImmutableSet.of("prop1", "propSub", "propSubList", "prop4"), configData.getPropertyNames());
+        assertEquals("value1", configData.getValues().get("prop1", String.class));
+        assertEquals("value1", configData.getEffectiveValues().get("prop1", String.class));
+        assertEquals(true, configData.getValues().get("prop4", false));
+        assertEquals(true, configData.getEffectiveValues().get("prop4", false));
+        
+        assertEquals(ConfigurationMetadata.class, configData.getValueInfo("propSub").getPropertyMetadata().getType());
+        assertEquals(ConfigurationMetadata[].class, configData.getValueInfo("propSubList").getPropertyMetadata().getType());
+        
+        ConfigurationData subData = configData.getValues().get("propSub", ConfigurationData.class);
+        ConfigurationData subDataEffective = configData.getEffectiveValues().get("propSub", ConfigurationData.class);
+        assertNotNull(subData);
+        assertNotNull(subDataEffective);
+        
+        assertNull(subData.getValues().get("prop1", String.class));
+        assertEquals("propSubValue1", subData.getEffectiveValues().get("prop1", String.class));
+        assertNull(subData.getValues().get("prop4", String.class));
+        assertEquals(true, subData.getEffectiveValues().get("prop4", false));
+        
+        ConfigurationData[] subListData = configData.getValues().get("propSubList", ConfigurationData[].class);
+        ConfigurationData[] subListDataEffective = configData.getEffectiveValues().get("propSubList", ConfigurationData[].class);
+        assertNotNull(subListData);
+        assertNotNull(subListDataEffective);
+        
+        assertEquals(2, subListData.length);
+        assertEquals("propSubListValue1.1", subListData[0].getValues().get("prop1", String.class));
+        assertEquals("propSubListValue1.1", subListData[0].getEffectiveValues().get("prop1", String.class));
+        assertEquals("propSubListValue1.2", subListData[1].getValues().get("prop1", String.class));
+        assertEquals("propSubListValue1.2", subListData[1].getEffectiveValues().get("prop1", String.class));
+        
+        ConfigurationData subListDataItem1Sub = subListData[0].getValues().get("propSub", ConfigurationData.class);
+        ConfigurationData subListDataItem1SubEffecive = subListData[0].getEffectiveValues().get("propSub", ConfigurationData.class);
+        assertNotNull(subListDataItem1Sub);
+        assertNotNull(subListDataItem1SubEffecive);
+
+        assertNull(subListDataItem1Sub.getValues().get("prop1", String.class));
+        assertEquals("propSubList1_proSubValue1", subListDataItem1Sub.getEffectiveValues().get("prop1", String.class));
+        assertNull(subListDataItem1Sub.getValues().get("prop4", String.class));
+        assertEquals(true, subListDataItem1Sub.getEffectiveValues().get("prop4", false));
+    }
+
 }

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerTest.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerTest.java Wed Nov 30 15:34:44 2016
@@ -18,6 +18,7 @@
  */
 package org.apache.sling.caconfig.management.impl;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
@@ -59,6 +60,7 @@ public class ConfigurationPersistenceStr
     @Test
     public void testWithNoStrategies() {
         assertNull(underTest.getResource(resource1));
+        assertNull(underTest.getResourcePath(resource1.getPath()));
         assertFalse(underTest.persist(context.resourceResolver(), "/conf/test1", resource1.getValueMap()));
         assertFalse(underTest.persistCollection(context.resourceResolver(), "/conf/testCol", ImmutableList.of(
                         new ResourceCollectionItem(resource1.getName(), resource1.getValueMap()),
@@ -69,8 +71,8 @@ public class ConfigurationPersistenceStr
     public void testWithDefaultStrategy() {
         context.registerInjectActivateService(new DefaultConfigurationPersistenceStrategy());
 
-        Resource result = underTest.getResource(resource1);
-        assertSame(resource1, result);
+        assertSame(resource1, underTest.getResource(resource1));
+        assertEquals(resource1.getPath(), underTest.getResourcePath(resource1.getPath()));
         assertTrue(underTest.persist(context.resourceResolver(), "/conf/test1", resource1.getValueMap()));
         assertTrue(underTest.persistCollection(context.resourceResolver(), "/conf/testCol", ImmutableList.of(
                         new ResourceCollectionItem(resource1.getName(), resource1.getValueMap()),
@@ -87,6 +89,10 @@ public class ConfigurationPersistenceStr
                 return resource2;
             }
             @Override
+            public String getResourcePath(String resourcePath) {
+                return resource2.getPath();
+            }
+            @Override
             public boolean persist(ResourceResolver resourceResolver, String configResourcePath, Map<String,Object> properties) {
                 return true;
             }
@@ -104,6 +110,10 @@ public class ConfigurationPersistenceStr
                 return resource1;
             }
             @Override
+            public String getResourcePath(String resourcePath) {
+                return resource1.getPath();
+            }
+            @Override
             public boolean persist(ResourceResolver resourceResolver, String configResourcePath, Map<String,Object> properties) {
                 return false;
             }
@@ -115,8 +125,8 @@ public class ConfigurationPersistenceStr
 
         }, Constants.SERVICE_RANKING, 1000);
         
-        Resource result = underTest.getResource(resource1);
-        assertSame(resource2, result);
+        assertSame(resource2, underTest.getResource(resource1));
+        assertEquals(resource2.getPath(), underTest.getResourcePath(resource1.getPath()));
         assertTrue(underTest.persist(context.resourceResolver(), "/conf/test1", resource1.getValueMap()));
         assertTrue(underTest.persistCollection(context.resourceResolver(), "/conf/testCol", ImmutableList.of(
                         new ResourceCollectionItem(resource1.getName(), resource1.getValueMap()),

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy.java Wed Nov 30 15:34:44 2016
@@ -42,14 +42,21 @@ public class CustomConfigurationPersiste
     
     private static final String DEFAULT_RESOURCE_TYPE = JcrConstants.NT_UNSTRUCTURED;
     
+    private static final String CHILD_NODE_NAME = "jcr:content";
+    
     @Override
     public Resource getResource(Resource resource) {
-        return resource.getChild("jcr:content");
+        return resource.getChild(CHILD_NODE_NAME);
+    }
+
+    @Override
+    public String getResourcePath(String resourcePath) {
+        return resourcePath + "/" + CHILD_NODE_NAME;
     }
 
     @Override
     public boolean persist(ResourceResolver resourceResolver, String configResourcePath, Map<String,Object> properties) {
-        getOrCreateResource(resourceResolver, configResourcePath + "/jcr:content", properties);
+        getOrCreateResource(resourceResolver, configResourcePath + "/" + CHILD_NODE_NAME, properties);
         return true;
     }
 
@@ -59,7 +66,7 @@ public class CustomConfigurationPersiste
         Resource configResourceParent = getOrCreateResource(resourceResolver, configResourceCollectionParentPath, ValueMap.EMPTY);
         deleteChildren(configResourceParent);
         for (ResourceCollectionItem item : resourceCollectionItems) {
-            String path = configResourceParent.getPath() + "/" + item.getCollectionItemName() + "/jcr:content";
+            String path = configResourceParent.getPath() + "/" + item.getCollectionItemName() + "/" + CHILD_NODE_NAME;
             getOrCreateResource(resourceResolver, path, item.getValues());
         }
         return true;

Modified: sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationPersistenceStrategy.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationPersistenceStrategy.java?rev=1772057&r1=1772056&r2=1772057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationPersistenceStrategy.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationPersistenceStrategy.java Wed Nov 30 15:34:44 2016
@@ -44,6 +44,14 @@ public interface ConfigurationPersistenc
     @CheckForNull Resource getResource(@Nonnull Resource resource);
     
     /**
+     * Allows the strategy to transform the given configuration resource path according to it's persistent strategies,
+     * e.g. fetching the data from a child resource instead of the given resource. 
+     * @param resource Configuration resource path
+     * @return Transformed configuration resource path. If null is returned this strategy does not support the given configuration resource path.
+     */
+    @CheckForNull String getResourcePath(@Nonnull String resourcePath);
+    
+    /**
      * Stores configuration data for a singleton configuration resource.
      * The changes are written using the given resource resolver. They are not committed, this is left to the caller.
      * @param resourceResolver Resource resolver