Save This Page
Home » xwork-2.1.1-src » com.opensymphony.xwork2.conversion.impl » [javadoc | source]
    1   //--------------------------------------------------------------------------
    2   //  Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
    3   //  All rights reserved.
    4   //
    5   //  Redistribution and use in source and binary forms, with or without
    6   //  modification, are permitted provided that the following conditions are
    7   //  met:
    8   //
    9   //  Redistributions of source code must retain the above copyright notice,
   10   //  this list of conditions and the following disclaimer.
   11   //  Redistributions in binary form must reproduce the above copyright
   12   //  notice, this list of conditions and the following disclaimer in the
   13   //  documentation and/or other materials provided with the distribution.
   14   //  Neither the name of the Drew Davidson nor the names of its contributors
   15   //  may be used to endorse or promote products derived from this software
   16   //  without specific prior written permission.
   17   //
   18   //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   19   //  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   20   //  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   21   //  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   22   //  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   23   //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   24   //  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
   25   //  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   26   //  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   27   //  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
   28   //  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
   29   //  DAMAGE.
   30   //--------------------------------------------------------------------------
   31   package com.opensymphony.xwork2.conversion.impl;
   32   
   33   import java.lang.reflect.Array;
   34   import java.lang.reflect.Member;
   35   import java.math.BigDecimal;
   36   import java.math.BigInteger;
   37   import java.util.Collections;
   38   import java.util.HashMap;
   39   import java.util.Map;
   40   
   41   import com.opensymphony.xwork2.conversion.TypeConverter;
   42   import com.opensymphony.xwork2.ognl.XWorkTypeConverterWrapper;
   43   
   44   /**
   45    * Default type conversion. Converts among numeric types and also strings.  Contains the basic 
   46    * type mapping code from OGNL.
   47    * 
   48    * @author Luke Blanshard (blanshlu@netscape.net)
   49    * @author Drew Davidson (drew@ognl.org)
   50    */
   51   public class DefaultTypeConverter implements TypeConverter {
   52       private static final String NULL_STRING = "null";
   53   
   54       private final Map<Class, Object> primitiveDefaults;
   55   
   56       public DefaultTypeConverter() {
   57           Map<Class, Object> map = new HashMap<Class, Object>();
   58           map.put(Boolean.TYPE, Boolean.FALSE);
   59           map.put(Byte.TYPE, new Byte((byte) 0));
   60           map.put(Short.TYPE, new Short((short) 0));
   61           map.put(Character.TYPE, new Character((char) 0));
   62           map.put(Integer.TYPE, new Integer(0));
   63           map.put(Long.TYPE, new Long(0L));
   64           map.put(Float.TYPE, new Float(0.0f));
   65           map.put(Double.TYPE, new Double(0.0));
   66           map.put(BigInteger.class, new BigInteger("0"));
   67           map.put(BigDecimal.class, new BigDecimal(0.0));
   68           primitiveDefaults = Collections.unmodifiableMap(map);
   69       }
   70   
   71       public Object convertValue(Map context, Object value, Class toType) {
   72           return convertValue(value, toType);
   73       }
   74   
   75       public Object convertValue(Map context, Object target, Member member,
   76               String propertyName, Object value, Class toType) {
   77           return convertValue(context, value, toType);
   78       }
   79       
   80       public TypeConverter getTypeConverter( Map context )
   81       {
   82           Object obj = context.get(TypeConverter.TYPE_CONVERTER_CONTEXT_KEY);
   83           if (obj instanceof TypeConverter) {
   84               return (TypeConverter) obj;
   85               
   86           // for backwards-compatibility
   87           } else if (obj instanceof ognl.TypeConverter) {
   88               return new XWorkTypeConverterWrapper((ognl.TypeConverter) obj);
   89           }
   90           return null; 
   91       }
   92   
   93       /**
   94        * Returns the value converted numerically to the given class type
   95        * 
   96        * This method also detects when arrays are being converted and converts the
   97        * components of one array to the type of the other.
   98        * 
   99        * @param value
  100        *            an object to be converted to the given type
  101        * @param toType
  102        *            class type to be converted to
  103        * @return converted value of the type given, or value if the value cannot
  104        *         be converted to the given type.
  105        */
  106       public Object convertValue(Object value, Class toType) {
  107           Object result = null;
  108   
  109           if (value != null) {
  110               /* If array -> array then convert components of array individually */
  111               if (value.getClass().isArray() && toType.isArray()) {
  112                   Class componentType = toType.getComponentType();
  113   
  114                   result = Array.newInstance(componentType, Array
  115                           .getLength(value));
  116                   for (int i = 0, icount = Array.getLength(value); i < icount; i++) {
  117                       Array.set(result, i, convertValue(Array.get(value, i),
  118                               componentType));
  119                   }
  120               } else {
  121                   if ((toType == Integer.class) || (toType == Integer.TYPE))
  122                       result = new Integer((int) longValue(value));
  123                   if ((toType == Double.class) || (toType == Double.TYPE))
  124                       result = new Double(doubleValue(value));
  125                   if ((toType == Boolean.class) || (toType == Boolean.TYPE))
  126                       result = booleanValue(value) ? Boolean.TRUE : Boolean.FALSE;
  127                   if ((toType == Byte.class) || (toType == Byte.TYPE))
  128                       result = new Byte((byte) longValue(value));
  129                   if ((toType == Character.class) || (toType == Character.TYPE))
  130                       result = new Character((char) longValue(value));
  131                   if ((toType == Short.class) || (toType == Short.TYPE))
  132                       result = new Short((short) longValue(value));
  133                   if ((toType == Long.class) || (toType == Long.TYPE))
  134                       result = new Long(longValue(value));
  135                   if ((toType == Float.class) || (toType == Float.TYPE))
  136                       result = new Float(doubleValue(value));
  137                   if (toType == BigInteger.class)
  138                       result = bigIntValue(value);
  139                   if (toType == BigDecimal.class)
  140                       result = bigDecValue(value);
  141                   if (toType == String.class)
  142                       result = stringValue(value);
  143                   if (Enum.class.isAssignableFrom(toType))
  144                       result = enumValue((Class<Enum>)toType, value);
  145               }
  146           } else {
  147               if (toType.isPrimitive()) {
  148                   result = primitiveDefaults.get(toType);
  149               }
  150           }
  151           return result;
  152       }
  153   
  154       /**
  155        * Evaluates the given object as a boolean: if it is a Boolean object, it's
  156        * easy; if it's a Number or a Character, returns true for non-zero objects;
  157        * and otherwise returns true for non-null objects.
  158        * 
  159        * @param value
  160        *            an object to interpret as a boolean
  161        * @return the boolean value implied by the given object
  162        */
  163       public static boolean booleanValue(Object value) {
  164           if (value == null)
  165               return false;
  166           Class c = value.getClass();
  167           if (c == Boolean.class)
  168               return ((Boolean) value).booleanValue();
  169           // if ( c == String.class )
  170           // return ((String)value).length() > 0;
  171           if (c == Character.class)
  172               return ((Character) value).charValue() != 0;
  173           if (value instanceof Number)
  174               return ((Number) value).doubleValue() != 0;
  175           return true; // non-null
  176       }
  177       
  178       public Enum<?> enumValue(Class toClass, Object o) {
  179           Enum<?> result = null;
  180           if (o == null) {
  181               result = null;
  182           } else if (o instanceof String[]) {
  183               result = Enum.valueOf(toClass, ((String[]) o)[0]);
  184           } else if (o instanceof String) {
  185               result = Enum.valueOf(toClass, (String) o);
  186           }
  187           return result;
  188       }
  189   
  190       /**
  191        * Evaluates the given object as a long integer.
  192        * 
  193        * @param value
  194        *            an object to interpret as a long integer
  195        * @return the long integer value implied by the given object
  196        * @throws NumberFormatException
  197        *             if the given object can't be understood as a long integer
  198        */
  199       public static long longValue(Object value) throws NumberFormatException {
  200           if (value == null)
  201               return 0L;
  202           Class c = value.getClass();
  203           if (c.getSuperclass() == Number.class)
  204               return ((Number) value).longValue();
  205           if (c == Boolean.class)
  206               return ((Boolean) value).booleanValue() ? 1 : 0;
  207           if (c == Character.class)
  208               return ((Character) value).charValue();
  209           return Long.parseLong(stringValue(value, true));
  210       }
  211   
  212       /**
  213        * Evaluates the given object as a double-precision floating-point number.
  214        * 
  215        * @param value
  216        *            an object to interpret as a double
  217        * @return the double value implied by the given object
  218        * @throws NumberFormatException
  219        *             if the given object can't be understood as a double
  220        */
  221       public static double doubleValue(Object value) throws NumberFormatException {
  222           if (value == null)
  223               return 0.0;
  224           Class c = value.getClass();
  225           if (c.getSuperclass() == Number.class)
  226               return ((Number) value).doubleValue();
  227           if (c == Boolean.class)
  228               return ((Boolean) value).booleanValue() ? 1 : 0;
  229           if (c == Character.class)
  230               return ((Character) value).charValue();
  231           String s = stringValue(value, true);
  232   
  233           return (s.length() == 0) ? 0.0 : Double.parseDouble(s);
  234           /*
  235            * For 1.1 parseDouble() is not available
  236            */
  237           // return Double.valueOf( value.toString() ).doubleValue();
  238       }
  239   
  240       /**
  241        * Evaluates the given object as a BigInteger.
  242        * 
  243        * @param value
  244        *            an object to interpret as a BigInteger
  245        * @return the BigInteger value implied by the given object
  246        * @throws NumberFormatException
  247        *             if the given object can't be understood as a BigInteger
  248        */
  249       public static BigInteger bigIntValue(Object value)
  250               throws NumberFormatException {
  251           if (value == null)
  252               return BigInteger.valueOf(0L);
  253           Class c = value.getClass();
  254           if (c == BigInteger.class)
  255               return (BigInteger) value;
  256           if (c == BigDecimal.class)
  257               return ((BigDecimal) value).toBigInteger();
  258           if (c.getSuperclass() == Number.class)
  259               return BigInteger.valueOf(((Number) value).longValue());
  260           if (c == Boolean.class)
  261               return BigInteger.valueOf(((Boolean) value).booleanValue() ? 1 : 0);
  262           if (c == Character.class)
  263               return BigInteger.valueOf(((Character) value).charValue());
  264           return new BigInteger(stringValue(value, true));
  265       }
  266   
  267       /**
  268        * Evaluates the given object as a BigDecimal.
  269        * 
  270        * @param value
  271        *            an object to interpret as a BigDecimal
  272        * @return the BigDecimal value implied by the given object
  273        * @throws NumberFormatException
  274        *             if the given object can't be understood as a BigDecimal
  275        */
  276       public static BigDecimal bigDecValue(Object value)
  277               throws NumberFormatException {
  278           if (value == null)
  279               return BigDecimal.valueOf(0L);
  280           Class c = value.getClass();
  281           if (c == BigDecimal.class)
  282               return (BigDecimal) value;
  283           if (c == BigInteger.class)
  284               return new BigDecimal((BigInteger) value);
  285           if (c.getSuperclass() == Number.class)
  286               return new BigDecimal(((Number) value).doubleValue());
  287           if (c == Boolean.class)
  288               return BigDecimal.valueOf(((Boolean) value).booleanValue() ? 1 : 0);
  289           if (c == Character.class)
  290               return BigDecimal.valueOf(((Character) value).charValue());
  291           return new BigDecimal(stringValue(value, true));
  292       }
  293   
  294       /**
  295        * Evaluates the given object as a String and trims it if the trim flag is
  296        * true.
  297        * 
  298        * @param value
  299        *            an object to interpret as a String
  300        * @return the String value implied by the given object as returned by the
  301        *         toString() method, or "null" if the object is null.
  302        */
  303       public static String stringValue(Object value, boolean trim) {
  304           String result;
  305   
  306           if (value == null) {
  307               result = NULL_STRING;
  308           } else {
  309               result = value.toString();
  310               if (trim) {
  311                   result = result.trim();
  312               }
  313           }
  314           return result;
  315       }
  316   
  317       /**
  318        * Evaluates the given object as a String.
  319        * 
  320        * @param value
  321        *            an object to interpret as a String
  322        * @return the String value implied by the given object as returned by the
  323        *         toString() method, or "null" if the object is null.
  324        */
  325       public static String stringValue(Object value) {
  326           return stringValue(value, false);
  327       }
  328   }

Save This Page
Home » xwork-2.1.1-src » com.opensymphony.xwork2.conversion.impl » [javadoc | source]