You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Rodrigo di Lorenzo Lopes <rd...@gmail.com> on 2008/02/01 16:22:10 UTC

Hi alll and a suggestion

Hi all!

I'm Rodrigo di Lorenzo Lopes and I'd like to do some contributions to 
commons apache project (despite my poor English Knowledge).

So, I have one problem with BeanUtils.copyProperties:  From a source, I 
have a bean partialy populated. From another source, I have the same 
bean with others informations. How can I merge these beans?
My solutions is:  verify an mustOverwrite method before each 
copyProperty call.  See the patch in attachment.

;)

Best Regards,

Rodrigo

------------------------------------------------------------------------

Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java
===================================================================
--- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java	(revision 617468)
+++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java	(working copy)
@@ -20,6 +20,7 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Locale;
@@ -1637,4 +1638,28 @@
         }
         return false;
     }
+    
+    public void testMergeProperty() throws Exception {
+    	TestBean testBean = new TestBean();
+    	testBean.setStringProperty("string");
+    	HashMap hashmapTest = new HashMap();
+    	testBean.setMapProperty(null);
+    	Date date = new Date();    	
+    	testBean.setDateProperty(date);
+    	TestBean testBean2 = new TestBean();
+    	testBean2.setStringProperty("string2");
+    	testBean2.setMapProperty(hashmapTest);
+    	testBean2.setDateProperty(null);
+    	BeanUtilsBean.getInstance().mergeProperties(testBean, testBean2, new Overwritable() {
+
+			public boolean mustOverwrite(String propertyName, Object originValue) {
+				if (originValue != null) return true; 
+				return false;
+			}
+    		
+    	});
+    	assertEquals(testBean.getStringProperty(), "string2");
+    	assertEquals(testBean.getMapProperty(), hashmapTest);
+    	assertEquals(testBean.getDateProperty(), date);
+	}
 }
Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java
===================================================================
--- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java	(revision 0)
+++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * 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.beanutils;
+/**
+ * <p>Interface to know when a property must be overwrite.</p>
+ * <p>See mergeProperties {@link BeanUtils}.</p>
+ * @author Rodrigo di Lorenzo Lopes
+ * @version 1.0
+ * @since 3.3
+ *
+ */
+public interface Overwritable {
+ 
+	/**
+	 * Determine if property must be overwrite.
+	 * @param propertyName Property name
+	 * @param value Value from origin bean 
+	 * @return true, if method must be overwrite.
+	 */
+	public boolean mustOverwrite(String propertyName, Object originValue);
+
+}
Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java
===================================================================
--- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java	(revision 617468)
+++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java	(working copy)
@@ -190,8 +190,9 @@
 
 
     /**
-     * <p>Copy property values from the origin bean to the destination bean
-     * for all cases where the property names are the same.  For each
+     * <p>Merge property values from the origin bean to the destination bean
+     * for all cases where the property names are the same, and always where
+     * method mustOverwrite of overwritable return true.  For each
      * property, a conversion is attempted as necessary.  All combinations of
      * standard JavaBeans and DynaBeans as origin and destination are
      * supported.  Properties that exist in the origin bean, but do not exist
@@ -205,22 +206,17 @@
      * is intended to perform a "shallow copy" of the properties and so complex
      * properties (for example, nested ones) will not be copied.</p>
      *
-     * <p>This method differs from <code>populate()</code>, which
-     * was primarily designed for populating JavaBeans from the map of request
-     * parameters retrieved on an HTTP request, is that no scalar->indexed
-     * or indexed->scalar manipulations are performed.  If the origin property
-     * is indexed, the destination property must be also.</p>
+     * <p>This method differs from <code>copyProperties()</code>, which
+     * always overwrite destination bean with origin bean values. </p>
      *
-     * <p>If you know that no type conversions are required, the
-     * <code>copyProperties()</code> method in {@link PropertyUtils} will
-     * execute faster than this method.</p>
-     *
      * <p><strong>FIXME</strong> - Indexed and mapped properties that do not
      * have getter and setter methods for the underlying array or Map are not
      * copied by this method.</p>
      *
      * @param dest Destination bean whose properties are modified
      * @param orig Origin bean whose properties are retrieved
+     * @param overwritable Overwritable whose determines when origin bean value must overwrite
+     * destination bean
      *
      * @exception IllegalAccessException if the caller does not have
      *  access to the property accessor method
@@ -231,7 +227,7 @@
      * @exception InvocationTargetException if the property accessor method
      *  throws an exception
      */
-    public void copyProperties(Object dest, Object orig)
+    public void mergeProperties(Object dest, Object orig, Overwritable overwritable)
         throws IllegalAccessException, InvocationTargetException {
 
         // Validate existence of the specified beans
@@ -258,6 +254,7 @@
                 if (getPropertyUtils().isReadable(orig, name) &&
                     getPropertyUtils().isWriteable(dest, name)) {
                     Object value = ((DynaBean) orig).get(name);
+                    if (overwritable.mustOverwrite(name, value))
                     copyProperty(dest, name, value);
                 }
             }
@@ -267,6 +264,7 @@
                 String name = (String) names.next();
                 if (getPropertyUtils().isWriteable(dest, name)) {
                     Object value = ((Map) orig).get(name);
+                    if (overwritable.mustOverwrite(name, value))
                     copyProperty(dest, name, value);
                 }
             }
@@ -283,9 +281,10 @@
                     try {
                         Object value =
                             getPropertyUtils().getSimpleProperty(orig, name);
+                        if (overwritable.mustOverwrite(name, value))
                         copyProperty(dest, name, value);
                     } catch (NoSuchMethodException e) {
-                        // Should not happen
+                        ; // Should not happen
                     }
                 }
             }
@@ -293,7 +292,56 @@
 
     }
 
+    /**
+     * <p>Copy property values from the origin bean to the destination bean
+     * for all cases where the property names are the same.  For each
+     * property, a conversion is attempted as necessary.  All combinations of
+     * standard JavaBeans and DynaBeans as origin and destination are
+     * supported.  Properties that exist in the origin bean, but do not exist
+     * in the destination bean (or are read-only in the destination bean) are
+     * silently ignored.</p>
+     *
+     * <p>If the origin "bean" is actually a <code>Map</code>, it is assumed
+     * to contain String-valued <strong>simple</strong> property names as the keys, pointing at
+     * the corresponding property values that will be converted (if necessary)
+     * and set in the destination bean. <strong>Note</strong> that this method
+     * is intended to perform a "shallow copy" of the properties and so complex
+     * properties (for example, nested ones) will not be copied.</p>
+     *
+     * <p>This method differs from <code>populate()</code>, which
+     * was primarily designed for populating JavaBeans from the map of request
+     * parameters retrieved on an HTTP request, is that no scalar->indexed
+     * or indexed->scalar manipulations are performed.  If the origin property
+     * is indexed, the destination property must be also.</p>
+     *
+     * <p>If you know that no type conversions are required, the
+     * <code>copyProperties()</code> method in {@link PropertyUtils} will
+     * execute faster than this method.</p>
+     *
+     * <p><strong>FIXME</strong> - Indexed and mapped properties that do not
+     * have getter and setter methods for the underlying array or Map are not
+     * copied by this method.</p>
+     *
+     * @param dest Destination bean whose properties are modified
+     * @param orig Origin bean whose properties are retrieved
+     *
+     * @exception IllegalAccessException if the caller does not have
+     *  access to the property accessor method
+     * @exception IllegalArgumentException if the <code>dest</code> or
+     *  <code>orig</code> argument is null
+     * @exception InvocationTargetException if the property accessor method
+     *  throws an exception
+     */
+    public void copyProperties(Object dest, Object orig)
+        throws IllegalAccessException, InvocationTargetException {
+    	mergeProperties(dest, orig, new Overwritable() {
 
+			public boolean mustOverwrite(String property, Object value) {
+				return true;
+			}});
+    }
+
+
     /**
      * <p>Copy the specified property value to the specified destination bean,
      * performing any type conversion that is required.  If the specified


Re: Hi alll and a suggestion

Posted by Rodrigo di Lorenzo Lopes <rd...@gmail.com>.
I'm sorry if I resent this email. Actually, I didn't know if I was 
sending this mail correctly.

Thanks.

Rodrigo


Em 1/2/2008 13:41, Niall Pemberton escreveu:
> On Feb 1, 2008 3:22 PM, Rodrigo di Lorenzo Lopes <rd...@gmail.com> wrote:
>   
>> Hi all!
>>
>> I'm Rodrigo di Lorenzo Lopes and I'd like to do some contributions to
>> commons apache project (despite my poor English Knowledge).
>>
>> So, I have one problem with BeanUtils.copyProperties:  From a source, I
>> have a bean partialy populated. From another source, I have the same
>> bean with others informations. How can I merge these beans?
>> My solutions is:  verify an mustOverwrite method before each
>> copyProperty call.  See the patch in attachment.
>>     
>
> I don't have time at the moment to look at what you're proposing -
> could you file a JIRA enhancement request with your patch attached
> please - otherwise its likely to be forgotten / lost on the list.
>
> http://commons.apache.org/beanutils/issue-tracking.html
>
> thanks
>
> Niall
>   

Re: Hi alll and a suggestion

Posted by Niall Pemberton <ni...@gmail.com>.
On Feb 1, 2008 3:22 PM, Rodrigo di Lorenzo Lopes <rd...@gmail.com> wrote:
> Hi all!
>
> I'm Rodrigo di Lorenzo Lopes and I'd like to do some contributions to
> commons apache project (despite my poor English Knowledge).
>
> So, I have one problem with BeanUtils.copyProperties:  From a source, I
> have a bean partialy populated. From another source, I have the same
> bean with others informations. How can I merge these beans?
> My solutions is:  verify an mustOverwrite method before each
> copyProperty call.  See the patch in attachment.

I don't have time at the moment to look at what you're proposing -
could you file a JIRA enhancement request with your patch attached
please - otherwise its likely to be forgotten / lost on the list.

http://commons.apache.org/beanutils/issue-tracking.html

thanks

Niall

> ;)
>
> Best Regards,
>
> Rodrigo
>
> ------------------------------------------------------------------------
>
> Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java
> ===================================================================
> --- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java     (revision 617468)
> +++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java     (working copy)
> @@ -20,6 +20,7 @@
>
>  import java.lang.reflect.InvocationTargetException;
>  import java.util.Calendar;
> +import java.util.Date;
>  import java.util.HashMap;
>  import java.util.Iterator;
>  import java.util.Locale;
> @@ -1637,4 +1638,28 @@
>          }
>          return false;
>      }
> +
> +    public void testMergeProperty() throws Exception {
> +       TestBean testBean = new TestBean();
> +       testBean.setStringProperty("string");
> +       HashMap hashmapTest = new HashMap();
> +       testBean.setMapProperty(null);
> +       Date date = new Date();
> +       testBean.setDateProperty(date);
> +       TestBean testBean2 = new TestBean();
> +       testBean2.setStringProperty("string2");
> +       testBean2.setMapProperty(hashmapTest);
> +       testBean2.setDateProperty(null);
> +       BeanUtilsBean.getInstance().mergeProperties(testBean, testBean2, new Overwritable() {
> +
> +                       public boolean mustOverwrite(String propertyName, Object originValue) {
> +                               if (originValue != null) return true;
> +                               return false;
> +                       }
> +
> +       });
> +       assertEquals(testBean.getStringProperty(), "string2");
> +       assertEquals(testBean.getMapProperty(), hashmapTest);
> +       assertEquals(testBean.getDateProperty(), date);
> +       }
>  }
> Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java
> ===================================================================
> --- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java  (revision 0)
> +++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java  (revision 0)
> @@ -0,0 +1,37 @@
> +/*
> + * 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.beanutils;
> +/**
> + * <p>Interface to know when a property must be overwrite.</p>
> + * <p>See mergeProperties {@link BeanUtils}.</p>
> + * @author Rodrigo di Lorenzo Lopes
> + * @version 1.0
> + * @since 3.3
> + *
> + */
> +public interface Overwritable {
> +
> +       /**
> +        * Determine if property must be overwrite.
> +        * @param propertyName Property name
> +        * @param value Value from origin bean
> +        * @return true, if method must be overwrite.
> +        */
> +       public boolean mustOverwrite(String propertyName, Object originValue);
> +
> +}
> Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java
> ===================================================================
> --- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java (revision 617468)
> +++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java (working copy)
> @@ -190,8 +190,9 @@
>
>
>      /**
> -     * <p>Copy property values from the origin bean to the destination bean
> -     * for all cases where the property names are the same.  For each
> +     * <p>Merge property values from the origin bean to the destination bean
> +     * for all cases where the property names are the same, and always where
> +     * method mustOverwrite of overwritable return true.  For each
>       * property, a conversion is attempted as necessary.  All combinations of
>       * standard JavaBeans and DynaBeans as origin and destination are
>       * supported.  Properties that exist in the origin bean, but do not exist
> @@ -205,22 +206,17 @@
>       * is intended to perform a "shallow copy" of the properties and so complex
>       * properties (for example, nested ones) will not be copied.</p>
>       *
> -     * <p>This method differs from <code>populate()</code>, which
> -     * was primarily designed for populating JavaBeans from the map of request
> -     * parameters retrieved on an HTTP request, is that no scalar->indexed
> -     * or indexed->scalar manipulations are performed.  If the origin property
> -     * is indexed, the destination property must be also.</p>
> +     * <p>This method differs from <code>copyProperties()</code>, which
> +     * always overwrite destination bean with origin bean values. </p>
>       *
> -     * <p>If you know that no type conversions are required, the
> -     * <code>copyProperties()</code> method in {@link PropertyUtils} will
> -     * execute faster than this method.</p>
> -     *
>       * <p><strong>FIXME</strong> - Indexed and mapped properties that do not
>       * have getter and setter methods for the underlying array or Map are not
>       * copied by this method.</p>
>       *
>       * @param dest Destination bean whose properties are modified
>       * @param orig Origin bean whose properties are retrieved
> +     * @param overwritable Overwritable whose determines when origin bean value must overwrite
> +     * destination bean
>       *
>       * @exception IllegalAccessException if the caller does not have
>       *  access to the property accessor method
> @@ -231,7 +227,7 @@
>       * @exception InvocationTargetException if the property accessor method
>       *  throws an exception
>       */
> -    public void copyProperties(Object dest, Object orig)
> +    public void mergeProperties(Object dest, Object orig, Overwritable overwritable)
>          throws IllegalAccessException, InvocationTargetException {
>
>          // Validate existence of the specified beans
> @@ -258,6 +254,7 @@
>                  if (getPropertyUtils().isReadable(orig, name) &&
>                      getPropertyUtils().isWriteable(dest, name)) {
>                      Object value = ((DynaBean) orig).get(name);
> +                    if (overwritable.mustOverwrite(name, value))
>                      copyProperty(dest, name, value);
>                  }
>              }
> @@ -267,6 +264,7 @@
>                  String name = (String) names.next();
>                  if (getPropertyUtils().isWriteable(dest, name)) {
>                      Object value = ((Map) orig).get(name);
> +                    if (overwritable.mustOverwrite(name, value))
>                      copyProperty(dest, name, value);
>                  }
>              }
> @@ -283,9 +281,10 @@
>                      try {
>                          Object value =
>                              getPropertyUtils().getSimpleProperty(orig, name);
> +                        if (overwritable.mustOverwrite(name, value))
>                          copyProperty(dest, name, value);
>                      } catch (NoSuchMethodException e) {
> -                        // Should not happen
> +                        ; // Should not happen
>                      }
>                  }
>              }
> @@ -293,7 +292,56 @@
>
>      }
>
> +    /**
> +     * <p>Copy property values from the origin bean to the destination bean
> +     * for all cases where the property names are the same.  For each
> +     * property, a conversion is attempted as necessary.  All combinations of
> +     * standard JavaBeans and DynaBeans as origin and destination are
> +     * supported.  Properties that exist in the origin bean, but do not exist
> +     * in the destination bean (or are read-only in the destination bean) are
> +     * silently ignored.</p>
> +     *
> +     * <p>If the origin "bean" is actually a <code>Map</code>, it is assumed
> +     * to contain String-valued <strong>simple</strong> property names as the keys, pointing at
> +     * the corresponding property values that will be converted (if necessary)
> +     * and set in the destination bean. <strong>Note</strong> that this method
> +     * is intended to perform a "shallow copy" of the properties and so complex
> +     * properties (for example, nested ones) will not be copied.</p>
> +     *
> +     * <p>This method differs from <code>populate()</code>, which
> +     * was primarily designed for populating JavaBeans from the map of request
> +     * parameters retrieved on an HTTP request, is that no scalar->indexed
> +     * or indexed->scalar manipulations are performed.  If the origin property
> +     * is indexed, the destination property must be also.</p>
> +     *
> +     * <p>If you know that no type conversions are required, the
> +     * <code>copyProperties()</code> method in {@link PropertyUtils} will
> +     * execute faster than this method.</p>
> +     *
> +     * <p><strong>FIXME</strong> - Indexed and mapped properties that do not
> +     * have getter and setter methods for the underlying array or Map are not
> +     * copied by this method.</p>
> +     *
> +     * @param dest Destination bean whose properties are modified
> +     * @param orig Origin bean whose properties are retrieved
> +     *
> +     * @exception IllegalAccessException if the caller does not have
> +     *  access to the property accessor method
> +     * @exception IllegalArgumentException if the <code>dest</code> or
> +     *  <code>orig</code> argument is null
> +     * @exception InvocationTargetException if the property accessor method
> +     *  throws an exception
> +     */
> +    public void copyProperties(Object dest, Object orig)
> +        throws IllegalAccessException, InvocationTargetException {
> +       mergeProperties(dest, orig, new Overwritable() {
>
> +                       public boolean mustOverwrite(String property, Object value) {
> +                               return true;
> +                       }});
> +    }
> +
> +
>      /**
>       * <p>Copy the specified property value to the specified destination bean,
>       * performing any type conversion that is required.  If the specified
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: Hi alll and a suggestion

Posted by simon <si...@chello.at>.
Hi Rodrigo,

It's great to see your offered patch. Thanks. And don't worry about your
English; everyone understands about that.

BeanUtils has only a couple of active developers, so how long it takes
until someone can look at your code depends very much on how busy those
people happen to be now.

The best thing to do would be to create an entry in the JIRA
issue-tracking system and attach your patch there. If there is no
response after a week or so, emailing an occasional reminder to this
list is a good idea.

And by the way, it's great to see a unit test too...

Oh - and in future, please try to select a good subject for your emails.
Firstly, we all put the commons project name at the start. The rest of
the subject line should indicate what the email is about, so people can
see from just the summary line whether to read it.

For example, a better subject for your email would be something like:
 [beanutils] add bean merging to BeanUtils.copyProperties (patch)

Regards,

Simon

On Fri, 2008-02-01 at 13:22 -0200, Rodrigo di Lorenzo Lopes wrote:
> Hi all!
> 
> I'm Rodrigo di Lorenzo Lopes and I'd like to do some contributions to 
> commons apache project (despite my poor English Knowledge).
> 
> So, I have one problem with BeanUtils.copyProperties:  From a source, I 
> have a bean partialy populated. From another source, I have the same 
> bean with others informations. How can I merge these beans?
> My solutions is:  verify an mustOverwrite method before each 
> copyProperty call.  See the patch in attachment.
> 
> ;)
> 
> Best Regards,
> 
> Rodrigo
> 
> ------------------------------------------------------------------------
> 
> Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java
> ===================================================================
> --- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java	(revision 617468)
> +++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/test/org/apache/commons/beanutils/BeanUtilsTestCase.java	(working copy)
> @@ -20,6 +20,7 @@
>  
>  import java.lang.reflect.InvocationTargetException;
>  import java.util.Calendar;
> +import java.util.Date;
>  import java.util.HashMap;
>  import java.util.Iterator;
>  import java.util.Locale;
> @@ -1637,4 +1638,28 @@
>          }
>          return false;
>      }
> +    
> +    public void testMergeProperty() throws Exception {
> +    	TestBean testBean = new TestBean();
> +    	testBean.setStringProperty("string");
> +    	HashMap hashmapTest = new HashMap();
> +    	testBean.setMapProperty(null);
> +    	Date date = new Date();    	
> +    	testBean.setDateProperty(date);
> +    	TestBean testBean2 = new TestBean();
> +    	testBean2.setStringProperty("string2");
> +    	testBean2.setMapProperty(hashmapTest);
> +    	testBean2.setDateProperty(null);
> +    	BeanUtilsBean.getInstance().mergeProperties(testBean, testBean2, new Overwritable() {
> +
> +			public boolean mustOverwrite(String propertyName, Object originValue) {
> +				if (originValue != null) return true; 
> +				return false;
> +			}
> +    		
> +    	});
> +    	assertEquals(testBean.getStringProperty(), "string2");
> +    	assertEquals(testBean.getMapProperty(), hashmapTest);
> +    	assertEquals(testBean.getDateProperty(), date);
> +	}
>  }
> Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java
> ===================================================================
> --- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java	(revision 0)
> +++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/Overwritable.java	(revision 0)
> @@ -0,0 +1,37 @@
> +/*
> + * 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.beanutils;
> +/**
> + * <p>Interface to know when a property must be overwrite.</p>
> + * <p>See mergeProperties {@link BeanUtils}.</p>
> + * @author Rodrigo di Lorenzo Lopes
> + * @version 1.0
> + * @since 3.3
> + *
> + */
> +public interface Overwritable {
> + 
> +	/**
> +	 * Determine if property must be overwrite.
> +	 * @param propertyName Property name
> +	 * @param value Value from origin bean 
> +	 * @return true, if method must be overwrite.
> +	 */
> +	public boolean mustOverwrite(String propertyName, Object originValue);
> +
> +}
> Index: C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java
> ===================================================================
> --- C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java	(revision 617468)
> +++ C:/desenvolvimento/workspace_3.3/Commons-BeanUtils/src/java/org/apache/commons/beanutils/BeanUtilsBean.java	(working copy)
> @@ -190,8 +190,9 @@
>  
> 
>      /**
> -     * <p>Copy property values from the origin bean to the destination bean
> -     * for all cases where the property names are the same.  For each
> +     * <p>Merge property values from the origin bean to the destination bean
> +     * for all cases where the property names are the same, and always where
> +     * method mustOverwrite of overwritable return true.  For each
>       * property, a conversion is attempted as necessary.  All combinations of
>       * standard JavaBeans and DynaBeans as origin and destination are
>       * supported.  Properties that exist in the origin bean, but do not exist
> @@ -205,22 +206,17 @@
>       * is intended to perform a "shallow copy" of the properties and so complex
>       * properties (for example, nested ones) will not be copied.</p>
>       *
> -     * <p>This method differs from <code>populate()</code>, which
> -     * was primarily designed for populating JavaBeans from the map of request
> -     * parameters retrieved on an HTTP request, is that no scalar->indexed
> -     * or indexed->scalar manipulations are performed.  If the origin property
> -     * is indexed, the destination property must be also.</p>
> +     * <p>This method differs from <code>copyProperties()</code>, which
> +     * always overwrite destination bean with origin bean values. </p>
>       *
> -     * <p>If you know that no type conversions are required, the
> -     * <code>copyProperties()</code> method in {@link PropertyUtils} will
> -     * execute faster than this method.</p>
> -     *
>       * <p><strong>FIXME</strong> - Indexed and mapped properties that do not
>       * have getter and setter methods for the underlying array or Map are not
>       * copied by this method.</p>
>       *
>       * @param dest Destination bean whose properties are modified
>       * @param orig Origin bean whose properties are retrieved
> +     * @param overwritable Overwritable whose determines when origin bean value must overwrite
> +     * destination bean
>       *
>       * @exception IllegalAccessException if the caller does not have
>       *  access to the property accessor method
> @@ -231,7 +227,7 @@
>       * @exception InvocationTargetException if the property accessor method
>       *  throws an exception
>       */
> -    public void copyProperties(Object dest, Object orig)
> +    public void mergeProperties(Object dest, Object orig, Overwritable overwritable)
>          throws IllegalAccessException, InvocationTargetException {
>  
>          // Validate existence of the specified beans
> @@ -258,6 +254,7 @@
>                  if (getPropertyUtils().isReadable(orig, name) &&
>                      getPropertyUtils().isWriteable(dest, name)) {
>                      Object value = ((DynaBean) orig).get(name);
> +                    if (overwritable.mustOverwrite(name, value))
>                      copyProperty(dest, name, value);
>                  }
>              }
> @@ -267,6 +264,7 @@
>                  String name = (String) names.next();
>                  if (getPropertyUtils().isWriteable(dest, name)) {
>                      Object value = ((Map) orig).get(name);
> +                    if (overwritable.mustOverwrite(name, value))
>                      copyProperty(dest, name, value);
>                  }
>              }
> @@ -283,9 +281,10 @@
>                      try {
>                          Object value =
>                              getPropertyUtils().getSimpleProperty(orig, name);
> +                        if (overwritable.mustOverwrite(name, value))
>                          copyProperty(dest, name, value);
>                      } catch (NoSuchMethodException e) {
> -                        // Should not happen
> +                        ; // Should not happen
>                      }
>                  }
>              }
> @@ -293,7 +292,56 @@
>  
>      }
>  
> +    /**
> +     * <p>Copy property values from the origin bean to the destination bean
> +     * for all cases where the property names are the same.  For each
> +     * property, a conversion is attempted as necessary.  All combinations of
> +     * standard JavaBeans and DynaBeans as origin and destination are
> +     * supported.  Properties that exist in the origin bean, but do not exist
> +     * in the destination bean (or are read-only in the destination bean) are
> +     * silently ignored.</p>
> +     *
> +     * <p>If the origin "bean" is actually a <code>Map</code>, it is assumed
> +     * to contain String-valued <strong>simple</strong> property names as the keys, pointing at
> +     * the corresponding property values that will be converted (if necessary)
> +     * and set in the destination bean. <strong>Note</strong> that this method
> +     * is intended to perform a "shallow copy" of the properties and so complex
> +     * properties (for example, nested ones) will not be copied.</p>
> +     *
> +     * <p>This method differs from <code>populate()</code>, which
> +     * was primarily designed for populating JavaBeans from the map of request
> +     * parameters retrieved on an HTTP request, is that no scalar->indexed
> +     * or indexed->scalar manipulations are performed.  If the origin property
> +     * is indexed, the destination property must be also.</p>
> +     *
> +     * <p>If you know that no type conversions are required, the
> +     * <code>copyProperties()</code> method in {@link PropertyUtils} will
> +     * execute faster than this method.</p>
> +     *
> +     * <p><strong>FIXME</strong> - Indexed and mapped properties that do not
> +     * have getter and setter methods for the underlying array or Map are not
> +     * copied by this method.</p>
> +     *
> +     * @param dest Destination bean whose properties are modified
> +     * @param orig Origin bean whose properties are retrieved
> +     *
> +     * @exception IllegalAccessException if the caller does not have
> +     *  access to the property accessor method
> +     * @exception IllegalArgumentException if the <code>dest</code> or
> +     *  <code>orig</code> argument is null
> +     * @exception InvocationTargetException if the property accessor method
> +     *  throws an exception
> +     */
> +    public void copyProperties(Object dest, Object orig)
> +        throws IllegalAccessException, InvocationTargetException {
> +    	mergeProperties(dest, orig, new Overwritable() {
>  
> +			public boolean mustOverwrite(String property, Object value) {
> +				return true;
> +			}});
> +    }
> +
> +
>      /**
>       * <p>Copy the specified property value to the specified destination bean,
>       * performing any type conversion that is required.  If the specified
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org