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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 
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 [EMAIL PROTECTED] 
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

Reply via email to