Mega Code Archive

 
Categories / Java / J2EE
 

Contains static methods related to Java and JDO type conversions

/*  * Copyright 2005 (C) TJDO.  * All rights reserved.  *  * This software is distributed under the terms of the TJDO License version 1.0.  * See the terms of the TJDO License in the documentation provided with this software.  *  * $Id: Types.java,v 1.1 2005/12/13 20:46:16 jackknifebarber Exp $  */ import java.math.BigDecimal; import java.math.BigInteger; import java.util.HashMap; /**  * Contains static methods related to Java and JDO type conversions.  *  * @author <a href="mailto:jackknifebarber@users.sourceforge.net">Mike Martin</a>  * @version $Revision: 1.1 $  */ public final class Types {     private Types()     {     }     private static final HashMap WRAPPERS_BY_PRIMITIVE = new HashMap(9);     private static final HashMap PRIMITIVES_BY_WRAPPER = new HashMap(9);     static     {         WRAPPERS_BY_PRIMITIVE.put(Boolean.TYPE,   Boolean.class);         WRAPPERS_BY_PRIMITIVE.put(Byte.TYPE,      Byte.class);         WRAPPERS_BY_PRIMITIVE.put(Character.TYPE, Character.class);         WRAPPERS_BY_PRIMITIVE.put(Short.TYPE,     Short.class);         WRAPPERS_BY_PRIMITIVE.put(Integer.TYPE,   Integer.class);         WRAPPERS_BY_PRIMITIVE.put(Long.TYPE,      Long.class);         WRAPPERS_BY_PRIMITIVE.put(Float.TYPE,     Float.class);         WRAPPERS_BY_PRIMITIVE.put(Double.TYPE,    Double.class);         WRAPPERS_BY_PRIMITIVE.put(Void.TYPE,      Void.class);         PRIMITIVES_BY_WRAPPER.put(Boolean.class,   Boolean.TYPE);         PRIMITIVES_BY_WRAPPER.put(Byte.class,      Byte.TYPE);         PRIMITIVES_BY_WRAPPER.put(Character.class, Character.TYPE);         PRIMITIVES_BY_WRAPPER.put(Short.class,     Short.TYPE);         PRIMITIVES_BY_WRAPPER.put(Integer.class,   Integer.TYPE);         PRIMITIVES_BY_WRAPPER.put(Long.class,      Long.TYPE);         PRIMITIVES_BY_WRAPPER.put(Float.class,     Float.TYPE);         PRIMITIVES_BY_WRAPPER.put(Double.class,    Double.TYPE);         PRIMITIVES_BY_WRAPPER.put(Void.class,      Void.TYPE);     }     /**      * Performs a boxing conversion, if applicable.      * If the type is a Java primitive type it's equivalent wrapper class is      * returned.      * Otherwise the type itself is returned.      *      * @param c      *      the type to be boxed, or <code>null</code>      *      * @return      *      The boxed equivalent, or the type itself if not applicable.      *      <code>null</code> is returned if the argument was null.      */     public static Class box(Class c)     {         Class boxed = (Class)WRAPPERS_BY_PRIMITIVE.get(c);         return boxed == null ? c : boxed;     }     /**      * Performs an unboxing conversion, if applicable.      * If the type is a Java primitive wrapper class it's equivalent primitive      * type is returned.      * Otherwise the type itself is returned.      *      * @param c      *      the type to be unboxed, or <code>null</code>      *      * @return      *      The unboxed equivalent, or the type itself if not applicable.      *      <code>null</code> is returned if the argument was null.      */     public static Class unbox(Class c)     {         Class unboxed = (Class)PRIMITIVES_BY_WRAPPER.get(c);         return unboxed == null ? c : unboxed;     }     /**      * Performs a boxing conversion on multiple classes.      * The returned array contains the results of calling {@link #box(Class)}      * on every class in the argument array.      *      * @param c      *      the types to be boxed      *      * @return      *      the boxed equivalent of all the types in <var>c</var>      */     public static Class[] box(Class[] c)     {         int n = c.length;         Class[] boxed = new Class[n];         for (int i = 0; i < n; ++i)             boxed[i] = box(c[i]);         return boxed;     }     /**      * Performs an unboxing conversion on multiple classes.      * The returned array contains the results of calling {@link #unbox(Class)}      * on every class in the argument array.      *      * @param c      *      the types to be unboxed      *      * @return      *      the unboxed equivalent of all the types in <var>c</var>      */     public static Class[] unbox(Class[] c)     {         int n = c.length;         Class[] unboxed = new Class[n];         for (int i = 0; i < n; ++i)             unboxed[i] = unbox(c[i]);         return unboxed;     }     /**      * Tests if a set of parameters types are all assignable from a given set of      * argument types.      * Returns true iff the number of types match and each parameter type is      * assignable from its corresponding argument type.      * "Assignable" is defined by <code>Class.isAssignableFrom()</code>.      * <p>      * All classes in the parameter type array and the argument type array must      * already be boxed.      *      * @param boxedParamTypes      *      the parameter types      * @param boxedArgTypes      *      the argument types      *      * @return      *      <code>true</code> if the all the parameter types are assignable from      *      the argument types.      */     public static boolean areAssignableFrom(Class[] boxedParamTypes, Class[] boxedArgTypes)     {         int n = boxedParamTypes.length;         if (n != boxedArgTypes.length)             return false;         for (int i = 0; i < n; ++i)         {             if (!boxedParamTypes[i].isAssignableFrom(boxedArgTypes[i]))                 return false;         }         return true;     }     /**      * Performs <dfn>unary numeric promotion</dfn> on the given type.      * Unary numeric promotion is as defined in &sect;5.6.1 of the Java Language      * Specification.      *      * @param operandType      *      the type to be promoted, or <code>null</code>      *      * @return      *      The promoted type, or <code>null</code> if the argument was null.      */     public static Class unaryNumericPromotion(Class operandType)     {         operandType = box(operandType);         if (operandType == Byte.class || operandType == Character.class || operandType == Short.class)             return Integer.class;         else             return operandType;     }     /**      * Performs <dfn>binary numeric promotion</dfn> on a set of input types.      * Binary numeric promotion is as defined in &sect;14.6.2 of the JDO 2.0      * spec.      *      * @param types      *      The input types to be promoted.  If more than two types are present      *      then the first two are promoted, then the promoted type and the      *      third type are promoted, and so on for all the types.      *      * @return      *      The promoted type.  Returns <code>null</code> if the input array      *      is empty.  Returns the first type if the input array has only one      *      type.      *      * @exception IllegalArgumentException      *      if any argument type is not a subclass of java.lang.Number      */     public static Class binaryNumericPromotion(Class[] types)     {         Class promoted = null;         int n = types.length;         if (n > 0)             promoted = types[0];         for (int i = 1; i < n; ++i)             promoted = binaryNumericPromotion(promoted, types[i]);         return promoted;     }     /**      * Performs <dfn>binary numeric promotion</dfn> on a pair of types.      * Binary numeric promotion is as defined in &sect;14.6.2 of the JDO 2.0      * spec.      *      * @param operand1Type      *      the first type in the pair.      * @param operand2Type      *      the other type in the pair.      *      * @return      *      The promoted type.      *      * @exception IllegalArgumentException      *      if either argument type is not a subclass of java.lang.Number      */     public static Class binaryNumericPromotion(Class operand1Type, Class operand2Type)     {         operand1Type = box(operand1Type);         operand2Type = box(operand2Type);         if (operand1Type == BigDecimal.class || operand2Type == BigDecimal.class)             return BigDecimal.class;         if (isBigIntegerVsFloating(operand1Type, operand2Type) || isBigIntegerVsFloating(operand2Type, operand1Type))             return BigDecimal.class;         if (operand1Type == BigInteger.class || operand2Type == BigInteger.class)             return BigInteger.class;         if (operand1Type == Double.class || operand2Type == Double.class)             return Double.class;         if (operand1Type == Float.class || operand2Type == Float.class)             return Float.class;         if (operand1Type == Long.class || operand2Type == Long.class)             return Long.class;         if (!Number.class.isAssignableFrom(operand1Type) || !Number.class.isAssignableFrom(operand2Type))             throw new IllegalArgumentException("No defined numeric promotion for operands of type " + operand1Type.getName() + " and " + operand2Type.getName());         return Integer.class;     }     private static boolean isBigIntegerVsFloating(Class c1, Class c2)     {         return c1 == BigInteger.class && (c2 == Float.class || c2 == Double.class);     } }