| /* |
| * 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 com.opensymphony.xwork2.conversion.impl; |
| |
| import org.apache.struts2.conversion.TypeConversionException; |
| import com.opensymphony.xwork2.conversion.TypeConverter; |
| import com.opensymphony.xwork2.inject.Container; |
| import com.opensymphony.xwork2.inject.Inject; |
| import org.apache.struts2.StrutsConstants; |
| |
| import java.lang.reflect.Member; |
| import java.util.Calendar; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.Map; |
| |
| |
| /** |
| * <!-- START SNIPPET: javadoc --> |
| * <p> |
| * XWork will automatically handle the most common type conversion for you. This includes support for converting to |
| * and from Strings for each of the following: |
| * </p> |
| * |
| * <ul> |
| * <li>String</li> |
| * <li>boolean / Boolean</li> |
| * <li>char / Character</li> |
| * <li>int / Integer, float / Float, long / Long, double / Double</li> |
| * <li>dates - uses the SHORT format for the Locale associated with the current request</li> |
| * <li>arrays - assuming the individual strings can be coverted to the individual items</li> |
| * <li>collections - if not object type can be determined, it is assumed to be a String and a new ArrayList is |
| * created</li> |
| * </ul> |
| * |
| * <p> Note that with arrays the type conversion will defer to the type of the array elements and try to convert each |
| * item individually. As with any other type conversion, if the conversion can't be performed the standard type |
| * conversion error reporting is used to indicate a problem occurred while processing the type conversion. |
| * </p> |
| * |
| * <!-- END SNIPPET: javadoc --> |
| * |
| * @author <a href="mailto:plightbo@gmail.com">Pat Lightbody</a> |
| * @author Mike Mosiewicz |
| * @author Rainer Hermanns |
| * @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a> |
| */ |
| public class XWorkBasicConverter extends DefaultTypeConverter { |
| |
| private Container container; |
| |
| @Inject |
| public void setContainer(Container container) { |
| this.container = container; |
| } |
| |
| @Override |
| public Object convertValue(Map<String, Object> context, Object o, Member member, String propertyName, Object value, Class toType) { |
| Object result = null; |
| |
| if (value == null || toType.isAssignableFrom(value.getClass())) { |
| // no need to convert at all, right? |
| return value; |
| } |
| |
| if (toType == String.class) { |
| /* the code below has been disabled as it causes sideffects in Struts2 (XW-512) |
| // if input (value) is a number then use special conversion method (XW-490) |
| Class inputType = value.getClass(); |
| if (Number.class.isAssignableFrom(inputType)) { |
| result = doConvertFromNumberToString(context, value, inputType); |
| if (result != null) { |
| return result; |
| } |
| }*/ |
| // okay use default string conversion |
| result = doConvertToString(context, value); |
| } else if (toType == boolean.class) { |
| result = doConvertToBoolean(value); |
| } else if (toType == Boolean.class) { |
| result = doConvertToBoolean(value); |
| } else if (toType.isArray()) { |
| result = doConvertToArray(context, o, member, propertyName, value, toType); |
| } else if (Date.class.isAssignableFrom(toType)) { |
| result = doConvertToDate(context, value, toType); |
| } else if (Calendar.class.isAssignableFrom(toType)) { |
| result = doConvertToCalendar(context, value); |
| } else if (Collection.class.isAssignableFrom(toType)) { |
| result = doConvertToCollection(context, o, member, propertyName, value, toType); |
| } else if (toType == Character.class) { |
| result = doConvertToCharacter(value); |
| } else if (toType == char.class) { |
| result = doConvertToCharacter(value); |
| } else if (Number.class.isAssignableFrom(toType) || toType.isPrimitive()) { |
| result = doConvertToNumber(context, value, toType); |
| } else if (toType == Class.class) { |
| result = doConvertToClass(value); |
| } |
| |
| if (result == null) { |
| if (value instanceof Object[]) { |
| Object[] array = (Object[]) value; |
| |
| if (array.length >= 1) { |
| value = array[0]; |
| } else { |
| value = null; |
| } |
| |
| // let's try to convert the first element only |
| result = convertValue(context, o, member, propertyName, value, toType); |
| } else if (!"".equals(value)) { // we've already tried the types we know |
| result = super.convertValue(context, value, toType); |
| } |
| |
| if (result == null && value != null && !"".equals(value)) { |
| throw new TypeConversionException("Cannot create type " + toType + " from value " + value); |
| } |
| } |
| |
| return result; |
| } |
| |
| private Object doConvertToCalendar(Map<String, Object> context, Object value) { |
| Object result = null; |
| Date dateResult = (Date) doConvertToDate(context, value, Date.class); |
| if (dateResult != null) { |
| Calendar calendar = Calendar.getInstance(); |
| calendar.setTime(dateResult); |
| result = calendar; |
| } |
| return result; |
| } |
| |
| private Object doConvertToCharacter(Object value) { |
| if (value instanceof String) { |
| String cStr = (String) value; |
| return (cStr.length() > 0) ? cStr.charAt(0) : null; |
| } |
| return null; |
| } |
| |
| private Object doConvertToBoolean(Object value) { |
| if (value instanceof String) { |
| String bStr = (String) value; |
| return Boolean.valueOf(bStr); |
| } |
| return null; |
| } |
| |
| private Class doConvertToClass(Object value) { |
| Class clazz = null; |
| if (value != null && value instanceof String && ((String) value).length() > 0) { |
| try { |
| clazz = Class.forName((String) value); |
| } catch (ClassNotFoundException e) { |
| throw new TypeConversionException(e.getLocalizedMessage(), e); |
| } |
| } |
| return clazz; |
| } |
| |
| private Object doConvertToCollection(Map<String, Object> context, Object o, Member member, String prop, Object value, Class toType) { |
| TypeConverter converter = container.getInstance(CollectionConverter.class); |
| if (converter == null) { |
| throw new TypeConversionException("TypeConverter with name [#0] must be registered first! Converter: "+ StrutsConstants.STRUTS_CONVERTER_COLLECTION); |
| } |
| return converter.convertValue(context, o, member, prop, value, toType); |
| } |
| |
| private Object doConvertToArray(Map<String, Object> context, Object o, Member member, String prop, Object value, Class toType) { |
| TypeConverter converter = container.getInstance(ArrayConverter.class); |
| if (converter == null) { |
| throw new TypeConversionException("TypeConverter with name [#0] must be registered first! Converter: "+ StrutsConstants.STRUTS_CONVERTER_ARRAY); |
| } |
| return converter.convertValue(context, o, member, prop, value, toType); |
| } |
| |
| private Object doConvertToDate(Map<String, Object> context, Object value, Class toType) { |
| TypeConverter converter = container.getInstance(DateConverter.class); |
| if (converter == null) { |
| throw new TypeConversionException("TypeConverter with name [#0] must be registered first! Converter: "+ StrutsConstants.STRUTS_CONVERTER_DATE); |
| } |
| return converter.convertValue(context, null, null, null, value, toType); |
| } |
| |
| private Object doConvertToNumber(Map<String, Object> context, Object value, Class toType) { |
| TypeConverter converter = container.getInstance(NumberConverter.class); |
| if (converter == null) { |
| throw new TypeConversionException("TypeConverter with name [#0] must be registered first! Converter: "+ StrutsConstants.STRUTS_CONVERTER_NUMBER); |
| } |
| return converter.convertValue(context, null, null, null, value, toType); |
| } |
| |
| private Object doConvertToString(Map<String, Object> context, Object value) { |
| TypeConverter converter = container.getInstance(StringConverter.class); |
| if (converter == null) { |
| throw new TypeConversionException("TypeConverter with name [#0] must be registered first! Converter: "+ StrutsConstants.STRUTS_CONVERTER_STRING); |
| } |
| return converter.convertValue(context, null, null, null, value, null); |
| } |
| |
| } |