On Feb 1, 2008 3:22 PM, Rodrigo di Lorenzo Lopes <[EMAIL PROTECTED]> 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 [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 > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]