rdonkin     2002/11/20 13:45:47

  Modified:    lang/src/java/org/apache/commons/lang/reflect
                        MethodUtils.java ReflectionUtils.java
               lang/src/test/org/apache/commons/lang/reflect
                        PrimitiveBean.java ReflectionUtilsTestCase.java
  Log:
  Moved isAssignmentCompatable method from MethodUtils into ReflectionUtils and 
renamed it. Enhanced existing isCompatible so that widening of primitives is allowed. 
Created test case for moved method.
  
  Revision  Changes    Path
  1.5       +3 -52     
jakarta-commons/lang/src/java/org/apache/commons/lang/reflect/MethodUtils.java
  
  Index: MethodUtils.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/lang/src/java/org/apache/commons/lang/reflect/MethodUtils.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- MethodUtils.java  18 Nov 2002 23:00:26 -0000      1.4
  +++ MethodUtils.java  20 Nov 2002 21:45:47 -0000      1.5
  @@ -570,7 +570,7 @@
                               log("Param=" + parameterTypes[n].getName());
                               log("Method=" + methodsParams[n].getName());
                           }
  -                        if (!isAssignmentCompatible(methodsParams[n], 
parameterTypes[n])) {
  +                        if (!ReflectionUtils.isCompatable(parameterTypes[n], 
methodsParams[n])) {
                               if (debug) {
                                   log(methodsParams[n] + " is not assignable from " 
                                               + parameterTypes[n]);
  @@ -613,56 +613,7 @@
           // didn't find a match
           log("No match found.");
           return null;                                        
  -    }
  -
  -
  -    /**
  -     * <p>Determine whether a type can be used as a parameter in a method 
invocation.
  -     * This method handles primitive conversions correctly.</p>
  -     *
  -     * <p>In order words, it will match a <code>Boolean</code> to a 
<code>boolean</code>,
  -     * a <code>Long</code> to a <code>long</code>,
  -     * a <code>Float</code> to a <code>float</code>,
  -     * a <code>Integer</code> to a <code>int</code>,
  -     * and a <code>Double</code> to a <code>double</code>.
  -     * Now logic widening matches are allowed.
  -     * For example, a <code>Long</code> will not match a <code>int</code>.
  -     *
  -     * @param parameterType the type of parameter accepted by the method
  -     * @param parameterization the type of parameter being tested 
  -     *
  -     * @return true if the assignement is compatible.
  -     */
  -    private static final boolean isAssignmentCompatible(Class parameterType, Class 
parameterization) {
  -        // try plain assignment
  -        if (parameterType.isAssignableFrom(parameterization)) {
  -            return true;
  -        }
  -        
  -        if (parameterType.isPrimitive()) {
  -            // does anyone know a better strategy than comparing names?
  -            // also, this method does *not* do widening - you must specify exactly
  -            // is this the right behaviour?
  -            if (boolean.class.equals(parameterType)) {
  -                return Boolean.class.equals(parameterization);
  -            }         
  -            if (float.class.equals(parameterType)) {
  -                return Float.class.equals(parameterization);
  -            }     
  -            if (long.class.equals(parameterType)) {
  -                return Long.class.equals(parameterization);
  -            }     
  -            if (int.class.equals(parameterType)) {
  -                return Integer.class.equals(parameterization);
  -            }                
  -            if (double.class.equals(parameterType)) {
  -                return Double.class.equals(parameterization);
  -            }               
  -        }
  -        
  -        return false;
  -    }
  -    
  +    }    
       
       private static void log(Object o) {
           if (debug) {
  
  
  
  1.3       +83 -3     
jakarta-commons/lang/src/java/org/apache/commons/lang/reflect/ReflectionUtils.java
  
  Index: ReflectionUtils.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/lang/src/java/org/apache/commons/lang/reflect/ReflectionUtils.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ReflectionUtils.java      18 Nov 2002 23:01:36 -0000      1.2
  +++ ReflectionUtils.java      20 Nov 2002 21:45:47 -0000      1.3
  @@ -197,7 +197,10 @@
        * Primitive classes are handled correctly .
        * <p>
        * In other words, a <code>boolean</code> Class will be converted to 
  -     * a <code>Boolean</code> Class and so on.
  +     * a <code>Boolean</code> Class and so on.</p>
  +     *
  +     * <p>This method also handles widening for primitives as given in section 
5.1.2 of the
  +     * <em><a href="http://java.sun.com/docs/books/jls/";>The Java Language 
Specification</a></em>.
        *
        * @param requestedTypes  the class array requested
        * @param paramTypes  the actual class array for the method
  @@ -214,12 +217,89 @@
               paramTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
           }
           for (int i = 0; i < requestedTypes.length; i++) {
  -            if (ClassUtils.isAssignable(requestedTypes[i], paramTypes[i]) == false) 
{
  +            if (isCompatable(requestedTypes[i], paramTypes[i]) == false) {
                   return false;
               }
           }
           return true;
       }
  +    
  +
  +    /**
  +     * <p>Determine whether a type can be used as a parameter in a method 
invocation.
  +     * This method handles primitive conversions correctly.</p>
  +     *
  +     * <p>This method also handles widening for primitives as given in section 
5.1.2 of the
  +     * <em><a href="http://java.sun.com/docs/books/jls/";>The Java Language 
Specification</a></em>.
  +     *
  +     * @param parameterType the type of parameter accepted by the method
  +     * @param requestedType the type of parameter being requested 
  +     *
  +     * @return true if the assignement is compatible.
  +     */
  +    public static boolean isCompatable(Class requestedType, Class parameterType) {
  +        // try plain assignment
  +        if (ClassUtils.isAssignable(requestedType, parameterType)) {
  +            return true;
  +        }
  +        
  +        if (parameterType.isPrimitive()) {
  +            // also, this method does *not* do widening - you must specify exactly
  +            // is this the right behaviour?
  +            if (boolean.class.equals(parameterType)) {
  +                return Boolean.class.equals(requestedType);
  +            }              
  +            
  +            if (byte.class.equals(parameterType)) {
  +                return Byte.class.equals(requestedType);
  +            }
  +            
  +            if (short.class.equals(parameterType)) {
  +                return (Short.class.equals(requestedType)
  +                        || Byte.class.equals(requestedType));
  +            }                    
  +            
  +            if (char.class.equals(parameterType)) {
  +                return Character.class.equals(requestedType);
  +            }
  +                               
  +            if (int.class.equals(parameterType)) {
  +                return (Integer.class.equals(requestedType)
  +                        || Character.class.equals(requestedType)
  +                        || Short.class.equals(requestedType)
  +                        || Byte.class.equals(requestedType));
  +            }       
  +            if (long.class.equals(parameterType)) {
  +                return (Long.class.equals(requestedType) 
  +                        || Integer.class.equals(requestedType)
  +                        || Character.class.equals(requestedType)
  +                        || Short.class.equals(requestedType)
  +                        || Byte.class.equals(requestedType));
  +            }                   
  +                
  +            if (float.class.equals(parameterType)) {
  +                return (Float.class.equals(requestedType)
  +                        || Long.class.equals(requestedType)
  +                        || Integer.class.equals(requestedType)
  +                        || Character.class.equals(requestedType)
  +                        || Short.class.equals(requestedType)
  +                        || Byte.class.equals(requestedType));
  +            }     
  +               
  +            if (double.class.equals(parameterType)) {
  +                return (Double.class.equals(requestedType)   
  +                        || Float.class.equals(requestedType)
  +                        || Long.class.equals(requestedType)
  +                        || Integer.class.equals(requestedType)
  +                        || Character.class.equals(requestedType)
  +                        || Short.class.equals(requestedType)
  +                        || Byte.class.equals(requestedType));
  +            }   
  +        }
  +        
  +        return false;
  +    }
  +
       
       /**
        * Converts a primitive class to its matching object class.
  
  
  
  1.2       +9 -0      
jakarta-commons/lang/src/test/org/apache/commons/lang/reflect/PrimitiveBean.java
  
  Index: PrimitiveBean.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/lang/src/test/org/apache/commons/lang/reflect/PrimitiveBean.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PrimitiveBean.java        14 Nov 2002 18:53:36 -0000      1.1
  +++ PrimitiveBean.java        20 Nov 2002 21:45:47 -0000      1.2
  @@ -67,6 +67,15 @@
       private boolean _boolean;
       private long _long;
       private int _int;
  +    private short _short;
  +    
  +    public short getShort() {
  +        return _short;
  +    }
  +    
  +    public void setShort(short _short) {
  +        this._short = _short;
  +    }
       
       public float getFloat() {
           return _float;
  
  
  
  1.2       +83 -0     
jakarta-commons/lang/src/test/org/apache/commons/lang/reflect/ReflectionUtilsTestCase.java
  
  Index: ReflectionUtilsTestCase.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/lang/src/test/org/apache/commons/lang/reflect/ReflectionUtilsTestCase.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ReflectionUtilsTestCase.java      18 Nov 2002 23:01:36 -0000      1.1
  +++ ReflectionUtilsTestCase.java      20 Nov 2002 21:45:47 -0000      1.2
  @@ -202,4 +202,87 @@
           assertEquals("Static scope (method) [isPublicScope]", true, 
ReflectionUtils.isPublicScope(method));
           assertEquals("Static scope (method) [isStatic]", true, 
ReflectionUtils.isStatic(method));
       }
  +    
  +    public void testWidening() throws Exception
  +    {
  +        // test byte conversions
  +        assertEquals("byte -> char", ReflectionUtils.isCompatable(Byte.class, 
char.class), false);
  +        assertEquals("byte -> byte", ReflectionUtils.isCompatable(Byte.class, 
byte.class), true);
  +        assertEquals("byte -> short", ReflectionUtils.isCompatable(Byte.class, 
short.class), true);
  +        assertEquals("byte -> int", ReflectionUtils.isCompatable(Byte.class, 
int.class), true);
  +        assertEquals("byte -> long", ReflectionUtils.isCompatable(Byte.class, 
long.class), true);
  +        assertEquals("byte -> float", ReflectionUtils.isCompatable(Byte.class, 
float.class), true);
  +        assertEquals("byte -> double", ReflectionUtils.isCompatable(Byte.class, 
double.class), true);
  +        assertEquals("byte -> boolean", ReflectionUtils.isCompatable(Byte.class, 
boolean.class), false);
  +        
  +        // test short conversions
  +        assertEquals("short -> char", ReflectionUtils.isCompatable(Short.class, 
char.class), false);
  +        assertEquals("short -> byte", ReflectionUtils.isCompatable(Short.class, 
byte.class), false);
  +        assertEquals("short -> short", ReflectionUtils.isCompatable(Short.class, 
short.class), true);
  +        assertEquals("short -> int", ReflectionUtils.isCompatable(Short.class, 
int.class), true);
  +        assertEquals("short -> long", ReflectionUtils.isCompatable(Short.class, 
long.class), true);
  +        assertEquals("short -> float", ReflectionUtils.isCompatable(Short.class, 
float.class), true);
  +        assertEquals("short -> double", ReflectionUtils.isCompatable(Short.class, 
double.class), true);
  +        assertEquals("short -> boolean", ReflectionUtils.isCompatable(Short.class, 
boolean.class), false);
  +        
  +        // test char conversions
  +        assertEquals("char -> char", ReflectionUtils.isCompatable(Character.class, 
char.class), true);
  +        assertEquals("char -> byte", ReflectionUtils.isCompatable(Character.class, 
byte.class), false);
  +        assertEquals("char -> short", ReflectionUtils.isCompatable(Character.class, 
short.class), false);
  +        assertEquals("char -> int", ReflectionUtils.isCompatable(Character.class, 
int.class), true);
  +        assertEquals("char -> long", ReflectionUtils.isCompatable(Character.class, 
long.class), true);
  +        assertEquals("char -> float", ReflectionUtils.isCompatable(Character.class, 
float.class), true);
  +        assertEquals("char -> double", 
ReflectionUtils.isCompatable(Character.class, double.class), true);
  +        assertEquals("char -> boolean", 
ReflectionUtils.isCompatable(Character.class, boolean.class), false);
  +        
  +        // test int conversions
  +        assertEquals("int -> char", ReflectionUtils.isCompatable(Integer.class, 
char.class), false);
  +        assertEquals("int -> byte", ReflectionUtils.isCompatable(Integer.class, 
byte.class), false);
  +        assertEquals("int -> short", ReflectionUtils.isCompatable(Integer.class, 
short.class), false);
  +        assertEquals("int -> int", ReflectionUtils.isCompatable(Integer.class, 
int.class), true);
  +        assertEquals("int -> long", ReflectionUtils.isCompatable(Integer.class, 
long.class), true);
  +        assertEquals("int -> float", ReflectionUtils.isCompatable(Integer.class, 
float.class), true);
  +        assertEquals("int -> double", ReflectionUtils.isCompatable(Integer.class, 
double.class), true);
  +        assertEquals("int -> boolean", ReflectionUtils.isCompatable(Integer.class, 
boolean.class), false);
  + 
  +        // test long conversions
  +        assertEquals("long -> char", ReflectionUtils.isCompatable(Long.class, 
char.class), false);
  +        assertEquals("long -> byte", ReflectionUtils.isCompatable(Long.class, 
byte.class), false);
  +        assertEquals("long -> short", ReflectionUtils.isCompatable(Long.class, 
short.class), false);
  +        assertEquals("long -> int", ReflectionUtils.isCompatable(Long.class, 
int.class), false);
  +        assertEquals("long -> long", ReflectionUtils.isCompatable(Long.class, 
long.class), true);
  +        assertEquals("long -> float", ReflectionUtils.isCompatable(Long.class, 
float.class), true);
  +        assertEquals("long -> double", ReflectionUtils.isCompatable(Long.class, 
double.class), true);
  +        assertEquals("long -> boolean", ReflectionUtils.isCompatable(Long.class, 
boolean.class), false);
  + 
  +        // test float conversions
  +        assertEquals("float -> char", ReflectionUtils.isCompatable(Float.class, 
char.class), false);
  +        assertEquals("float -> byte", ReflectionUtils.isCompatable(Float.class, 
byte.class), false);
  +        assertEquals("float -> short", ReflectionUtils.isCompatable(Float.class, 
short.class), false);
  +        assertEquals("float -> int", ReflectionUtils.isCompatable(Float.class, 
int.class), false);
  +        assertEquals("float -> long", ReflectionUtils.isCompatable(Float.class, 
long.class), false);
  +        assertEquals("float -> float", ReflectionUtils.isCompatable(Float.class, 
float.class), true);
  +        assertEquals("float -> double", ReflectionUtils.isCompatable(Float.class, 
double.class), true);
  +        assertEquals("float -> boolean", ReflectionUtils.isCompatable(Float.class, 
boolean.class), false);
  +        
  +        // test float conversions
  +        assertEquals("double -> char", ReflectionUtils.isCompatable(Double.class, 
char.class), false);
  +        assertEquals("double -> byte", ReflectionUtils.isCompatable(Double.class, 
byte.class), false);
  +        assertEquals("double -> short", ReflectionUtils.isCompatable(Double.class, 
short.class), false);
  +        assertEquals("double -> int", ReflectionUtils.isCompatable(Double.class, 
int.class), false);
  +        assertEquals("double -> long", ReflectionUtils.isCompatable(Double.class, 
long.class), false);
  +        assertEquals("double -> float", ReflectionUtils.isCompatable(Double.class, 
float.class), false);
  +        assertEquals("double -> double", ReflectionUtils.isCompatable(Double.class, 
double.class), true);
  +        assertEquals("double -> boolean", 
ReflectionUtils.isCompatable(Double.class, boolean.class), false);
  +        
  +        // test float conversions
  +        assertEquals("boolean -> char", ReflectionUtils.isCompatable(Boolean.class, 
char.class), false);
  +        assertEquals("boolean -> byte", ReflectionUtils.isCompatable(Boolean.class, 
byte.class), false);
  +        assertEquals("boolean -> short", 
ReflectionUtils.isCompatable(Boolean.class, short.class), false);
  +        assertEquals("boolean -> int", ReflectionUtils.isCompatable(Boolean.class, 
int.class), false);
  +        assertEquals("boolean -> long", ReflectionUtils.isCompatable(Boolean.class, 
long.class), false);
  +        assertEquals("boolean -> float", 
ReflectionUtils.isCompatable(Boolean.class, float.class), false);
  +        assertEquals("boolean -> double", 
ReflectionUtils.isCompatable(Boolean.class, double.class), false);
  +        assertEquals("boolean -> boolean", 
ReflectionUtils.isCompatable(Boolean.class, boolean.class), true);
  +    }
   }
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to