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.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk@137139 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b991b3f973
commit
0cc87fe88d
|
@ -82,7 +82,7 @@ import org.apache.commons.lang.StringUtils;
|
||||||
* @author Gregor Raýman
|
* @author Gregor Raýman
|
||||||
* @author Jan Sorensen
|
* @author Jan Sorensen
|
||||||
* @author Robert Burrell Donkin
|
* @author Robert Burrell Donkin
|
||||||
* @version $Id: MethodUtils.java,v 1.4 2002/11/18 23:00:26 rdonkin Exp $
|
* @version $Id: MethodUtils.java,v 1.5 2002/11/20 21:45:47 rdonkin Exp $
|
||||||
*/
|
*/
|
||||||
public class MethodUtils {
|
public class MethodUtils {
|
||||||
|
|
||||||
|
@ -570,7 +570,7 @@ public class MethodUtils {
|
||||||
log("Param=" + parameterTypes[n].getName());
|
log("Param=" + parameterTypes[n].getName());
|
||||||
log("Method=" + methodsParams[n].getName());
|
log("Method=" + methodsParams[n].getName());
|
||||||
}
|
}
|
||||||
if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
|
if (!ReflectionUtils.isCompatable(parameterTypes[n], methodsParams[n])) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
log(methodsParams[n] + " is not assignable from "
|
log(methodsParams[n] + " is not assignable from "
|
||||||
+ parameterTypes[n]);
|
+ parameterTypes[n]);
|
||||||
|
@ -613,56 +613,7 @@ public class MethodUtils {
|
||||||
// didn't find a match
|
// didn't find a match
|
||||||
log("No match found.");
|
log("No match found.");
|
||||||
return null;
|
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) {
|
private static void log(Object o) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ import org.apache.commons.lang.StringUtils;
|
||||||
* reflection.
|
* reflection.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
|
* @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
|
||||||
* @version $Id: ReflectionUtils.java,v 1.2 2002/11/18 23:01:36 rdonkin Exp $
|
* @version $Id: ReflectionUtils.java,v 1.3 2002/11/20 21:45:47 rdonkin Exp $
|
||||||
*/
|
*/
|
||||||
public class ReflectionUtils {
|
public class ReflectionUtils {
|
||||||
|
|
||||||
|
@ -197,7 +197,10 @@ public class ReflectionUtils {
|
||||||
* Primitive classes are handled correctly .
|
* Primitive classes are handled correctly .
|
||||||
* <p>
|
* <p>
|
||||||
* In other words, a <code>boolean</code> Class will be converted to
|
* 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 requestedTypes the class array requested
|
||||||
* @param paramTypes the actual class array for the method
|
* @param paramTypes the actual class array for the method
|
||||||
|
@ -214,13 +217,90 @@ public class ReflectionUtils {
|
||||||
paramTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
paramTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < requestedTypes.length; i++) {
|
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 false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
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.
|
* Converts a primitive class to its matching object class.
|
||||||
* Non-primitive classes are unaffected.
|
* Non-primitive classes are unaffected.
|
||||||
|
|
|
@ -67,6 +67,15 @@ public class PrimitiveBean {
|
||||||
private boolean _boolean;
|
private boolean _boolean;
|
||||||
private long _long;
|
private long _long;
|
||||||
private int _int;
|
private int _int;
|
||||||
|
private short _short;
|
||||||
|
|
||||||
|
public short getShort() {
|
||||||
|
return _short;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShort(short _short) {
|
||||||
|
this._short = _short;
|
||||||
|
}
|
||||||
|
|
||||||
public float getFloat() {
|
public float getFloat() {
|
||||||
return _float;
|
return _float;
|
||||||
|
|
|
@ -202,4 +202,87 @@ public class ReflectionUtilsTestCase extends TestCase {
|
||||||
assertEquals("Static scope (method) [isPublicScope]", true, ReflectionUtils.isPublicScope(method));
|
assertEquals("Static scope (method) [isPublicScope]", true, ReflectionUtils.isPublicScope(method));
|
||||||
assertEquals("Static scope (method) [isStatic]", true, ReflectionUtils.isStatic(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue