Author: henning
Date: Mon Oct 21 22:02:27 2013
New Revision: 1534393

URL: http://svn.apache.org/r1534393
Log:
Backport COLLECTIONS-546 from r1492404.


Added:
    
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBean.java
   (with props)
    
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBeanWithListChild.java
   (with props)
Modified:
    
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/RELEASE-NOTES.txt
    
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/changes/changes.xml
    
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/main/java/org/apache/commons/configuration/beanutils/BeanHelper.java
    
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/TestBeanHelper.java

Modified: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/RELEASE-NOTES.txt
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/RELEASE-NOTES.txt?rev=1534393&r1=1534392&r2=1534393&view=diff
==============================================================================
--- 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/RELEASE-NOTES.txt
 (original)
+++ 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/RELEASE-NOTES.txt
 Mon Oct 21 22:02:27 2013
@@ -36,9 +36,11 @@ BUG FIXES IN 1.10
   XMLConfiguration now adds attributes of elements defining a list to
   all list nodes.
 
-* [CONFIGURATION-550] Missing conversion to char
+* [CONFIGURATION-546] ClassCastException in BeanHelper constructing beans with 
a list 
+                     of child beans.
 
-  Conversion to Character is now supported.
+  BeanHelper can now process BeanDefinitions initializing properties of
+  collection types of their target beans.
 
 * [CONFIGURATION-555] XMLConfiguration doesn't seem to be preserving 
whitespace 
                       for the current node where xml:space="preserve" is set.
@@ -72,5 +74,10 @@ BUG FIXES IN 1.10
 IMPROVEMENTS AND NEW FEATURES IN 1.10
 =====================================
 
+* [CONFIGURATION-550] Missing conversion to char
+
+  Conversion to Character is now supported.
+
+
 OTHER CHANGES
 =============

Modified: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/changes/changes.xml?rev=1534393&r1=1534392&r2=1534393&view=diff
==============================================================================
--- 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/changes/changes.xml
 (original)
+++ 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/changes/changes.xml
 Mon Oct 21 22:02:27 2013
@@ -31,6 +31,10 @@
         XMLConfiguration now adds attributes of elements defining a list to
         all list nodes.
       </action>
+      <action dev="oheger" type="update" issue="CONFIGURATION-546" 
due-to="Justin Couch">
+        BeanHelper can now process BeanDefinitions initializing properties of
+        collection types of their target beans.
+      </action>
       <action dev="oheger" type="add" issue="CONFIGURATION-550">
         Conversion to Character is now supported.
       </action>

Modified: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/main/java/org/apache/commons/configuration/beanutils/BeanHelper.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/main/java/org/apache/commons/configuration/beanutils/BeanHelper.java?rev=1534393&r1=1534392&r2=1534393&view=diff
==============================================================================
--- 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/main/java/org/apache/commons/configuration/beanutils/BeanHelper.java
 (original)
+++ 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/main/java/org/apache/commons/configuration/beanutils/BeanHelper.java
 Mon Oct 21 22:02:27 2013
@@ -18,12 +18,14 @@ package org.apache.commons.configuration
 
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.beanutils.PropertyUtils;
@@ -203,8 +205,27 @@ public final class BeanHelper
                 {
                     String propName = e.getKey();
                     Class<?> defaultClass = getDefaultClass(bean, propName);
-                    initProperty(bean, propName, createBean(
-                        (BeanDeclaration) e.getValue(), defaultClass));
+
+                    Object prop = e.getValue();
+
+                    if (prop instanceof Collection)
+                    {
+                        Collection<Object> beanCollection =
+                                createPropertyCollection(propName, 
defaultClass);
+
+                        for (Object elemDef : (Collection<?>) prop)
+                        {
+                            beanCollection
+                                    .add(createBean((BeanDeclaration) 
elemDef));
+                        }
+
+                        initProperty(bean, propName, beanCollection);
+                    }
+                    else
+                    {
+                        initProperty(bean, propName, createBean(
+                            (BeanDeclaration) e.getValue(), defaultClass));
+                    }
                 }
             }
         }
@@ -287,6 +308,39 @@ public final class BeanHelper
     }
 
     /**
+     * Creates a concrete collection instance to populate a property of type
+     * collection. This method tries to guess an appropriate collection type.
+     * Mostly the type of the property will be one of the collection interfaces
+     * rather than a concrete class; so we have to create a concrete 
equivalent.
+     *
+     * @param propName the name of the collection property
+     * @param propertyClass the type of the property
+     * @return the newly created collection
+     */
+    private static Collection<Object> createPropertyCollection(String propName,
+            Class<?> propertyClass)
+    {
+        Collection<Object> beanCollection = null;
+
+        if (List.class.isAssignableFrom(propertyClass))
+        {
+            beanCollection = new ArrayList<Object>();
+        }
+        else if (Set.class.isAssignableFrom(propertyClass))
+        {
+            beanCollection = new TreeSet<Object>();
+        }
+        else
+        {
+            throw new UnsupportedOperationException(
+                    "Unable to handle collection of type : "
+                            + propertyClass.getName() + " for property "
+                            + propName);
+        }
+        return beanCollection;
+    }
+
+    /**
      * Set a property on the bean only if the property exists
      *
      * @param bean the bean

Added: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBean.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBean.java?rev=1534393&view=auto
==============================================================================
--- 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBean.java
 (added)
+++ 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBean.java
 Mon Oct 21 22:02:27 2013
@@ -0,0 +1,61 @@
+/*
+ * 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.commons.configuration.beanutils;
+
+/**
+ * A simple bean class used for testing bean creation operations.
+ *
+ * @version $Id$
+ */
+public class BeanCreationTestBean
+{
+    private String stringValue;
+
+    private int intValue;
+
+    private BeanCreationTestBean buddy;
+
+    public BeanCreationTestBean getBuddy()
+    {
+        return buddy;
+    }
+
+    public void setBuddy(BeanCreationTestBean buddy)
+    {
+        this.buddy = buddy;
+    }
+
+    public int getIntValue()
+    {
+        return intValue;
+    }
+
+    public void setIntValue(int intValue)
+    {
+        this.intValue = intValue;
+    }
+
+    public String getStringValue()
+    {
+        return stringValue;
+    }
+
+    public void setStringValue(String stringValue)
+    {
+        this.stringValue = stringValue;
+    }
+}

Propchange: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBean.java
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Revision

Added: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBeanWithListChild.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBeanWithListChild.java?rev=1534393&view=auto
==============================================================================
--- 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBeanWithListChild.java
 (added)
+++ 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBeanWithListChild.java
 Mon Oct 21 22:02:27 2013
@@ -0,0 +1,66 @@
+/*
+ * 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.commons.configuration.beanutils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A simple bean class used for testing bean creation operations that has 
+ * a list of children of a different bean type.
+ *
+ * @version $Id$
+ */
+public class BeanCreationTestBeanWithListChild
+{
+    private String stringValue;
+
+    private int intValue;
+
+    private List<BeanCreationTestBean> children = new 
ArrayList<BeanCreationTestBean>();
+
+    public List<BeanCreationTestBean> getChildren()
+    {
+        return children;
+    }
+
+    public void setChildren(List<BeanCreationTestBean> buddies)
+    {
+        this.children.clear();
+        this.children.addAll(buddies);
+    }
+
+    public int getIntValue()
+    {
+        return intValue;
+    }
+
+    public void setIntValue(int intValue)
+    {
+        this.intValue = intValue;
+    }
+
+    public String getStringValue()
+    {
+        return stringValue;
+    }
+
+    public void setStringValue(String stringValue)
+    {
+        this.stringValue = stringValue;
+    }
+}

Propchange: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBeanWithListChild.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/BeanCreationTestBeanWithListChild.java
------------------------------------------------------------------------------
    svn:keywords = Id Author Date Revision

Modified: 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/TestBeanHelper.java
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/TestBeanHelper.java?rev=1534393&r1=1534392&r2=1534393&view=diff
==============================================================================
--- 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/TestBeanHelper.java
 (original)
+++ 
commons/proper/configuration/branches/CONFIGURATION_1_X_MAINTENANCE/src/test/java/org/apache/commons/configuration/beanutils/TestBeanHelper.java
 Mon Oct 21 22:02:27 2013
@@ -22,7 +22,9 @@ import static org.junit.Assert.assertNul
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.configuration.ConfigurationRuntimeException;
@@ -41,6 +43,12 @@ import org.junit.Test;
  */
 public class TestBeanHelper
 {
+    /** Constant for the test value of the string property. */
+    private static final String TEST_STRING = "testString";
+
+    /** Constant for the test value of the numeric property. */
+    private static final int TEST_INT = 42;
+
     /** Constant for the name of the test bean factory. */
     private static final String TEST_FACTORY = "testFactory";
 
@@ -207,6 +215,18 @@ public class TestBeanHelper
         assertNull("A parameter was passed", factory.parameter);
     }
 
+    @Test
+    public void testCreateBeanWithListChildBean()
+    {
+        TestBeanFactory factory = new TestBeanFactory();
+        BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
+        TestBeanDeclaration data = setUpBeanDeclarationWithListChild();
+        data.setBeanFactoryName(TEST_FACTORY);
+        
data.setBeanClassName(BeanCreationTestBeanWithListChild.class.getName());
+        checkBean((BeanCreationTestBeanWithListChild) 
BeanHelper.createBean(data, null));
+        assertNull("A parameter was passed", factory.parameter);
+    }
+
     /**
      * Tests creating a bean when no bean declaration is provided. This should
      * cause an exception.
@@ -347,6 +367,7 @@ public class TestBeanHelper
         {
             buddyData.setBeanFactoryName(TEST_FACTORY);
         }
+
         Map<String, Object> nested = new HashMap<String, Object>();
         nested.put("buddy", buddyData);
         data.setNestedBeanDeclarations(nested);
@@ -354,6 +375,53 @@ public class TestBeanHelper
     }
 
     /**
+     * Same as setUpBeanDeclaration, but returns a nested array of beans
+     * as a single property. Tests multi-value (Collection<BeanDeclaration>)
+     * children construction.
+     *
+     * @return The bean declaration with a list child bean proerty
+     */
+    private TestBeanDeclaration setUpBeanDeclarationWithListChild()
+    {
+        TestBeanDeclaration data = new TestBeanDeclaration();
+        Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put("stringValue", TEST_STRING);
+        properties.put("intValue", String.valueOf(TEST_INT));
+        data.setBeanProperties(properties);
+
+        List<BeanDeclaration> childData = new ArrayList<BeanDeclaration>();
+        childData.add(createChildBean("child1"));
+        childData.add(createChildBean("child2"));
+        Map<String, Object> nested = new HashMap<String, Object>();
+        nested.put("children", childData);
+        data.setNestedBeanDeclarations(nested);
+        return data;
+    }
+
+    /**
+     * Create a simple bean declaration that has no children for testing
+     * of nested children bean declarations.
+     *
+     * @param name A name prefix that can be used to disambiguate the children
+     * @return A simple declaration
+     */
+    private TestBeanDeclaration createChildBean(String name)
+    {
+        TestBeanDeclaration childBean = new TestBeanDeclaration();
+        Map<String, Object> properties2 = new HashMap<String, Object>();
+        properties2.put("stringValue", name + " Another test string");
+        properties2.put("intValue", new Integer(100));
+        childBean.setBeanProperties(properties2);
+        childBean.setBeanClassName(BeanCreationTestBean.class.getName());
+        if (BeanHelper.getDefaultBeanFactory() == null)
+        {
+            childBean.setBeanFactoryName(TEST_FACTORY);
+        }
+
+        return childBean;
+    }
+
+    /**
      * Tests if the bean was correctly initialized from the data of the test
      * bean declaration.
      *
@@ -414,6 +482,24 @@ public class TestBeanHelper
     }
 
     /**
+     * Tests if the bean was correctly initialized from the data of the test
+     * bean declaration.
+     *
+     * @param bean the bean to be checked
+     */
+    private void checkBean(BeanCreationTestBeanWithListChild bean)
+    {
+        assertEquals("Wrong string property", TEST_STRING, bean
+                .getStringValue());
+        assertEquals("Wrong int property", TEST_INT, bean.getIntValue());
+        List<BeanCreationTestBean> children = bean.getChildren();
+        assertNotNull("Children were not set", children);
+        assertEquals("Wrong number of children created", children.size(), 2);
+        assertNotNull("First child was set as null", children.get(0));
+        assertNotNull("Second child was set as null", children.get(1));
+    }
+
+    /**
      * An implementation of the BeanFactory interface used for testing. This
      * implementation is really simple: If the TestBean class is provided, a 
new
      * instance will be created. Otherwise an exception is thrown.
@@ -434,6 +520,12 @@ public class TestBeanHelper
                 BeanHelper.initBean(bean, data);
                 return bean;
             }
+            else if (BeanCreationTestBeanWithListChild.class.equals(beanClass))
+            {
+                BeanCreationTestBeanWithListChild bean = new 
BeanCreationTestBeanWithListChild();
+                BeanHelper.initBean(bean, data);
+                return bean;
+            }
             else
             {
                 throw new IllegalArgumentException("Unsupported class: "


Reply via email to