SLING-6050 ResourceBuilder: Support Map for resource properties

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/resourcebuilder@1760380 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java b/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java
index 3d33b26..7cae0dd 100644
--- a/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java
+++ b/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java
@@ -19,6 +19,7 @@
 package org.apache.sling.resourcebuilder.api;
 
 import java.io.InputStream;
+import java.util.Map;
 
 import org.apache.sling.api.resource.Resource;
 
@@ -39,7 +40,17 @@
      * @param properties optional name-value pairs 
      * @return this builder
      */
-    ResourceBuilder resource(String path, Object ... properties);
+    ResourceBuilder resource(String path, Object... properties);
+
+    /** Create a Resource, which optionally becomes the current 
+     *  parent Resource. 
+     * @param path The path of the Resource to create.
+     *    If it's a relative path this builder's current resource is used as parent.
+     *    Otherwise the resource is created ad the given absoulte path.
+     * @param properties Name-value pairs 
+     * @return this builder
+     */
+    ResourceBuilder resource(String path, Map<String, Object> properties);
 
     /** Create a file under the current parent resource
      * @param filename The name of the created file
diff --git a/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java b/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java
index 9b8781a..fcc4cae 100644
--- a/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java
+++ b/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java
@@ -27,6 +27,7 @@
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.commons.mime.MimeTypeService;
 import org.apache.sling.resourcebuilder.api.ResourceBuilder;
 
@@ -106,7 +107,7 @@
     }
     
     @Override
-    public ResourceBuilder resource(String path, Object... properties) {
+    public ResourceBuilder resource(String path, Map<String,Object> properties) {
         Resource r = null;
         
         final String parentPath;
@@ -124,17 +125,16 @@
         
         try {
             r = currentParent.getResourceResolver().getResource(fullPath);
-            final Map<String, Object> props = MapArgsConverter.toMap(properties);
-            if(r == null) {
+            if (r == null) {
                 r = currentParent.getResourceResolver().create(myParent, 
-                        ResourceUtil.getName(fullPath), props);
+                        ResourceUtil.getName(fullPath), properties);
             } else {
                 // Resource exists, set our properties
                 final ModifiableValueMap mvm = r.adaptTo(ModifiableValueMap.class);
                 if(mvm == null) {
                     throw new IllegalStateException("Cannot modify properties of " + r.getPath());
                 }
-                for(Map.Entry <String, Object> e : props.entrySet()) {
+                for(Map.Entry <String, Object> e : properties.entrySet()) {
                     mvm.put(e.getKey(), e.getValue());
                 }
             }
@@ -151,6 +151,20 @@
         return this;
     }
     
+    @SuppressWarnings("unchecked")
+    @Override
+    public ResourceBuilder resource(String path, Object... properties) {
+        if (properties == null || properties.length == 0) {
+            return resource(path, ValueMap.EMPTY);
+        }
+        else if (properties.length == 1 && properties[0] instanceof Map) {
+            return resource(path, (Map<String,Object>)properties[0]);
+        }
+        else {
+            return resource(path, MapArgsConverter.toMap(properties));
+        }
+    }
+    
     /** Create a Resource at the specified path if none exists yet,
      *  using the current intermediate primary type. "Stolen" from
      *  the sling-mock module's ContentBuilder class.
diff --git a/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java b/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java
index e33b900..e025c16 100644
--- a/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java
+++ b/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java
@@ -24,6 +24,8 @@
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.when;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Random;
 import java.util.UUID;
 
@@ -113,6 +115,18 @@
     }
     
     @Test
+    public void basicResourceWithMap() throws Exception {
+        Map<String,Object> props = new HashMap<String,Object>();
+        props.put("title", "foo");
+        getBuilder(testRootPath)
+            .resource("child", props)
+            .commit();
+        
+        A.assertProperties("child", "title", "foo");
+        assertEquals(A.fullPath("child"), A.assertResource("child").getPath());
+    }
+    
+    @Test
     public void ensureResourceExists() throws Exception {
         
         class MyResourceBuilder extends ResourceBuilderImpl {