true the inner class is required to be static
*/
public static Class getClass(Class cl, String name, boolean staticRequired){
Class[] clazzes = cl.getClasses();
for( int i=0; iFor methods, this returns the name of the method * plus a suffix that depends on the number of arguments of the method. * *
The string "()" is added
* if the method has no arguments, and the string "(" is added
* if the method has one or more arguments.
*/
public static String getCompletionName(Member m){
if( m instanceof Field ) return m.getName();
if( m instanceof Method ){
String suffix = ( ((Method)m).getParameterTypes().length == 0 ) ? ")" : "" ;
return m.getName() + "(" + suffix ;
}
return "" ;
}
/**
* Indicates if a member of a Class (field, method ) is static
*
* @param member class member
* @return true if the member is static
*/
public static boolean isStatic( Member member ){
return (member.getModifiers() & Modifier.STATIC) != 0 ;
}
/**
* Checks if the class of the object has the given field. The
* getFields method of Class is used so only public fields are
* checked
*
* @param o object
* @param name name of the field
*
* @return true if the class of o has the field name
*/
public static boolean hasField(Object o, String name) {
return classHasField(o.getClass(), name, false);
}
/**
* Checks if the class of the object has the given inner class. The
* getClasses method of Class is used so only public classes are
* checked
*
* @param o object
* @param name (simple) name of the inner class
*
* @return true if the class of o has the class name
*/
public static boolean hasClass(Object o, String name) {
return classHasClass(o.getClass(), name, false);
}
/**
* Checks if the specified class has the given field. The
* getFields method of Class is used so only public fields are
* checked
*
* @param cl class object
* @param name name of the field
* @param staticRequired if true then the field is required to be static
*
* @return true if the class cl has the field name
*/
public static boolean classHasField(Class cl, String name, boolean staticRequired) {
Field[] fields = cl.getFields();
for (int i = 0; i < fields.length; i++)
if(name.equals(fields[i].getName()) && (!staticRequired || ((fields[i].getModifiers() & Modifier.STATIC) != 0)))
return true;
return false;
}
/**
* Checks if the specified class has the given method. The
* getMethods method of Class is used so only public methods are
* checked
*
* @param cl class
* @param name name of the method
* @param staticRequired if true then the method is required to be static
*
* @return true if the class cl has the method name
*/
public static boolean classHasMethod(Class cl, String name, boolean staticRequired) {
Method[] methodz = cl.getMethods();
for (int i = 0; i < methodz.length; i++)
if (name.equals(methodz[i].getName()) && (!staticRequired || ((methodz[i].getModifiers() & Modifier.STATIC) != 0)))
return true;
return false;
}
/**
* Checks if the specified class has the given inner class. The
* getClasses method of Class is used so only public classes are
* checked
*
* @param cl class
* @param name name of the inner class
* @param staticRequired if true then the method is required to be static
*
* @return true if the class cl has the field name
*/
public static boolean classHasClass(Class cl, String name, boolean staticRequired) {
Class[] clazzes = cl.getClasses();
for (int i = 0; i < clazzes.length; i++)
if (name.equals( getSimpleName(clazzes[i].getName()) ) && (!staticRequired || isStatic( clazzes[i] ) ) )
return true;
return false;
}
/**
* Checks if the class of the object has the given method. The
* getMethods method of Class is used so only public methods are
* checked
*
* @param o object
* @param name name of the method
*
* @return true if the class of o has the field name
*/
public static boolean hasMethod(Object o, String name) {
return classHasMethod(o.getClass(), name, false);
}
/**
* Object creator. Find the best constructor based on the parameter classes
* and invoke newInstance on the resolved constructor
*/
public static Object newInstance( Class o_clazz, Object[] args, Class[] clazzes ) throws Throwable {
boolean[] is_null = new boolean[args.length];
for( int i=0; inull if no constructor is found, or the constructor
*
*/
public static Constructor getConstructor( Class o_clazz, Class[] arg_clazz, boolean[] arg_is_null)
throws SecurityException, NoSuchMethodException {
if (o_clazz == null)
return null;
Constructor cons = null ;
/* if there is no argument, try to find a direct match */
if (arg_clazz == null || arg_clazz.length == 0) {
cons = o_clazz.getConstructor( (Class[] )null );
return cons ;
}
/* try to find an exact match */
try {
cons = o_clazz.getConstructor(arg_clazz);
if (cons != null)
return cons ;
} catch (NoSuchMethodException e) {
/* we catch this one because we want to further search */
}
/* ok, no exact match was found - we have to walk through all methods */
cons = null;
Constructor[] candidates = o_clazz.getConstructors();
for (int k = 0; k < candidates.length; k++) {
Constructor c = candidates[k];
Class[] param_clazz = c.getParameterTypes();
if (arg_clazz.length != param_clazz.length) // number of parameters must match
continue;
int n = arg_clazz.length;
boolean ok = true;
for (int i = 0; i < n; i++) {
if( arg_is_null[i] ){
/* then the class must not be a primitive type */
if( isPrimitive(arg_clazz[i]) ){
ok = false ;
break ;
}
} else{
if (arg_clazz[i] != null && !param_clazz[i].isAssignableFrom(arg_clazz[i])) {
ok = false;
break;
}
}
}
// it must be the only match so far or more specific than the current match
if (ok && (cons == null || isMoreSpecific(c, cons)))
cons = c;
}
if( cons == null ){
throw new NoSuchMethodException( "No constructor matching the given parameters" ) ;
}
return cons;
}
static boolean isPrimitive(Class cl){
return cl.equals(Boolean.TYPE) || cl.equals(Integer.TYPE) ||
cl.equals(Double.TYPE) || cl.equals(Float.TYPE) ||
cl.equals(Long.TYPE) || cl.equals(Short.TYPE) ||
cl.equals(Character.TYPE) ;
}
/**
* Attempts to find the best-matching method of the class o_clazz with the method name name and arguments types defined by arg_clazz.
* The lookup is performed by finding the most specific methods that matches the supplied arguments (see also {@link #isMoreSpecific}).
*
* @param o_clazz class in which to look for the method
* @param name method name
* @param arg_clazz an array of classes defining the types of arguments
* @param arg_is_null indicates if each argument is null
*
* @return null if no matching method could be found or the best matching method.
*/
public static Method getMethod(Class o_clazz, String name, Class[] arg_clazz, boolean[] arg_is_null)
throws SecurityException, NoSuchMethodException {
if (o_clazz == null)
return null;
/* if there is no argument, try to find a direct match */
if (arg_clazz == null || arg_clazz.length == 0) {
return o_clazz.getMethod(name, (Class[])null);
}
/* try to find an exact match */
Method met;
try {
met = o_clazz.getMethod(name, arg_clazz);
if (met != null)
return met;
} catch (NoSuchMethodException e) {
/* we want to search further */
}
/* ok, no exact match was found - we have to walk through all methods */
met = null;
Method[] ml = o_clazz.getMethods();
for (int k = 0; k < ml.length; k++) {
Method m = ml[k];
if (!m.getName().equals(name)) // the name must match
continue;
Class[] param_clazz = m.getParameterTypes();
if (arg_clazz.length != param_clazz.length) // number of parameters must match
continue;
int n = arg_clazz.length;
boolean ok = true;
for (int i = 0; i < n; i++) {
if( arg_is_null[i] ){
/* then the class must not be a primitive type */
if( isPrimitive(arg_clazz[i]) ){
ok = false ;
break ;
}
} else{
if (arg_clazz[i] != null && !param_clazz[i].isAssignableFrom(arg_clazz[i])) {
ok = false;
break;
}
}
}
if (ok && (met == null || isMoreSpecific(m, met))) // it must be the only match so far or more specific than the current match
met = m;
}
if( met == null ){
throw new NoSuchMethodException( "No suitable method for the given parameters" ) ;
}
return met;
}
/**
* Returns true if m1 is more specific than m2.
* The measure used is described in the isMoreSpecific( Class[], Class[] ) method
*
* @param m1 method to compare
* @param m2 method to compare
*
* @return true if m1 is more specific (in arguments) than m2.
*/
private static boolean isMoreSpecific(Method m1, Method m2) {
Class[] m1_param_clazz = m1.getParameterTypes();
Class[] m2_param_clazz = m2.getParameterTypes();
return isMoreSpecific( m1_param_clazz, m2_param_clazz );
}
/**
* Returns true if cons1 is more specific than cons2.
* The measure used is described in the isMoreSpecific( Class[], Class[] ) method
*
* @param cons1 constructor to compare
* @param cons2 constructor to compare
*
* @return true if cons1 is more specific (in arguments) than cons2.
*/
private static boolean isMoreSpecific(Constructor cons1, Constructor cons2) {
Class[] cons1_param_clazz = cons1.getParameterTypes();
Class[] cons2_param_clazz = cons2.getParameterTypes();
return isMoreSpecific( cons1_param_clazz, cons2_param_clazz );
}
/**
* Returns true if c1 is more specific than c2.
*
* The measure used is the sum of more specific arguments minus the sum of less specific arguments
* which in total must be positive to qualify as more specific.
* (More specific means the argument is a subclass of the other argument).
*
* Both set of classes must have signatures fully compatible in the arguments
* (more precisely incompatible arguments are ignored in the comparison).
*
* @param c1 set of classes to compare
* @param c2 set of classes to compare
*/
private static boolean isMoreSpecific( Class[] c1, Class[] c2){
int n = c1.length ;
int res = 0;
for (int i = 0; i < n; i++)
if( c1[i] != c2[i]) {
if( c1[i].isAssignableFrom(c2[i]))
res--;
else if( c2[i].isAssignableFrom(c2[i]) )
res++;
}
return res > 0;
}
/**
* Returns the list of classes of the object
*
* @param o an Object
*/
public static Class[] getClasses(Object o){
Vector/*