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 2021/12/17 08:12:01 UTC

[sling-org-apache-sling-caconfig-impl] 01/01: SLING-11019 Nested sub configurations in nested configuration collections: Config name not correctly applied from persistence strategy (backport to 1.5.x)

This is an automated email from the ASF dual-hosted git repository.

sseifert pushed a commit to branch release/15x
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-caconfig-impl.git

commit 8125e696e4606c6fce59e3e5293a522a951ec801
Author: Stefan Seifert <st...@users.noreply.github.com>
AuthorDate: Thu Dec 16 17:53:40 2021 +0100

    SLING-11019 Nested sub configurations in nested configuration collections: Config name not correctly applied from persistence strategy (backport to 1.5.x)
---
 .../management/impl/ConfigurationDataImpl.java     |   6 +-
 ...onfigurationResolverCustomPersistence3Test.java | 281 +++++++++++++++++++++
 ...igurationManagerImplCustomPersistence3Test.java | 116 +++++++++
 .../CustomConfigurationPersistenceStrategy2.java   |   2 +-
 ...> CustomConfigurationPersistenceStrategy3.java} |  68 ++---
 5 files changed, 423 insertions(+), 50 deletions(-)

diff --git a/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java b/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
index 6d43dcf..e5892cf 100644
--- a/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
+++ b/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
@@ -187,9 +187,9 @@ final class ConfigurationDataImpl implements ConfigurationData {
                 String relatedConfigPath = resolvedConfigurationResource != null ? resolvedConfigurationResource.getPath() : null;
                 String nestedConfigName;
                 if (configResourceCollection) {
-                    String collectionItemName = StringUtils.defaultString(getCollectionItemName(), "newItem");
-                    nestedConfigName = configurationPersistenceStrategy.getCollectionParentConfigName(configName, relatedConfigPath)
-                            + "/" + configurationPersistenceStrategy.getCollectionItemConfigName(collectionItemName, relatedConfigPath)
+                    String nestedCollectionItemName = StringUtils.defaultString(getCollectionItemName(), "newItem");
+                    nestedConfigName = configurationPersistenceStrategy.getCollectionItemConfigName(
+                            configurationPersistenceStrategy.getCollectionParentConfigName(configName, relatedConfigPath) + "/" + nestedCollectionItemName, relatedConfigPath)
                             + "/" + nestedConfigMetadata.getName();
                 }
                 else {
diff --git a/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence3Test.java b/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence3Test.java
new file mode 100644
index 0000000..030e184
--- /dev/null
+++ b/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence3Test.java
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.caconfig.impl;
+
+import static org.apache.sling.caconfig.resource.impl.def.ConfigurationResourceNameConstants.PROPERTY_CONFIG_REF;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.geom.Rectangle2D;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.caconfig.ConfigurationResolveException;
+import org.apache.sling.caconfig.ConfigurationResolver;
+import org.apache.sling.caconfig.example.ListConfig;
+import org.apache.sling.caconfig.example.ListDoubleNestedConfig;
+import org.apache.sling.caconfig.example.ListNestedConfig;
+import org.apache.sling.caconfig.example.NestedConfig;
+import org.apache.sling.caconfig.example.SimpleConfig;
+import org.apache.sling.caconfig.management.impl.CustomConfigurationPersistenceStrategy3;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.osgi.framework.Constants;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Test {@link ConfigurationResolver} with annotation classes for reading the config.
+ */
+@SuppressWarnings("null")
+public class ConfigurationResolverCustomPersistence3Test {
+
+    @Rule
+    public SlingContext context = new SlingContext();
+
+    private ConfigurationResolver underTest;
+
+    private Resource site1Page1;
+
+    @Before
+    public void setUp() {
+        // custom config with defines alternative bucket name "settings"
+        underTest = ConfigurationTestUtils.registerConfigurationResolver(context,
+                "configBucketNames", "settings");
+
+        // custom strategy which redirects all config resources to a jcr:content subnode
+        context.registerService(ConfigurationPersistenceStrategy2.class,
+                new CustomConfigurationPersistenceStrategy3(), Constants.SERVICE_RANKING, 2000);
+
+        // content resources
+        context.build().resource("/content/site1", PROPERTY_CONFIG_REF, "/conf/content/site1");
+        site1Page1 = context.create().resource("/content/site1/page1");
+    }
+
+    @Test
+    public void testNonExistingConfig_Simple() {
+        SimpleConfig cfg = underTest.get(site1Page1).as(SimpleConfig.class);
+
+        assertNull(cfg.stringParam());
+        assertEquals(5, cfg.intParam());
+        assertEquals(false, cfg.boolParam());
+    }
+
+    @Test
+    public void testNonExistingConfig_List() {
+        Collection<ListConfig> cfgList = underTest.get(site1Page1).asCollection(ListConfig.class);
+        assertTrue(cfgList.isEmpty());
+    }
+
+    @Test
+    public void testNonExistingConfig_Nested() {
+        NestedConfig cfg = underTest.get(site1Page1).as(NestedConfig.class);
+
+        assertNull(cfg.stringParam());
+        assertNotNull(cfg.subConfig());
+        assertNotNull(cfg.subListConfig());
+    }
+
+
+    @Test
+    public void testConfig_Simple() {
+        context.build().resource("/conf/content/site1/settings/org.apache.sling.caconfig.example.SimpleConfig/jcr:content",
+                "stringParam", "configValue1",
+                "intParam", 111,
+                "boolParam", true);
+
+        SimpleConfig cfg = underTest.get(site1Page1).as(SimpleConfig.class);
+
+        assertEquals("configValue1", cfg.stringParam());
+        assertEquals(111, cfg.intParam());
+        assertEquals(true, cfg.boolParam());
+    }
+
+    @Test
+    public void testConfig_SimpleWithName() {
+        context.build().resource("/conf/content/site1/settings/sampleName/jcr:content",
+                "stringParam", "configValue1.1",
+                "intParam", 1111,
+                "boolParam", true);
+
+        SimpleConfig cfg = underTest.get(site1Page1).name("sampleName").as(SimpleConfig.class);
+
+        assertEquals("configValue1.1", cfg.stringParam());
+        assertEquals(1111, cfg.intParam());
+        assertEquals(true, cfg.boolParam());
+    }
+
+    @Test
+    public void testConfig_List() {
+        context.build().resource("/conf/content/site1/settings/org.apache.sling.caconfig.example.ListConfig")
+            .siblingsMode()
+            .resource("1/jcr:content", "stringParam", "value1")
+            .resource("2/jcr:content", "stringParam", "value2")
+            .resource("3/jcr:content", "stringParam", "value3");
+
+        Collection<ListConfig> cfgList = underTest.get(site1Page1).asCollection(ListConfig.class);
+
+        assertEquals(3, cfgList.size());
+        Iterator<ListConfig> cfgIterator = cfgList.iterator();
+        assertEquals("value1", cfgIterator.next().stringParam());
+        assertEquals("value2", cfgIterator.next().stringParam());
+        assertEquals("value3", cfgIterator.next().stringParam());
+    }
+
+    @Test
+    public void testConfig_List_Nested() {
+        context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.ListNestedConfig")
+            .siblingsMode()
+            .resource("1/jcr:content", "stringParam", "value1")
+            .resource("2/jcr:content", "stringParam", "value2")
+            .resource("3/jcr:content", "stringParam", "value3");
+        context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.ListNestedConfig/1/jcr:content/subListConfig")
+            .siblingsMode()
+            .resource("1", "stringParam", "value11")
+            .resource("2", "stringParam", "value12");
+        context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.ListNestedConfig/2/jcr:content/subListConfig")
+            .siblingsMode()
+            .resource("1", "stringParam", "value21");
+
+        List<ListNestedConfig> cfgList = ImmutableList.copyOf(underTest.get(site1Page1).asCollection(ListNestedConfig.class));
+
+        assertEquals(3, cfgList.size());
+
+        ListNestedConfig config1 = cfgList.get(0);
+        assertEquals("value1", config1.stringParam());
+        assertEquals(2, config1.subListConfig().length);
+        assertEquals("value11", config1.subListConfig()[0].stringParam());
+        assertEquals("value12", config1.subListConfig()[1].stringParam());
+
+        ListNestedConfig config2 = cfgList.get(1);
+        assertEquals("value2", config2.stringParam());
+        assertEquals(1, config2.subListConfig().length);
+        assertEquals("value21", config2.subListConfig()[0].stringParam());
+
+        ListNestedConfig config3 = cfgList.get(2);
+        assertEquals("value3", config3.stringParam());
+        assertEquals(0, config3.subListConfig().length);
+    }
+
+    @Test
+    public void testConfig_List_DoubleNested() {
+        context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.ListDoubleNestedConfig")
+            .siblingsMode()
+            .resource("1/jcr:content", "stringParam", "value1")
+            .resource("2/jcr:content", "stringParam", "value2")
+            .resource("3/jcr:content", "stringParam", "value3");
+        context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.ListDoubleNestedConfig/1/jcr:content/subListNestedConfig")
+            .siblingsMode()
+            .resource("1", "stringParam", "value11")
+            .resource("2", "stringParam", "value12");
+        context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.ListDoubleNestedConfig/1/jcr:content/subListNestedConfig/1/subListConfig")
+            .siblingsMode()
+            .resource("1", "stringParam", "value111")
+            .resource("2", "stringParam", "value112");
+        context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.ListDoubleNestedConfig/1/jcr:content/subListNestedConfig/2/subListConfig")
+            .siblingsMode()
+            .resource("1", "stringParam", "value121");
+        context.build().resource("/conf/content/site1/sling:configs/org.apache.sling.caconfig.example.ListDoubleNestedConfig/2/jcr:content/subListNestedConfig")
+            .siblingsMode()
+            .resource("1", "stringParam", "value21");
+
+        List<ListDoubleNestedConfig> cfgList = ImmutableList.copyOf(underTest.get(site1Page1).asCollection(ListDoubleNestedConfig.class));
+
+        assertEquals(3, cfgList.size());
+
+        ListDoubleNestedConfig config1 = cfgList.get(0);
+        assertEquals("value1", config1.stringParam());
+        assertEquals(2, config1.subListNestedConfig().length);
+        assertEquals("value11", config1.subListNestedConfig()[0].stringParam());
+        assertEquals(2, config1.subListNestedConfig()[0].subListConfig().length);
+        assertEquals("value111", config1.subListNestedConfig()[0].subListConfig()[0].stringParam());
+        assertEquals("value112", config1.subListNestedConfig()[0].subListConfig()[1].stringParam());
+        assertEquals("value12", config1.subListNestedConfig()[1].stringParam());
+        assertEquals(1, config1.subListNestedConfig()[1].subListConfig().length);
+        assertEquals("value121", config1.subListNestedConfig()[1].subListConfig()[0].stringParam());
+
+        ListDoubleNestedConfig config2 = cfgList.get(1);
+        assertEquals("value2", config2.stringParam());
+        assertEquals(1, config2.subListNestedConfig().length);
+        assertEquals("value21", config2.subListNestedConfig()[0].stringParam());
+        assertEquals(0, config2.subListNestedConfig()[0].subListConfig().length);
+
+        ListDoubleNestedConfig config3 = cfgList.get(2);
+        assertEquals("value3", config3.stringParam());
+        assertEquals(0, config3.subListNestedConfig().length);
+    }
+
+    @Test
+    public void testConfig_Nested() {
+        context.build().resource("/conf/content/site1/settings/org.apache.sling.caconfig.example.NestedConfig")
+            .resource("jcr:content", "stringParam", "configValue3")
+                .siblingsMode()
+                .resource("subConfig", "stringParam", "configValue4", "intParam", 444, "boolParam", true)
+                .hierarchyMode()
+                .resource("subListConfig")
+                    .siblingsMode()
+                    .resource("1", "stringParam", "configValue2.1")
+                    .resource("2", "stringParam", "configValue2.2")
+                    .resource("3", "stringParam", "configValue2.3");
+
+        NestedConfig cfg = underTest.get(site1Page1).as(NestedConfig.class);
+
+        assertEquals("configValue3", cfg.stringParam());
+
+        SimpleConfig subConfig = cfg.subConfig();
+        assertEquals("configValue4", subConfig.stringParam());
+        assertEquals(444, subConfig.intParam());
+        assertEquals(true, subConfig.boolParam());
+
+        ListConfig[] listConfig = cfg.subListConfig();
+        assertEquals(3, listConfig.length);
+        assertEquals("configValue2.1", listConfig[0].stringParam());
+        assertEquals("configValue2.2", listConfig[1].stringParam());
+        assertEquals("configValue2.3", listConfig[2].stringParam());
+    }
+
+    @Test(expected=ConfigurationResolveException.class)
+    public void testInvalidClassConversion() {
+        // test with class not supported for configuration mapping
+        underTest.get(site1Page1).as(Rectangle2D.class);
+    }
+
+    @Test
+    public void testNonExistingContentResource_Simple() {
+        SimpleConfig cfg = underTest.get(null).as(SimpleConfig.class);
+
+        assertNull(cfg.stringParam());
+        assertEquals(5, cfg.intParam());
+        assertEquals(false, cfg.boolParam());
+    }
+
+    @Test
+    public void testNonExistingContentResource_List() {
+        Collection<ListConfig> cfgList = underTest.get(null).asCollection(ListConfig.class);
+        assertTrue(cfgList.isEmpty());
+    }
+
+}
diff --git a/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistence3Test.java b/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistence3Test.java
new file mode 100644
index 0000000..a8b7d4f
--- /dev/null
+++ b/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistence3Test.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.caconfig.management.impl;
+
+import static org.apache.sling.caconfig.management.impl.CustomConfigurationPersistenceStrategy2.containsJcrContent;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Test {@link ConfigurationManagerImpl} with custom persistence.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ConfigurationManagerImplCustomPersistence3Test extends ConfigurationManagerImplTest {
+
+    @Override
+    protected void provideCustomOsgiConfig() throws Exception {
+        // provide custom lookup resource name for collection properties
+        ConfigurationAdmin configAdmin = context.getService(ConfigurationAdmin.class);
+        org.osgi.service.cm.Configuration mgmtSettingsConfig = configAdmin.getConfiguration(ConfigurationManagementSettingsImpl.class.getName());
+        Dictionary<String, Object> mgmtSettings = new Hashtable<>();
+        mgmtSettings.put("configCollectionPropertiesResourceNames", new String[] { "colPropsResource", "." });
+        mgmtSettingsConfig.update(mgmtSettings);
+    }
+
+    @Before
+    public void setUpCustomPersistence() {
+        // custom strategy which redirects all config resources to a jcr:content subnode
+        context.registerService(ConfigurationPersistenceStrategy2.class,
+                new CustomConfigurationPersistenceStrategy3(), Constants.SERVICE_RANKING, 2000);
+    }
+
+    @Override
+    protected String getConfigResolvePath(String path) {
+        if (containsJcrContent(path)) {
+            return replaceBucketName(path);
+        }
+        else {
+            return replaceBucketName(path) + "/jcr:content";
+        }
+    }
+
+    @Override
+    protected String getConfigPersistPath(String path) {
+        if (containsJcrContent(path)) {
+            return path;
+        }
+        else {
+            return path + "/jcr:content";
+        }
+    }
+
+    @Override
+    protected String getConfigCollectionParentResolvePath(String path) {
+        return path;
+    }
+
+    @Override
+    protected String getConfigCollectionParentPersistPath(String path) {
+        return path;
+    }
+
+    @Override
+    protected String getConfigCollectionItemResolvePath(String path) {
+        if (containsJcrContent(path)) {
+            return path;
+        }
+        else {
+            return path + "/jcr:content";
+        }
+    }
+
+    @Override
+    protected String getConfigCollectionItemPersistPath(String path) {
+        if (containsJcrContent(path)) {
+            return path;
+        }
+        else {
+            return path + "/jcr:content";
+        }
+    }
+
+    private String replaceBucketName(String path) {
+        return StringUtils.replace(path, "/sling:configs/", "/settings/");
+    }
+
+    @Override
+    protected String[] getAlternativeBucketNames() {
+        return new String[] { "settings" };
+    }
+
+}
diff --git a/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy2.java b/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy2.java
index 06af08c..b7a8cd5 100644
--- a/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy2.java
+++ b/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy2.java
@@ -154,7 +154,7 @@ public class CustomConfigurationPersistenceStrategy2 implements ConfigurationPer
         // delete existing children and create new ones
         deleteChildren(configResourceParent);
         for (ConfigurationPersistData item : data.getItems()) {
-            String path = configResourceParent.getPath() + "/" + item.getCollectionItemName();
+            String path = getCollectionItemResourcePath(configResourceParent.getPath() + "/" + item.getCollectionItemName());
             getOrCreateResource(resourceResolver, path, item.getProperties());
         }
         
diff --git a/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy2.java b/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy3.java
similarity index 86%
copy from src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy2.java
copy to src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy3.java
index 06af08c..b853dd7 100644
--- a/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy2.java
+++ b/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy3.java
@@ -42,43 +42,35 @@ import org.jetbrains.annotations.Nullable;
 /**
  * This is a variant of {@link org.apache.sling.caconfig.impl.def.DefaultConfigurationPersistenceStrategy}
  * which reads and stores data from a sub-resources named "jcr:content".
- * 
+ *
  * Difference to {@link CustomConfigurationPersistenceStrategy}:
- * - For configuration collections jcr:content is added only for the parent, not for each item
+ * - For configuration collections jcr:content is added for each item, not for the parent
  * - For nested configuration jcr:content is not duplicated in the path
  */
-public class CustomConfigurationPersistenceStrategy2 implements ConfigurationPersistenceStrategy2 {
-    
-    private static final String DEFAULT_RESOURCE_TYPE = JcrConstants.NT_UNSTRUCTURED;    
+public class CustomConfigurationPersistenceStrategy3 implements ConfigurationPersistenceStrategy2 {
+
+    private static final String DEFAULT_RESOURCE_TYPE = JcrConstants.NT_UNSTRUCTURED;
     private static final String CHILD_NODE_NAME = JcrConstants.JCR_CONTENT;
     private static final Pattern JCR_CONTENT_PATTERN = Pattern.compile("(.*/)?" + Pattern.quote(CHILD_NODE_NAME) + "(/.*)?");
-    
+
     @Override
     public Resource getResource(@NotNull Resource resource) {
         assertNotNull(resource);
         if (containsJcrContent(resource.getPath())) {
             return resource;
         }
-        else {
-            return resource.getChild(CHILD_NODE_NAME);
-        }
+        return resource.getChild(CHILD_NODE_NAME);
     }
 
     @Override
     public Resource getCollectionParentResource(@NotNull Resource resource) {
         assertNotNull(resource);
-        if (containsJcrContent(resource.getPath())) {
-            return resource;
-        }
-        else {
-            return resource.getChild(CHILD_NODE_NAME);
-        }
+        return resource;
     }
 
     @Override
     public Resource getCollectionItemResource(@NotNull Resource resource) {
-        assertNotNull(resource);
-        return resource;
+        return getResource(resource);
     }
 
     @Override
@@ -87,26 +79,18 @@ public class CustomConfigurationPersistenceStrategy2 implements ConfigurationPer
         if (containsJcrContent(resourcePath)) {
             return resourcePath;
         }
-        else {
-            return resourcePath + "/" + CHILD_NODE_NAME;
-        }
+        return resourcePath + "/" + CHILD_NODE_NAME;
     }
 
     @Override
     public String getCollectionParentResourcePath(@NotNull String resourcePath) {
         assertNotNull(resourcePath);
-        if (containsJcrContent(resourcePath)) {
-            return resourcePath;
-        }
-        else {
-            return resourcePath + "/" + CHILD_NODE_NAME;
-        }
+        return resourcePath;
     }
 
     @Override
     public String getCollectionItemResourcePath(@NotNull String resourcePath) {
-        assertNotNull(resourcePath);
-        return resourcePath;
+        return getResourcePath(resourcePath);
     }
 
     @Override
@@ -115,28 +99,20 @@ public class CustomConfigurationPersistenceStrategy2 implements ConfigurationPer
         if (containsJcrContent(configName)) {
             return configName;
         }
-        else {
-            return configName + "/" + CHILD_NODE_NAME;
-        }
+        return configName + "/" + CHILD_NODE_NAME;
     }
 
     @Override
     public String getCollectionParentConfigName(@NotNull String configName, @Nullable String relatedConfigPath) {
         assertNotNull(configName);
-        if (containsJcrContent(configName)) {
-            return configName;
-        }
-        else {
-            return configName + "/" + CHILD_NODE_NAME;
-        }
+        return configName;
     }
 
     @Override
     public String getCollectionItemConfigName(@NotNull String configName, @Nullable String relatedConfigPath) {
-        assertNotNull(configName);
-        return configName;
+        return getConfigName(configName, relatedConfigPath);
     }
-    
+
     @Override
     public boolean persistConfiguration(@NotNull ResourceResolver resourceResolver, @NotNull String configResourcePath,
             @NotNull ConfigurationPersistData data) {
@@ -150,24 +126,24 @@ public class CustomConfigurationPersistenceStrategy2 implements ConfigurationPer
             @NotNull ConfigurationCollectionPersistData data) {
         String parentPath = getCollectionParentResourcePath(configResourceCollectionParentPath);
         Resource configResourceParent = getOrCreateResource(resourceResolver, parentPath, ValueMap.EMPTY);
-        
+
         // delete existing children and create new ones
         deleteChildren(configResourceParent);
         for (ConfigurationPersistData item : data.getItems()) {
-            String path = configResourceParent.getPath() + "/" + item.getCollectionItemName();
+            String path = getCollectionItemResourcePath(configResourceParent.getPath() + "/" + item.getCollectionItemName());
             getOrCreateResource(resourceResolver, path, item.getProperties());
         }
-        
+
         // if resource collection parent properties are given replace them as well
         if (data.getProperties() != null) {
             Resource propsResource = getOrCreateResource(resourceResolver, parentPath + "/colPropsResource", ValueMap.EMPTY);
             replaceProperties(propsResource, data.getProperties());
         }
-        
+
         commit(resourceResolver);
         return true;
     }
-    
+
     @Override
     public boolean deleteConfiguration(@NotNull ResourceResolver resourceResolver, @NotNull String configResourcePath) {
         Resource resource = resourceResolver.getResource(configResourcePath);
@@ -205,7 +181,7 @@ public class CustomConfigurationPersistenceStrategy2 implements ConfigurationPer
             throw new ConfigurationPersistenceException("Unable to remove children from " + resource.getPath(), ex);
         }
     }
-    
+
     @SuppressWarnings("null")
     private void replaceProperties(Resource resource, Map<String,Object> properties) {
         ModifiableValueMap modValueMap = resource.adaptTo(ModifiableValueMap.class);