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: "