com.varra.util.ReflectUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils4j Show documentation
Show all versions of utils4j Show documentation
A must have utils package for java, contains the utility classes which can fasten your development!
The newest version!
/*
* utils4j - ReflectUtil.java, Aug 3, 2013 10:38:29 AM
*
* 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.varra.util;
import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.varra.log.Logger;
import com.varra.lang.Void;
import static com.varra.util.WrapperUtils.*;
import static com.varra.util.ObjectUtils.*;
/**
* Various java.lang.reflect utilities.
*
* @author Rajakrishna V. Reddy
* @version 1.0
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class ReflectUtil
{
/** The Constant VOID. */
private static final String VOID = "void";
/** The Constant LOGGER. */
private static final Logger logger = Logger.getLogger(ReflectUtil.class);
/** an empty class array. */
public static final Class[] NO_PARAMETERS = new Class[0];
/** an empty object array. */
public static final Object[] NO_ARGUMENTS = new Object[0];
/** an empty object array. */
public static final Type[] NO_TYPES = new Type[0];
/** The Constant METHOD_GET_PREFIX. */
public static final String METHOD_GET_PREFIX = "get";
/** The Constant METHOD_IS_PREFIX. */
public static final String METHOD_IS_PREFIX = "is";
/** The Constant METHOD_SET_PREFIX. */
public static final String METHOD_SET_PREFIX = "set";
// ---------------------------------------------------------------- method0
/** The _get method0. */
private static Method _getMethod0;
static
{
try
{
_getMethod0 = Class.class.getDeclaredMethod("getMethod0", String.class, Class[].class);
_getMethod0.setAccessible(true);
}
catch (Exception ignore)
{
try
{
_getMethod0 = Class.class.getMethod("getMethod", String.class, Class[].class);
}
catch (Exception ignored)
{
_getMethod0 = null;
}
}
}
/**
* Invokes private Class.getMethod0()
without throwing
* NoSuchMethodException
. Returns only public methods or
* null
if method not found. Since no exception is throwing, it
* works faster.
*
* @param c
* class to inspect
* @param name
* name of method to find
* @param parameterTypes
* parameter types
* @return founded method, or null
*/
public static Method getMethod0(Class c, String name, Class... parameterTypes)
{
try
{
return (Method) _getMethod0.invoke(c, name, parameterTypes);
}
catch (Exception ignore)
{
return null;
}
}
// ---------------------------------------------------------------- find
// method
/**
* Returns method from an object, matched by name. This may be considered as
* a slow operation, since methods are matched one by one. Returns only
* accessible methods. Only first method is matched.
*
* @param c
* class to examine
* @param methodName
* Full name of the method.
* @return null if method not found
*/
public static Method findMethod(Class c, String methodName)
{
return findDeclaredMethod(c, methodName, true);
}
/**
* Find declared method.
*
* @param c
* the c
* @param methodName
* the method name
* @return the method
*/
public static Method findDeclaredMethod(Class c, String methodName)
{
return findDeclaredMethod(c, methodName, false);
}
/**
* Find declared method.
*
* @param c
* the c
* @param methodName
* the method name
* @param publicOnly
* the public only
* @return the method
*/
private static Method findDeclaredMethod(Class c, String methodName, boolean publicOnly)
{
if ((methodName == null) || (c == null))
{
return null;
}
Method[] ms = publicOnly ? c.getMethods() : c.getDeclaredMethods();
for (Method m : ms)
{
if (m.getName().equals(methodName))
{
return m;
}
}
return null;
}
// ---------------------------------------------------------------- classes
/**
* Returns classes from array of specified objects.
*
* @param objects
* the objects
* @return the classes
*/
public static Class[] getClasses(Object... objects)
{
if (objects == null)
{
return null;
}
Class[] result = new Class[objects.length];
for (int i = 0; i < objects.length; i++)
{
if (objects[i] != null)
{
result[i] = objects[i].getClass();
}
}
return result;
}
// ---------------------------------------------------------------- invoke
/**
* Invokes accessible method of an object.
*
* @param c
* class that contains method
* @param obj
* object to execute
* @param method
* method to invoke
* @param paramClasses
* classes of parameters
* @param params
* parameters �
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws NoSuchMethodException
* the no such method exception
* @throws InvocationTargetException
* the invocation target exception
*/
public static Object invoke(Class c, Object obj, String method, Class[] paramClasses, Object[] params)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException
{
final Method m = c.getMethod(method, paramClasses);
return m.invoke(obj, params);
}
/**
* Invokes accessible method of an object.
*
* @param obj
* object
* @param method
* name of the objects method
* @param paramClasses
* method parameter types
* @param params
* method parameters
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws NoSuchMethodException
* the no such method exception
* @throws InvocationTargetException
* the invocation target exception
*/
public static Object invoke(Object obj, String method, Class[] paramClasses, Object[] params)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException
{
Method m = obj.getClass().getMethod(method, paramClasses);
return m.invoke(obj, params);
}
/**
* Invokes accessible method of an object without specifying parameter
* types.
*
* @param obj
* object
* @param method
* method of an object
* @param params
* method parameters
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws NoSuchMethodException
* the no such method exception
* @throws InvocationTargetException
* the invocation target exception
*/
public static Object invoke(Object obj, String method, Object[] params) throws IllegalAccessException,
NoSuchMethodException, InvocationTargetException
{
Class[] paramClass = getClasses(params);
return invoke(obj, method, paramClass, params);
}
/**
* Invoke.
*
* @param c
* the c
* @param obj
* the obj
* @param method
* the method
* @param params
* the params
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws NoSuchMethodException
* the no such method exception
* @throws InvocationTargetException
* the invocation target exception
*/
public static Object invoke(Class c, Object obj, String method, Object[] params) throws IllegalAccessException,
NoSuchMethodException, InvocationTargetException
{
Class[] paramClass = getClasses(params);
return invoke(c, obj, method, paramClass, params);
}
// ----------------------------------------------------------------
// invokeDeclared
/**
* Invokes any method of a class, even private ones.
*
* @param c
* class to examine
* @param obj
* object to inspect
* @param method
* method to invoke
* @param paramClasses
* parameter types
* @param params
* parameters
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws NoSuchMethodException
* the no such method exception
* @throws InvocationTargetException
* the invocation target exception
*/
public static Object invokeDeclared(Class c, Object obj, String method, Class[] paramClasses, Object[] params)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException
{
final Method m = c.getDeclaredMethod(method, paramClasses);
m.setAccessible(true);
return m.invoke(obj, params);
}
/**
* Invokes any method of a class suppressing java access checking.
*
* @param obj
* object to inspect
* @param method
* method to invoke
* @param paramClasses
* parameter types
* @param params
* parameters
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws NoSuchMethodException
* the no such method exception
* @throws InvocationTargetException
* the invocation target exception
*/
public static Object invokeDeclared(Object obj, String method, Class[] paramClasses, Object[] params)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException
{
Method m = obj.getClass().getDeclaredMethod(method, paramClasses);
m.setAccessible(true);
return m.invoke(obj, params);
}
/**
* Invoke declared.
*
* @param obj
* the obj
* @param method
* the method
* @param params
* the params
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws NoSuchMethodException
* the no such method exception
* @throws InvocationTargetException
* the invocation target exception
*/
public static Object invokeDeclared(Object obj, String method, Object[] params) throws IllegalAccessException,
NoSuchMethodException, InvocationTargetException
{
Class[] paramClass = getClasses(params);
return invokeDeclared(obj, method, paramClass, params);
}
/**
* Invoke declared.
*
* @param c
* the c
* @param obj
* the obj
* @param method
* the method
* @param params
* the params
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws NoSuchMethodException
* the no such method exception
* @throws InvocationTargetException
* the invocation target exception
*/
public static Object invokeDeclared(Class c, Object obj, String method, Object[] params)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException
{
Class[] paramClass = getClasses(params);
return invokeDeclared(c, obj, method, paramClass, params);
}
// ---------------------------------------------------------------- match
// classes
/**
* Determines if first class match the destination and simulates kind of
* instanceof
. All subclasses and interface of first class are
* examined against second class. Method is not symmetric.
*
* @param thisClass
* the this class
* @param target
* the target
* @return true, if is subclass
*/
public static boolean isSubclass(Class thisClass, Class target)
{
if (target.isInterface() != false)
{
return isInterfaceImpl(thisClass, target);
}
for (Class x = thisClass; x != null; x = x.getSuperclass())
{
if (x == target)
{
return true;
}
}
return false;
}
/**
* Returns true
if provided class is interface implementation.
*
* @param thisClass
* the this class
* @param targetInterface
* the target interface
* @return true, if is interface impl
*/
public static boolean isInterfaceImpl(Class thisClass, Class targetInterface)
{
for (Class x = thisClass; x != null; x = x.getSuperclass())
{
Class[] interfaces = x.getInterfaces();
for (Class i : interfaces)
{
if (i == targetInterface)
{
return true;
}
if (isInterfaceImpl(i, targetInterface))
{
return true;
}
}
}
return false;
}
/**
* Dynamic version of instanceof
.
*
* @param o
* object to match
* @param target
* target class
* @return true
if object is an instance of target class
*/
public static boolean isInstanceOf(Object o, Class target)
{
return isSubclass(o.getClass(), target);
}
// ----------------------------------------------------------------
// accessible methods
/**
* Returns array of all methods that are accessible from given class.
*
* @param clazz
* the clazz
* @return the accessible methods
* @see #getAccessibleMethods(Class, Class)
*/
public static Method[] getAccessibleMethods(Class clazz)
{
return getAccessibleMethods(clazz, Object.class);
}
/**
* Returns array of all methods that are accessible from given class, upto
* limit (usually Object.class
). Abstract methods are ignored.
*
* @param clazz
* the clazz
* @param limit
* the limit
* @return the accessible methods
*/
public static Method[] getAccessibleMethods(Class clazz, Class limit)
{
Package topPackage = clazz.getPackage();
List methodList = new ArrayList();
int topPackageHash = topPackage == null ? 0 : topPackage.hashCode();
boolean top = true;
do
{
if (clazz == null)
{
break;
}
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods)
{
if (Modifier.isVolatile(method.getModifiers()))
{
continue;
}
// if (Modifier.isAbstract(method.getModifiers())) {
// continue;
// }
if (top == true)
{ // add all top declared methods
methodList.add(method);
continue;
}
int modifier = method.getModifiers();
if (Modifier.isPrivate(modifier) == true)
{
continue; // ignore super private methods
}
if (Modifier.isAbstract(modifier) == true)
{ // ignore super abstract methods
continue;
}
if (Modifier.isPublic(modifier) == true)
{
addMethodIfNotExist(methodList, method); // add super public
// methods
continue;
}
if (Modifier.isProtected(modifier) == true)
{
addMethodIfNotExist(methodList, method); // add super
// protected
// methods
continue;
}
// add super default methods from the same package
Package pckg = method.getDeclaringClass().getPackage();
int pckgHash = pckg == null ? 0 : pckg.hashCode();
if (pckgHash == topPackageHash)
{
addMethodIfNotExist(methodList, method);
}
}
top = false;
} while ((clazz = clazz.getSuperclass()) != limit);
Method[] methods = new Method[methodList.size()];
for (int i = 0; i < methods.length; i++)
{
methods[i] = methodList.get(i);
}
return methods;
}
/**
* Adds the method if not exist.
*
* @param allMethods
* the all methods
* @param newMethod
* the new method
*/
private static void addMethodIfNotExist(List allMethods, Method newMethod)
{
for (Method m : allMethods)
{
if (compareSignatures(m, newMethod) == true)
{
return;
}
}
allMethods.add(newMethod);
}
// ----------------------------------------------------------------
// accessible fields
/**
* Gets the accessible fields.
*
* @param clazz
* the clazz
* @return the accessible fields
*/
public static Field[] getAccessibleFields(Class clazz)
{
return getAccessibleFields(clazz, Object.class);
}
/**
* Gets the accessible fields.
*
* @param clazz
* the clazz
* @param limit
* the limit
* @return the accessible fields
*/
public static Field[] getAccessibleFields(Class clazz, Class limit)
{
Package topPackage = clazz.getPackage();
List fieldList = new ArrayList();
int topPackageHash = topPackage == null ? 0 : topPackage.hashCode();
boolean top = true;
do
{
if (clazz == null)
{
break;
}
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields)
{
if (top == true)
{ // add all top declared fields
fieldList.add(field);
continue;
}
int modifier = field.getModifiers();
if (Modifier.isPrivate(modifier) == true)
{
continue; // ignore super private fields
}
if (Modifier.isPublic(modifier) == true)
{
addFieldIfNotExist(fieldList, field); // add super public
// methods
continue;
}
if (Modifier.isProtected(modifier) == true)
{
addFieldIfNotExist(fieldList, field); // add super protected
// methods
continue;
}
// add super default methods from the same package
Package pckg = field.getDeclaringClass().getPackage();
int pckgHash = pckg == null ? 0 : pckg.hashCode();
if (pckgHash == topPackageHash)
{
addFieldIfNotExist(fieldList, field);
}
}
top = false;
} while ((clazz = clazz.getSuperclass()) != limit);
Field[] fields = new Field[fieldList.size()];
for (int i = 0; i < fields.length; i++)
{
fields[i] = fieldList.get(i);
}
return fields;
}
/**
* Adds the field if not exist.
*
* @param allFields
* the all fields
* @param newField
* the new field
*/
private static void addFieldIfNotExist(List allFields, Field newField)
{
for (Field f : allFields)
{
if (compareSignatures(f, newField) == true)
{
return;
}
}
allFields.add(newField);
}
// ----------------------------------------------------------------
// supported methods
/**
* Gets the supported methods.
*
* @param clazz
* the clazz
* @return the supported methods
*/
public static Method[] getSupportedMethods(Class clazz)
{
return getSupportedMethods(clazz, Object.class);
}
/**
* Returns a Method
array of the methods to which instances of
* the specified respond except for those methods defined in the class
* specified by limit or any of its superclasses. Note that limit is usually
* used to eliminate them methods defined by java.lang.Object
.
* If limit is null
then all methods are returned.
*
* @param clazz
* the clazz
* @param limit
* the limit
* @return the supported methods
*/
public static Method[] getSupportedMethods(Class clazz, Class limit)
{
ArrayList supportedMethods = new ArrayList();
for (Class c = clazz; c != limit; c = c.getSuperclass())
{
Method[] methods = c.getDeclaredMethods();
for (Method method : methods)
{
boolean found = false;
for (Method supportedMethod : supportedMethods)
{
if (compareSignatures(method, supportedMethod))
{
found = true;
break;
}
}
if (found == false)
{
supportedMethods.add(method);
}
}
}
return supportedMethods.toArray(new Method[supportedMethods.size()]);
}
/**
* Gets the supported fields.
*
* @param clazz
* the clazz
* @return the supported fields
*/
public static Field[] getSupportedFields(Class clazz)
{
return getSupportedFields(clazz, Object.class);
}
/**
* Gets the supported fields.
*
* @param clazz
* the clazz
* @param limit
* the limit
* @return the supported fields
*/
public static Field[] getSupportedFields(Class clazz, Class limit)
{
ArrayList supportedFields = new ArrayList();
for (Class c = clazz; c != limit; c = c.getSuperclass())
{
Field[] fields = c.getDeclaredFields();
for (Field field : fields)
{
boolean found = false;
for (Field supportedField : supportedFields)
{
if (compareSignatures(field, supportedField))
{
found = true;
break;
}
}
if (found == false)
{
supportedFields.add(field);
}
}
}
return supportedFields.toArray(new Field[supportedFields.size()]);
}
// ---------------------------------------------------------------- compare
/**
* Compares method declarations: signature and return types.
*
* @param first
* the first
* @param second
* the second
* @return true, if successful
*/
public static boolean compareDeclarations(Method first, Method second)
{
if (first.getReturnType() != second.getReturnType())
{
return false;
}
return compareSignatures(first, second);
}
/**
* Compares method signatures: names and parameters.
*
* @param first
* the first
* @param second
* the second
* @return true, if successful
*/
public static boolean compareSignatures(Method first, Method second)
{
if (first.getName().equals(second.getName()) == false)
{
return false;
}
return compareParameters(first.getParameterTypes(), second.getParameterTypes());
}
/**
* Compares constructor signatures: names and parameters.
*
* @param first
* the first
* @param second
* the second
* @return true, if successful
*/
public static boolean compareSignatures(Constructor first, Constructor second)
{
if (first.getName().equals(second.getName()) == false)
{
return false;
}
return compareParameters(first.getParameterTypes(), second.getParameterTypes());
}
/**
* Compare signatures.
*
* @param first
* the first
* @param second
* the second
* @return true, if successful
*/
public static boolean compareSignatures(Field first, Field second)
{
return first.getName().equals(second.getName());
}
/**
* Compares method or ctor parameters.
*
* @param first
* the first
* @param second
* the second
* @return true, if successful
*/
public static boolean compareParameters(Class[] first, Class[] second)
{
if (first.length != second.length)
{
return false;
}
for (int i = 0; i < first.length; i++)
{
if (first[i] != second[i])
{
return false;
}
}
return true;
}
// ---------------------------------------------------------------- force
/**
* Suppress access check against a reflection object. SecurityException is
* silently ignored. Checks first if the object is already accessible.
*
* @param accObject
* the acc object
*/
public static void forceAccess(AccessibleObject accObject)
{
if (accObject.isAccessible() == true)
{
return;
}
try
{
accObject.setAccessible(true);
}
catch (SecurityException sex)
{
// ignore
}
}
// ---------------------------------------------------------------- is
// public
/**
* Returns true
if class member is public.
*
* @param member
* the member
* @return true, if is public
*/
public static boolean isPublic(Member member)
{
return Modifier.isPublic(member.getModifiers());
}
/**
* Returns true
if class member is public and if its declaring
* class is also public.
*
* @param member
* the member
* @return true, if is public public
*/
public static boolean isPublicPublic(Member member)
{
if (Modifier.isPublic(member.getModifiers()) == true)
{
if (Modifier.isPublic(member.getDeclaringClass().getModifiers()))
{
return true;
}
}
return false;
}
/**
* Returns true
if class is public.
*
* @param c
* the c
* @return true, if is public
*/
public static boolean isPublic(Class c)
{
return Modifier.isPublic(c.getModifiers());
}
// ---------------------------------------------------------------- create
/**
* Creates new instances including for common mutable classes that do not
* have a default constructor. more user-friendly. It examines if class is a
* map, list, String, Character, Boolean or a Number. Immutable instances
* are cached and not created again. Arrays are also created with no
* elements. Note that this bunch of ifs is faster then a hashmap.
*
* @param type
* the type
* @return the object
* @throws IllegalAccessException
* the illegal access exception
* @throws InstantiationException
* the instantiation exception
*/
public static Object newInstance(Class type) throws IllegalAccessException, InstantiationException
{
if (type.isPrimitive())
{
if (type == int.class)
{
return Integer.valueOf(0);
}
if (type == long.class)
{
return Long.valueOf(0);
}
if (type == boolean.class)
{
return Boolean.FALSE;
}
if (type == float.class)
{
return Float.valueOf(0);
}
if (type == double.class)
{
return Double.valueOf(0);
}
if (type == byte.class)
{
return Byte.valueOf((byte) 0);
}
if (type == short.class)
{
return Short.valueOf((short) 0);
}
if (type == char.class)
{
return Character.valueOf((char) 0);
}
throw new IllegalArgumentException("Invalid primitive type: " + type);
}
if (type == Integer.class)
{
return Integer.valueOf(0);
}
if (type == String.class)
{
return StringPool.EMPTY;
}
if (type == Long.class)
{
return Long.valueOf(0);
}
if (type == Boolean.class)
{
return Boolean.FALSE;
}
if (type == Float.class)
{
Float.valueOf(0);
}
if (type == Double.class)
{
Double.valueOf(0);
}
if (type == Map.class)
{
return new HashMap();
}
if (type == List.class)
{
return new ArrayList();
}
if (type == Set.class)
{
return new LinkedHashSet();
}
if (type == Collection.class)
{
return new ArrayList();
}
if (type == Byte.class)
{
return Byte.valueOf((byte) 0);
}
if (type == Short.class)
{
return Short.valueOf((short) 0);
}
if (type == Character.class)
{
return Character.valueOf((char) 0);
}
if (type.isEnum() == true)
{
return type.getEnumConstants()[0];
}
if (type.isArray() == true)
{
return Array.newInstance(type.getComponentType(), 0);
}
return type.newInstance();
}
// ---------------------------------------------------------------- misc
/**
* Returns true
if the first member is accessible from second
* one.
*
* @param member1
* the member1
* @param member2
* the member2
* @return true, if is assignable from
*/
public static boolean isAssignableFrom(Member member1, Member member2)
{
return member1.getDeclaringClass().isAssignableFrom(member2.getDeclaringClass());
}
/**
* Returns all superclasses.
*
* @param type
* the type
* @return the superclasses
*/
public static Class[] getSuperclasses(Class type)
{
int i = 0;
for (Class x = type.getSuperclass(); x != null; x = x.getSuperclass())
{
i++;
}
Class[] result = new Class[i];
i = 0;
for (Class x = type.getSuperclass(); x != null; x = x.getSuperclass())
{
result[i] = x;
i++;
}
return result;
}
/**
* Returns true
if method is user defined and not defined in
* Object
class.
*
* @param method
* the method
* @return true, if is user defined method
*/
public static boolean isUserDefinedMethod(final Method method)
{
return method.getDeclaringClass() != Object.class;
}
/**
* Returns true
if method defined in Object
class.
*
* @param method
* the method
* @return true, if is object method
*/
public static boolean isObjectMethod(final Method method)
{
return method.getDeclaringClass() == Object.class;
}
/**
* Returns true
if method is a bean property.
*
* @param method
* the method
* @return true, if is bean property
*/
public static boolean isBeanProperty(Method method)
{
if (isObjectMethod(method))
{
return false;
}
String methodName = method.getName();
Class returnType = method.getReturnType();
Class[] paramTypes = method.getParameterTypes();
if (methodName.startsWith(METHOD_GET_PREFIX))
{ // getter method must starts with 'get' and it is not getClass()
if ((returnType != null) && (paramTypes.length == 0))
{ // getter must have a return type and no arguments
return true;
}
}
else if (methodName.startsWith(METHOD_IS_PREFIX))
{ // ister must starts with 'is'
if ((returnType != null) && (paramTypes.length == 0))
{ // ister must have return type and no arguments
return true;
}
}
else if (methodName.startsWith(METHOD_SET_PREFIX))
{ // setter must start with a 'set'
if (paramTypes.length == 1)
{ // setter must have just one argument
return true;
}
}
return false;
}
/**
* Returns true
if method is bean getter.
*
* @param method
* the method
* @return true, if is bean property getter
*/
public static boolean isBeanPropertyGetter(Method method)
{
return getBeanPropertyGetterPrefixLength(method) != 0;
}
/**
* Gets the bean property getter prefix length.
*
* @param method
* the method
* @return the bean property getter prefix length
*/
private static int getBeanPropertyGetterPrefixLength(Method method)
{
if (isObjectMethod(method))
{
return 0;
}
String methodName = method.getName();
Class returnType = method.getReturnType();
Class[] paramTypes = method.getParameterTypes();
if (methodName.startsWith(METHOD_GET_PREFIX))
{ // getter method must starts with 'get' and it is not getClass()
if ((returnType != null) && (paramTypes.length == 0))
{ // getter must have a return type and no arguments
return 3;
}
}
else if (methodName.startsWith(METHOD_IS_PREFIX))
{ // ister must starts with 'is'
if ((returnType != null) && (paramTypes.length == 0))
{ // ister must have return type and no arguments
return 2;
}
}
return 0;
}
/**
* Returns beans property getter name or null
if method is not
* a real getter.
*
* @param method
* the method
* @return the bean property getter name
*/
public static String getBeanPropertyGetterName(Method method)
{
int prefixLength = getBeanPropertyGetterPrefixLength(method);
if (prefixLength == 0)
{
return null;
}
String methodName = method.getName().substring(prefixLength);
return Introspector.decapitalize(methodName);
}
/**
* Returns true
if method is bean setter.
*
* @param method
* the method
* @return true, if is bean property setter
*/
public static boolean isBeanPropertySetter(Method method)
{
return getBeanPropertySetterPrefixLength(method) != 0;
}
/**
* Gets the bean property setter prefix length.
*
* @param method
* the method
* @return the bean property setter prefix length
*/
private static int getBeanPropertySetterPrefixLength(Method method)
{
if (isObjectMethod(method))
{
return 0;
}
String methodName = method.getName();
Class[] paramTypes = method.getParameterTypes();
if (methodName.startsWith(METHOD_SET_PREFIX))
{ // setter must start with a 'set'
if (paramTypes.length == 1)
{ // setter must have just one argument
return 3;
}
}
return 0;
}
/**
* Returns beans property setter name or null
if method is not
* a real setter.
*
* @param method
* the method
* @return the bean property setter name
*/
public static String getBeanPropertySetterName(Method method)
{
int prefixLength = getBeanPropertySetterPrefixLength(method);
if (prefixLength == 0)
{
return null;
}
String methodName = method.getName().substring(prefixLength);
return Introspector.decapitalize(methodName);
}
// ---------------------------------------------------------------- generics
/**
* Returns component type of the given type
. For
* ParameterizedType
it returns the last type in array.
*
* @param type
* the type
* @return the component type
*/
public static Class getComponentType(Type type)
{
return getComponentType(type, -1);
}
/**
* Returns the component type of the given type
.
* For example the following types all have the component-type MyClass:
*
* - MyClass[]
* - List<MyClass>
* - Foo<? extends MyClass>
* - Bar<? super MyClass>
* - <T extends MyClass> T[]
*
*
* @param type
* is the type where to get the component type from.
* @param index
* the index
* @return the component type of the given type
or
* null
if the given type
does NOT have a
* single (component) type.
*/
public static Class getComponentType(Type type, int index)
{
if (type instanceof Class)
{
Class clazz = (Class) type;
if (clazz.isArray())
{
return clazz.getComponentType();
}
}
else if (type instanceof ParameterizedType)
{
ParameterizedType pt = (ParameterizedType) type;
Type[] generics = pt.getActualTypeArguments();
if (index < 0)
{
index = generics.length + index;
}
if (index < generics.length)
{
return toClass(generics[index]);
}
}
else if (type instanceof GenericArrayType)
{
GenericArrayType gat = (GenericArrayType) type;
return toClass(gat.getGenericComponentType());
}
return null;
}
/**
* Gets the generic supertype.
*
* @param type
* the type
* @param index
* the index
* @return the generic supertype
*/
public static Class getGenericSupertype(Class type, int index)
{
return getComponentType(type.getGenericSuperclass(), index);
}
/**
* Gets the generic supertype.
*
* @param type
* the type
* @return the generic supertype
*/
public static Class getGenericSupertype(Class type)
{
return getComponentType(type.getGenericSuperclass());
}
/**
* Returns {@link Class} for the given type
.
* Examples:
*
*
* type
* getSimpleType(type)
*
*
* String
* String
*
* List<String>
* List
*
* <T extends MyClass> T[]
* MyClass[]
*
*
* @param type
* is the type to convert.
* @return the closest class representing the given type
.
*/
public static Class toClass(Type type)
{
if (type instanceof Class)
{
return (Class) type;
}
if (type instanceof ParameterizedType)
{
ParameterizedType pt = (ParameterizedType) type;
return toClass(pt.getRawType());
}
if (type instanceof WildcardType)
{
WildcardType wt = (WildcardType) type;
Type[] lower = wt.getLowerBounds();
if (lower.length == 1)
{
return toClass(lower[0]);
}
Type[] upper = wt.getUpperBounds();
if (upper.length == 1)
{
return toClass(upper[0]);
}
}
else if (type instanceof GenericArrayType)
{
GenericArrayType gat = (GenericArrayType) type;
Class componentType = toClass(gat.getGenericComponentType());
// this is sort of stupid but there seems no other way...
return Array.newInstance(componentType, 0).getClass();
}
else if (type instanceof TypeVariable)
{
TypeVariable tv = (TypeVariable) type;
Type[] bounds = tv.getBounds();
if (bounds.length == 1)
{
return toClass(bounds[0]);
}
}
return null;
}
// ----------------------------------------------------------------
// annotations
/**
* Reads annotation value. Returns null
on error.
*
* @param annotation
* the annotation
* @param name
* the name
* @return the object
*/
public static Object readAnnotationValue(Annotation annotation, String name)
{
try
{
Method method = annotation.annotationType().getDeclaredMethod(name);
return method.invoke(annotation);
}
catch (Exception ignore)
{
return null;
}
}
/**
* Checks the method for the given type of annotation, whether it contains
* it.
*
* @param
* the generic type
* @param type
* the type
* @param methodName
* the method name
* @param equalsIgnoreCase
* the equals ignore case
* @param annotation
* the annotation
* @return true, if successful
*/
public static boolean has(T type, String methodName, boolean equalsIgnoreCase, Class extends Annotation> annotation)
{
try
{
final Method method = getDeclaredMethod(type, methodName, equalsIgnoreCase);
if (isNotNull(method))
{
final Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation2 : annotations)
{
if (annotation2.annotationType().isAssignableFrom(annotation))
{
return true;
}
}
}
}
catch (Exception e)
{
logger.debug("Error while getting the method of type: " + annotation + ", from: " + type, e);
}
return false;
}
/**
* Gets the methods that has.
*
* @param
* the generic type
* @param type
* the type
* @param annotation
* the annotation
* @return the methods that has
*/
public static List getMethodsThatHas(T type, Class extends Annotation> annotation)
{
final List list = new ArrayList();
try
{
final Method[] methods = type.getClass().getMethods();
for (int i = 0; i < methods.length; i++)
{
final Method method = methods[i];
final Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation2 : annotations)
{
if (annotation2.annotationType().isAssignableFrom(annotation))
{
list.add(method.getName());
}
}
}
}
catch (Exception e)
{
logger.debug("Error while getting the list of methods: " + type, e);
}
return list;
}
/**
* Finds the method based on the name provided and executes the method by
* passing the arguments.
*
* @param
* the generic type
* @param
* the value type
* @param type
* the object
* @param methodName
* the method Name
* @param equalsIgnoreCase
* the equals ignore case for method search
* @param args
* the args
* @return the method value if it returns proper value like Integer, Void,
* Float, null if it is not executed success fully.
*/
public static V executeMethod(T type, String methodName, boolean equalsIgnoreCase, Object... args)
{
try
{
final Method method = getDeclaredMethod(type, methodName, equalsIgnoreCase);
method.setAccessible(true);
if (method.getReturnType() == Void.class || method.getReturnType().toString().equals(VOID))
{
method.invoke(type, args);
return (V) Void.getInstance();
}
else
{
return (V) method.invoke(type, args);
}
}
catch (Exception e)
{
logger.debug("Error while getting the field value of: " + methodName, e);
}
return null;
}
/**
* Finds the method based on the name provided and executes the method by
* passing the arguments.
*
* @param
* the generic type
* @param
* the value type
* @param type
* the object
* @param methodName
* the method Name
* @param equalsIgnoreCase
* the equals ignore case for method search
* @param args
* the args
* @return the method value if it returns proper value like Integer, Void,
* Float, null if it is not executed success fully.
*/
public static V executeMethod(T type, String methodName, boolean equalsIgnoreCase, String... args)
{
try
{
final Method method = getDeclaredMethod(type, methodName, equalsIgnoreCase);
method.setAccessible(true);
final Class>[] paramTypes = method.getParameterTypes();
final List