--- jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/BeanUtils.java	11 Mar 2002 04:49:53 -0000	1.15
+++ jakarta-commons/beanutils/src/java/org/apache/commons/beanutils/BeanUtils.java	27 Mar 2002 16:51:26 -0000
@@ -486,7 +486,49 @@
             if (name == null)
                 continue;
             Object value = properties.get(name);	// String or String[]
-
+            setProperty(bean, name, value);
+        }
+    }
+    
+    /**
+     * Sets the JavaBeans property of the specified bean, based on
+     * the specified name/value pair.
+     * <p>
+     * If the bean is a {@link DynaBean}, this method uses {@link DynaProperty}
+     * mechanism to verify existence of the property, and invokes the appropriate
+     * setter. If the dynabean property is nested, this method recursively calls
+     * itself, until a regular bean, or a dynabean with no nesting found.
+     * <p> 
+     * If the bean is a regular one, this method uses Java reflection APIs
+     * to identify corresponding "property setter" method name, and deals
+     * with setter arguments of type <code>String</code>, <code>boolean</code>,
+     * <code>int</code>, <code>long</code>, <code>float</code>, and
+     * <code>double</code>.  In addition, array setters for these types (or the
+     * corresponding primitive types) can also be identified.
+     * <p>
+     * The particular setter method to be called for each property is
+     * determined using the usual JavaBeans introspection mechanisms.  Thus,
+     * you may identify custom setter methods using a BeanInfo class that is
+     * associated with the class of the bean itself.  If no such BeanInfo
+     * class is available, the standard method name conversion ("set" plus
+     * the capitalized name of the property in question) is used.
+     * <p>
+     * <strong>NOTE</strong>:  It is contrary to the JavaBeans Specification
+     * to have more than one setter method (with different argument
+     * signatures) for the same property.
+     *
+     * @param bean JavaBean whose property has to be set
+     * @param name This is the name of the property to be set
+     * @param value This is corresponding (String or String[]) value(s) to be set
+     *
+     * @exception IllegalAccessException if the caller does not have
+     *  access to the property accessor method
+     * @exception InvocationTargetException if the property accessor method
+     *  throws an exception
+     */
+    public static void setProperty(Object bean, String name, Object value)
+            throws IllegalAccessException, InvocationTargetException {
+                
             if (log.isTraceEnabled()) {
                 log.trace("  name='" + name + "', value.class='" +
                           (value == null ? "NONE" :
@@ -500,6 +542,10 @@
             try {
                 if (bean instanceof DynaBean) {
                     String dynaName = name;
+                    int k = dynaName.indexOf(PropertyUtils.NESTED_DELIM);
+                    if (k >= 0) {
+                        dynaName = dynaName.substring(0, k);
+                    }
                     int i = dynaName.indexOf(PropertyUtils.INDEXED_DELIM);
                     if (i >= 0) {
                         dynaName = dynaName.substring(0, i);
@@ -529,7 +575,7 @@
                     log.trace("    No such property, skipping");
                 }
 
-                continue;
+                return;
             }
 
             if (log.isTraceEnabled()) {
@@ -564,7 +610,7 @@
                         log.trace("    No setter method, skipping");
                     }
 
-                    continue;
+                    return;
                 }
                 Class parameterTypes[] = setter.getParameterTypes();
 
@@ -621,6 +667,12 @@
                 Object newValue = null;
                 Class type = dynaProperty.getType();
                 String dynaName = name;
+                String next = null;
+                int nestedDelim = name.indexOf(PropertyUtils.NESTED_DELIM);
+                if (nestedDelim >= 0) {
+                    next = name.substring(nestedDelim+1);
+                    dynaName = name = name.substring(0, nestedDelim);
+                }
                 int index = -1;
                 String key = null;
                 int delim1 = name.indexOf(PropertyUtils.INDEXED_DELIM);
@@ -644,6 +696,33 @@
                         ;
                     }
                 }
+                if (nestedDelim >= 0) {
+                    // Invoke the getter method
+                    Object subBean = null;
+                    try {
+                        if (index >= 0) {
+                            subBean = PropertyUtils.getIndexedProperty(bean, dynaName,
+                                                                       index);
+                        } else if (key != null) {
+                            subBean = PropertyUtils.getMappedProperty(bean, dynaName,
+                                                                      key);
+                        } else {
+                            subBean = PropertyUtils.getProperty(bean, name);
+                        }
+                    } catch (NoSuchMethodException e) {
+                        log.error("    CANNOT HAPPEN (getProperty())", e);
+                    }
+                    if (subBean == null) {
+                        if (log.isTraceEnabled()) {
+                            log.trace("    No value for " + dynaName + ", skipping");
+                        }
+                    }
+                    else {
+                        setProperty(subBean, next, value);
+                    }
+                    return;
+                }
+                // Process the non-nested dyna property here.
                 if (type.isArray() && (index < 0)) {
                     if (value instanceof String) {
                         String values[] = new String[1];
@@ -699,7 +778,6 @@
 
         }
 
-    }
 
 
 }


