You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by bu...@apache.org on 2006/03/17 06:52:50 UTC

DO NOT REPLY [Bug 21679] - Map-backed ActionForms - multiple select - object value conversion

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG�
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=21679>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND�
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=21679





------- Additional Comments From vijaymagic@yahoo.com  2006-03-17 05:52 -------
On using with select with mulitple set to true and using map backed form results
in only one value to be set in map if multiple values are selected.

Copy pasting from my post to the forum : Is there any problem in fixing it in
bean utils? If so update the bug as to what the problem is.

I debugged it and found that this is handled by ||setProperty(Object bean,
String name, Object value) in bean util class
I have cut and pasted the code at the end and using that as context to explain
the problem.
The obtained descriptor is instanceof MappedPropertyDescriptor.

Look for the comments HERE>>> - From this point all idenfitcation for setting up
the value takes place.
At this point the type.isArray fails, the obtained value is: type =
java.lang.Object<T> (The return type for getValue)
value = String["ONE", "TWO"] - This comes out fine.

The code skips condition :  HERE>>>1 and goes through HERE>>>3

The code:
---------

public void setProperty(Object bean, String name, Object value)
       throws IllegalAccessException, InvocationTargetException {

       // Trace logging (if enabled)
       if (log.isTraceEnabled()) {
           StringBuffer sb = new StringBuffer("  setProperty(");
           sb.append(bean);
           sb.append(", ");
           sb.append(name);
           sb.append(", ");
           if (value == null) {
               sb.append("<NULL>");
           } else if (value instanceof String) {
               sb.append((String) value);
           } else if (value instanceof String[]) {
               String values[] = (String[]) value;
               sb.append('[');
               for (int i = 0; i < values.length; i++) {
                   if (i > 0) {
                       sb.append(',');
                   }
                   sb.append(values[i]);
               }
               sb.append(']');
           } else {
               sb.append(value.toString());
           }
           sb.append(')');
           log.trace(sb.toString());
       }

       // Resolve any nested expression to get the actual target bean
       Object target = bean;
       int delim = findLastNestedIndex(name);
       if (delim >= 0) {
           try {
               target =
                   getPropertyUtils().getProperty(bean, name.substring(0, delim));
           } catch (NoSuchMethodException e) {
               return; // Skip this property setter
           }
           name = name.substring(delim + 1);
           if (log.isTraceEnabled()) {
               log.trace("    Target bean = " + target);
               log.trace("    Target name = " + name);
           }
       }

       // Declare local variables we will require
       String propName = null;          // Simple name of target property
       Class type = null;               // Java type of target property
       int index = -1;                  // Indexed subscript value (if any)
       String key = null;               // Mapped key value (if any)

       // Calculate the property name, index, and key values
       propName = name;
       int i = propName.indexOf(PropertyUtils.INDEXED_DELIM);
       if (i >= 0) {
           int k = propName.indexOf(PropertyUtils.INDEXED_DELIM2);
           try {
               index =
                   Integer.parseInt(propName.substring(i + 1, k));
           } catch (NumberFormatException e) {
               ;
           }
           propName = propName.substring(0, i);
       }
       int j = propName.indexOf(PropertyUtils.MAPPED_DELIM);
       if (j >= 0) {
           int k = propName.indexOf(PropertyUtils.MAPPED_DELIM2);
           try {
               key = propName.substring(j + 1, k);
           } catch (IndexOutOfBoundsException e) {
               ;
           }
           propName = propName.substring(0, j);
       }

       // Calculate the property type
       if (target instanceof DynaBean) {
           DynaClass dynaClass = ((DynaBean) target).getDynaClass();
           DynaProperty dynaProperty = dynaClass.getDynaProperty(propName);
           if (dynaProperty == null) {
               return; // Skip this property setter
           }
           type = dynaProperty.getType();
       } else {
           PropertyDescriptor descriptor = null;
           try {
               descriptor =
                   getPropertyUtils().getPropertyDescriptor(target, name);
               if (descriptor == null) {
                   return; // Skip this property setter
               }
           } catch (NoSuchMethodException e) {
               return; // Skip this property setter
           }
           if (descriptor instanceof MappedPropertyDescriptor) {
               if (((MappedPropertyDescriptor)
descriptor).getMappedWriteMethod() == null) {
                   if (log.isDebugEnabled()) {
                       log.debug("Skipping read-only property");
                   }
                   return; // Read-only, skip this property setter
               }
               type = ((MappedPropertyDescriptor) descriptor).
                   getMappedPropertyType();
           } else if (descriptor instanceof IndexedPropertyDescriptor) {
               if (((IndexedPropertyDescriptor)
descriptor).getIndexedWriteMethod() == null) {
                   if (log.isDebugEnabled()) {
                       log.debug("Skipping read-only property");
                   }
                   return; // Read-only, skip this property setter
               }
               type = ((IndexedPropertyDescriptor) descriptor).
                   getIndexedPropertyType();
           } else {
               if (descriptor.getWriteMethod() == null) {
                   if (log.isDebugEnabled()) {
                       log.debug("Skipping read-only property");
                   }
                   return; // Read-only, skip this property setter
               }
               type = descriptor.getPropertyType();
           }
       }
       // HERE>>>
       // Convert the specified value to the required type
       Object newValue = null;
       // HERE>>>1
       if (type.isArray() && (index < 0)) { // Scalar value into array
           if (value == null) {
               String values[] = new String[1];
               values[0] = (String) value;
               newValue = getConvertUtils().convert((String[]) values, type);
           } else if (value instanceof String) {
               String values[] = new String[1];
               values[0] = (String) value;
               newValue = getConvertUtils().convert((String[]) values, type);
           } else if (value instanceof String[]) {
               newValue = getConvertUtils().convert((String[]) value, type);
           } else {
               newValue = value;
           }
       } else if (type.isArray()) {                    // HERE>>>2
           // Indexed value into array
           if (value instanceof String) {
               newValue = getConvertUtils().convert((String) value,
                                               type.getComponentType());
           } else if (value instanceof String[]) {
               newValue = getConvertUtils().convert(((String[]) value)[0],
                                               type.getComponentType());
           } else {
               newValue = value;
           }
       } else {
            // HERE>>>3
            // Value into scalar
           if ((value instanceof String) || (value == null)) {
               newValue = getConvertUtils().convert((String) value, type);
           } else if (value instanceof String[]) {
               newValue = getConvertUtils().convert(((String[]) value)[0],
                                               type);
           } else if (getConvertUtils().lookup(value.getClass()) != null) {
               newValue = getConvertUtils().convert(value.toString(), type);
           } else {
               newValue = value;
           }
       }

       // Invoke the setter method
       try {
           if (index >= 0) {
               getPropertyUtils().setIndexedProperty(target, propName,
                                                index, newValue);
           } else if (key != null) {
               getPropertyUtils().setMappedProperty(target, propName,
                                               key, newValue);
           } else {
               getPropertyUtils().setProperty(target, propName, newValue);
           }
       } catch (NoSuchMethodException e) {
           throw new InvocationTargetException
               (e, "Cannot set " + propName);
       }

   } 

Using struts 1.2.4 Note : I tried with the latest version of bean utils and the
bean utils that comes with 1.2.4.

What is the problem with fixing it by checking if the PropertyDescriptor is
instance of MappedPropertyDescriptor and then push the array values as is since
it is a Map which can take values.

Do you think this fix will break existing codes?

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

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