You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by si...@apache.org on 2012/02/25 20:00:38 UTC
svn commit: r1293663 - in /commons/sandbox/beanutils2/trunk/src: changes/
main/java/org/apache/commons/beanutils2/
test/java/org/apache/commons/beanutils2/
Author: simonetripodi
Date: Sat Feb 25 19:00:37 2012
New Revision: 1293663
URL: http://svn.apache.org/viewvc?rev=1293663&view=rev
Log:
[SANDBOX-396] Implement clone() on DefaultBeanAccessor - patch provided by Benedikt Ritter
Added:
commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/CloneTestCase.java (with props)
Modified:
commons/sandbox/beanutils2/trunk/src/changes/changes.xml
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java
commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java
Modified: commons/sandbox/beanutils2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/changes/changes.xml?rev=1293663&r1=1293662&r2=1293663&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/changes/changes.xml (original)
+++ commons/sandbox/beanutils2/trunk/src/changes/changes.xml Sat Feb 25 19:00:37 2012
@@ -23,9 +23,15 @@
</properties>
<body>
<release version="0.1" date="201?-??-??" description="First release.">
+ <action dev="simonetripodi" type="add" issue="SANDBOX-396" due-to="Benedikt Ritter">
+ Implement clone() on DefaultBeanAccessor
+ </action>
<action dev="simonetripodi" type="update" issue="SANDBOX-390" due-to="Benedikt Ritter">
Make sure that the internal package does not get exported when packaging as OSGi bundle
</action>
+ <action dev="simonetripodi" type="update" issue="SANDBOX-389" due-to="Benedikt Ritter">
+ implement populate() on DefaultBeanAccessor
+ </action>
<action dev="simonetripodi" type="update" issue="SANDBOX-387" due-to="Benedikt Ritter">
Implement possibility to find out if a property readable and/or wirtable
</action>
Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java?rev=1293663&r1=1293662&r2=1293663&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/BeanAccessor.java Sat Feb 25 19:00:37 2012
@@ -76,8 +76,26 @@ public interface BeanAccessor<B>
// clone
+ /**
+ * <p>
+ * Clones a bean based on the available property getters and setters, even if the bean class itself does not
+ * implement Cloneable.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> this method creates a <strong>shallow</strong> clone. In other words, any objects referred
+ * to by the bean are shared with the clone rather than being cloned in turn.
+ * </p>
+ *
+ * @return the cloned bean
+ * @throws IllegalAccessException if the caller does not have access to the property accessor method
+ * @throws InstantiationException if a new instance of the bean's class cannot be instantiated
+ * @throws InvocationTargetException if the property accessor method throws an exception
+ * @throws NoSuchMethodException if an accessor method for this property cannot be found
+ * @throws IntrospectionException
+ */
B cloneBean()
- throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException;
+ throws IllegalAccessException, InstantiationException, IntrospectionException,
+ InvocationTargetException, NoSuchMethodException;
<T extends B> void copyPropertiesTo( T target )
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException;
Modified: commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java?rev=1293663&r1=1293662&r2=1293663&view=diff
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java (original)
+++ commons/sandbox/beanutils2/trunk/src/main/java/org/apache/commons/beanutils2/DefaultBeanAccessor.java Sat Feb 25 19:00:37 2012
@@ -20,6 +20,7 @@ package org.apache.commons.beanutils2;
*/
import static java.lang.String.format;
+import static org.apache.commons.beanutils2.BeanUtils.on;
import static org.apache.commons.beanutils2.internal.Assertions.checkArgument;
import static org.apache.commons.beanutils2.internal.Assertions.checkNotNull;
@@ -208,10 +209,19 @@ final class DefaultBeanAccessor<B>
* {@inheritDoc}
*/
public B cloneBean()
- throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
+ throws IllegalAccessException, InstantiationException, IntrospectionException, InvocationTargetException,
+ NoSuchMethodException
{
- // TODO
- return null;
+ BeanAccessor<B> cloneAccessor = on( getBeanClass() ).newInstance();
+ cloneAccessor.populate( describe() );
+ return cloneAccessor.get();
+ }
+
+ private Class<B> getBeanClass()
+ {
+ @SuppressWarnings( "unchecked" ) // we can be sure, that bean is of Class<B>
+ Class<B> beanType = (Class<B>) bean.getClass();
+ return beanType;
}
/**
@@ -272,9 +282,8 @@ final class DefaultBeanAccessor<B>
public ArgumentsAccessor invoke( String methodName )
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
- @SuppressWarnings( "unchecked" )
- Class<B> beanClass = (Class<B>) bean.getClass();
- checkNotNull(methodName, "Impossible to execute null method in %s", beanClass.getName());
+ Class<B> beanClass = getBeanClass();
+ checkNotNull( methodName, "Impossible to execute null method in %s", beanClass.getName() );
return new DefaultArgumentsAccessor( beanClass, false, methodName, bean );
}
@@ -284,9 +293,8 @@ final class DefaultBeanAccessor<B>
public ArgumentsAccessor invokeExact( String methodName )
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
- @SuppressWarnings( "unchecked" )
- Class<B> beanClass = (Class<B>) bean.getClass();
- checkNotNull(methodName, "Impossible to execute null method in %s", beanClass.getName());
+ Class<B> beanClass = getBeanClass();
+ checkNotNull( methodName, "Impossible to execute null method in %s", beanClass.getName() );
return new DefaultArgumentsAccessor( beanClass, true, methodName, bean );
}
Added: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/CloneTestCase.java
URL: http://svn.apache.org/viewvc/commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/CloneTestCase.java?rev=1293663&view=auto
==============================================================================
--- commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/CloneTestCase.java (added)
+++ commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/CloneTestCase.java Sat Feb 25 19:00:37 2012
@@ -0,0 +1,178 @@
+package org.apache.commons.beanutils2;
+
+/*
+ * 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.
+ */
+
+import static org.apache.commons.beanutils2.BeanUtils.on;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CloneTestCase
+{
+
+ private TestBean original;
+
+ private TestBean clone;
+
+ @Before
+ public void setUp()
+ {
+ original = new TestBean();
+ }
+
+ @After
+ public void tearDown()
+ {
+ original = null;
+ clone = null;
+ }
+
+ @Test
+ public void cloneTestBean()
+ throws Exception
+ {
+ clone = on( new TestBean() ).cloneBean();
+ assertNotNull( "Clone is null!", clone );
+ assertReadWritePropertiesEquals( new TestBean(), clone );
+ }
+
+ @Test
+ public void cloneWithChangedScalarProperties()
+ throws Exception
+ {
+ changeScalarProperties();
+
+ clone = on( original ).cloneBean();
+ assertNotNull( "Clone is null!", clone );
+
+ assertReadWritePropertiesEquals( original, clone );
+ }
+
+ private void changeScalarProperties()
+ {
+ original.setBooleanProperty( false );
+ // booleanSecond is left at true
+ original.setByteProperty( (byte) 111 );
+ original.setDoubleProperty( 432.0 );
+ // floatProperty is left at 123.0
+ original.setIntProperty( 543 );
+ original.setLongProperty( 123456789l );
+ original.setNullProperty( "Non-null value" );
+ original.setShortProperty( (short) 654 );
+ // stringProperty is left at "This is a string"
+ }
+
+ @Test
+ public void cloneWithChangedArrayProperties()
+ throws Exception
+ {
+ changeArrayProperties();
+
+ clone = on( original ).cloneBean();
+ assertNotNull( clone );
+
+ assertReadWritePropertiesEquals( original, clone );
+ }
+
+ private void changeArrayProperties()
+ {
+ int intArray[] = new int[] { 123, 456, 789 };
+ String stringArray[] = new String[] { "New String 0", "New String 1" };
+ original.setIntArray( intArray );
+ original.setStringArray( stringArray );
+ }
+
+ @Test
+ public void cloneWithChangedWriteOnlyProperty()
+ throws Exception
+ {
+ original.setWriteOnlyProperty( "New writeOnlyProperty value" );
+
+ clone = on( original ).cloneBean();
+ assertNotNull( "Clone is null!", clone );
+ assertReadWritePropertiesEquals( original, clone );
+
+ // The value of writeOnlyProperty can not be read out from original, so it must have the
+ // original value
+ assertEquals( "writeOnlyProperty has been changed on clone!", new TestBean().getWriteOnlyPropertyValue(),
+ clone.getWriteOnlyPropertyValue() );
+ }
+
+ /**
+ * Makes sure, that the general contract of creating a shallow clone is not violated.
+ */
+ @Test
+ public void cloneIsShallow()
+ throws Exception
+ {
+ clone = on( original ).cloneBean();
+
+ assertTrue(clone.getAnotherNested() == original.getAnotherNested());
+ assertTrue(clone.getDateArrayProperty() == original.getDateArrayProperty());
+ assertTrue(clone.getDateProperty() == original.getDateProperty());
+ assertTrue(clone.getDateProperty() == original.getDateProperty());
+ assertTrue(clone.getDupProperty() == original.getDupProperty());
+ assertTrue(clone.getIntArray() == original.getIntArray());
+ assertTrue(clone.getMapProperty() == original.getMapProperty());
+ assertTrue(clone.getStringArray() == original.getStringArray());
+ assertTrue(clone.getStringProperty() == original.getStringProperty());
+ }
+
+ /**
+ * Asserts that all properties that are readable and writable on {@code actual} are equal to those on
+ * {@code expected}.
+ *
+ * @param expected the {@code TestBean} with the expected properties.
+ * @param actual the {@code TestBean} with the actual values.
+ */
+ private static void assertReadWritePropertiesEquals( TestBean expected, TestBean actual )
+ {
+ assertEquals( "Property 'anotherNested' is not equal!", expected.getAnotherNested(), actual.getAnotherNested() );
+ assertEquals( "Property 'booleanProperty' is not equal!", expected.getBooleanProperty(),
+ actual.getBooleanProperty() );
+ assertEquals( "Property 'booleanSecond' is not equal!", expected.isBooleanSecond(), actual.isBooleanSecond() );
+ assertEquals( "Property 'byteProperty' is not equal!", expected.getByteProperty(), actual.getByteProperty() );
+ assertArrayEquals( "Property 'DateArrayProperty' is not equal!", expected.getDateArrayProperty(),
+ actual.getDateArrayProperty() );
+ assertEquals( "Property 'dateProperty' is not equal!", expected.getDateProperty(), actual.getDateProperty() );
+ assertEquals( "Property 'doubleProperty' is not equal!", expected.getDoubleProperty(),
+ actual.getDoubleProperty(), 0.0 );
+ assertArrayEquals( "Property 'dupProperty' is not equal!", expected.getDupProperty(), actual.getDupProperty() );
+ assertEquals( "Property 'floatProperty' is not equal!", expected.getFloatProperty(), actual.getFloatProperty(),
+ 0.0 );
+ assertArrayEquals( "Property 'intArrayProperty' is not equal!", expected.getIntArray(), actual.getIntArray() );
+ assertEquals( "Property 'intProperty' is not equal!", expected.getIntProperty(), actual.getIntProperty() );
+ assertEquals( "Property 'invalidBoolean' is not equal!", expected.getInvalidBoolean(),
+ actual.getInvalidBoolean() );
+ assertEquals( "Property 'listIndexed' is not equal!", expected.getListIndexed(), actual.getListIndexed() );
+ assertEquals( "Property 'longProperty' is not equal!", expected.getLongProperty(), actual.getLongProperty() );
+ assertEquals( "Property 'mapProperty' is not equal!", expected.getMapProperty(), actual.getMapProperty() );
+ assertEquals( "Property 'nested' is not equal!", expected.getNested(), actual.getNested() );
+ assertEquals( "Property 'nullProperty' is not equal!", expected.getNullProperty(), actual.getNullProperty() );
+ assertEquals( "Property 'shortProperty' is not equal!", expected.getShortProperty(), actual.getShortProperty() );
+ assertArrayEquals( "Property 'stringArray' is not equal!", expected.getStringArray(), actual.getStringArray() );
+ assertEquals( "Property 'stringProperty' is not equal!", expected.getStringProperty(),
+ actual.getStringProperty() );
+ }
+
+}
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/CloneTestCase.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/CloneTestCase.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: commons/sandbox/beanutils2/trunk/src/test/java/org/apache/commons/beanutils2/CloneTestCase.java
------------------------------------------------------------------------------
svn:mime-type = text/plain