/*****************************************************************************
* Copyright (C) Codehaus.org. All rights reserved. *
* ------------------------------------------------------------------------- *
* The software in this package is published under the terms of the BSD *
* style license a copy of which has been included with this distribution in *
* the LICENSE.txt file. *
*****************************************************************************/
/*
* Created on Feb 28, 2005
*
* Author Ben Yu
* ZBS
*/
package jfun.yan;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import jfun.util.beans.Bean;
import jfun.util.beans.BeanType;
import jfun.yan.function.Function;
import jfun.yan.util.ReflectionUtil;
/**
* This is the facade class to create different Function objects.
* <p>
* throughout this class, when searching reflection objects,
* public members are defined as members
* defined with "public" keyword and declared in a public type.
* public members declared by a non-public class is considered non-public
* because access to it from outside is prohibited by the java access control
* anyway.
* </p>
* <p>
* public members defined in public classes are always prefered even
* when we allow private/protected members and types to be visible.
* So if a non-public subtype and a public super type both have a field
* with the same name, the field in the public super type is always used.
* </p>
* <P>
* Codehaus.org.
*
* @author Ben Yu
*
*/
public final class Functions {
/**
* Adapts a {@link java.lang.reflect.Constructor} object
* to a Function object.
* @param ctor the constructor object.
* @return the Function object.
*/
public static <T> Function<T> ctor(Constructor<T> ctor){
return new ConstructorFunction<T>(ctor);
}
/**
* Adapts a {@link java.lang.reflect.Method} object and the receiver object
* to a Function object.
* @param obj the receiver object to call the method against.
* If the method is static, the object can be null.
* @param mtd the method object.
* @return the Function object.
*/
public static Function method(Object obj, Method mtd){
return new MethodFunction(canonicalize(obj, mtd), mtd);
}
private static final Object canonicalize(Object obj, Method mtd){
//if method is static, we do not save the object,
//lest the object is not serializable and prevent us from serializing
//the function.
if(java.lang.reflect.Modifier.isStatic(mtd.getModifiers())){
return null;
}
else return obj;
}
private static final Object canonicalize(Object obj, Field fld){
//if field is static, we do not save the object,
//lest the object is not serializable and prevent us from serializing
//the function.
if(java.lang.reflect.Modifier.isStatic(fld.getModifiers())){
return null;
}
else return obj;
}
/**
* Create a Function object that uses the public constructor of a class.
* This class should have one and only one public constructor.
* <br>
* Array type is given a special constructor so that the constructor of
* array type T has one parameter of type int
* and calls new T[size] when invoked.
* @param c the class.
* @return the Function object.
* @throws IllegalArgumentException
* if the class has no public constructor
* or has more than one public constructor.
*/
public static <T> Function<T> ctor(Class<T> c)
throws IllegalArgumentException{
return ctor(c, false);
}
/**
* Create a Function object that uses the constructor of a class.
* This class should have one and only one visible constructor.
* <br>
* Array type is given a special constructor so that the constructor of
* array type T has one parameter of type int
* and calls new T[size] when invoked.
* @param c the class.
* @param suppress_security whether access to non-public members is allowed.
* @return the Function object.
* @throws IllegalArgumentException
* if the class has no public constructor
* or has more than one public constructor.
*/
public static <T> Function<T> ctor(Class<T> c, boolean suppress_security)
throws IllegalArgumentException{
if(c.isArray()){
return new ArrayConstructorFunction<T>(c);
}
else{
final Constructor<T> ctor = ReflectionUtil.getConstructor(c, suppress_security);
return ctor(ctor);
}
}
/**
* Create a Function object that uses one public constructor of a class.
* The constructor to invoke is determined by the parameter types specified.
* <br>
* Array type is given a special constructor so that the constructor of
* array type T has one parameter of type int
* and calls new T[size] when invoked.
* @param c the class.
* @param param_types the parameter types of the constructor to use.
* null indicates the default constructor.
* @return the Function object.
* @throws IllegalArgumentException
* if the public constructor cannot be found.
*/
public static <T> Function<T> ctor(Class<T> c, Class[] param_types){
return ctor(c, param_types, false);
}
/**
* Create a Function object that uses one constructor of a class.
* The constructor to invoke is determined by the parameter types specified.
* <br>
* Array type is given a special constructor so that the constructor of
* array type T has one parameter of type int
* and calls new T[size] when invoked.
* @param c the class.
* @param param_types the parameter types of the constructor to use.
* @param suppress_security whether access to non-public member is allowed.
* null indicates the default constructor.
* @return the Function object.
* @throws IllegalArgumentException
* if the public constructor cannot be found.
*/
public static <T> Function<T> ctor(Class<T> c, Class[] param_types, boolean suppress_security)
throws IllegalArgumentException{
if(c.isArray() && param_types!=null &&
param_types.length==1 && int.class.equals(param_types[0])){
return new ArrayConstructorFunction<T>(c);
}
else{
final Constructor<T> ctor = ReflectionUtil.getConstructor(c, param_types,
suppress_security);
return ctor(ctor);
}
}
/**
* Create a Function object that invokes a public static method.
* This class should have one and only one public static method of this name.
* @param c the class where the static method belongs.
* @param name the static method name.
* @return the Component object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. this method is not static. <br>
* 3. more than one public static method with the specified name. <br>
* 4. no public static method with the specified name. <br>
* 5. the class is not public.<br>
*/
public static Function static_method(Class c, String name){
return static_method(c, name, false);
}
/**
* Create a Function object that invokes a static method.
* This class should have one and only one visible static method of this name.
* @param c the class where the static method belongs.
* @param name the static method name.
* @param suppress_security whether to look at non-public methods.
* @return the Component object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not visible. <br>
* 2. this method is not static. <br>
* 3. more than one visible static method with the specified name. <br>
* 4. no visible static method with the specified name. <br>
* 5. the class is not visible.<br>
*/
public static Function static_method(Class c, final String name, boolean suppress_security){
final Method mtd = ReflectionUtil.getStaticMethod(c, name, suppress_security);
return method(null, mtd);
}
/**
* Create a Function object that invokes a public static method.
* The static method to invoke is determined by the method name
* and the parameter types.
* @param c the class where the static method belongs.
* @param name the static method name.
* @param param_types the parameter types.
* null indicates a parameter-less method.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. this method is not static. <br>
* 3. no public static method with the specified name and the parameter types. <br>
* 4. the class is not public. <br>
*/
public static Function static_method(Class c, String name,
Class[] param_types){
return static_method(c, name, param_types, false);
}
/**
* Create a Function object that invokes a static method.
* The static method to invoke is determined by the method name
* and the parameter types.
* @param c the class where the static method belongs.
* @param name the static method name.
* @param param_types the parameter types.
* null indicates a parameter-less method.
* @param suppress_security whether to look at non-public methods.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not visible. <br>
* 2. this method is not static. <br>
* 3. no visible static method with the specified name and the parameter types. <br>
* 4. the class is not visible.<br>
*/
public static Function static_method(Class c, String name,
Class[] param_types, boolean suppress_security)
throws IllegalArgumentException{
final Method mtd = ReflectionUtil.getMethod(c, name, param_types, suppress_security);
return static_method(mtd);
}
/**
* Create a Function object that invokes a static method.
* The static method to invoke is determined by the method name
* and the parameter types.
* @param mtd the method.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if this method is not static. <br>
*/
public static Function static_method(Method mtd){
if(!Modifier.isStatic(mtd.getModifiers())){
throw new IllegalArgumentException(""+mtd
+ " is not static");
}
return method(null, mtd);
}
/**
* Create a Function object that invokes a public instance method.
* This class should have one and only one public instance method of this name.
* <br>
* The first parameter of this Function will be the object to
* invoke the method against.
* @param c the class where the instance method belongs.
* @param name the instance method name.
* @return the Component object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. this method is static. <br>
* 3. more than one public instance method with the specified name. <br>
* 4. no public instance method with the specified name. <br>
* 5. the class is not public. <br>
*/
public static Function instance_method(Class c, String name){
return instance_method(c, name, false);
}
/**
* Create a Function object that invokes an instance method.
* This class should have one and only one visible instance method of this name.
* <br>
* The first parameter of this Function will be the object to
* invoke the method against.
* @param c the class where the instance method belongs.
* @param name the instance method name.
* @param suppress_security whether to look at non-public methods.
* @return the Component object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not visible. <br>
* 2. this method is static. <br>
* 3. more than one visible instance method with the specified name. <br>
* 4. no visible instance method with the specified name. <br>
* 5. the class is not visible. <br>
*/
public static Function instance_method(Class c, String name,
boolean suppress_security)
throws IllegalArgumentException{
final Method mtd = ReflectionUtil.getInstanceMethod(c, name,
suppress_security);
return instance_method(c, mtd);
}
/**
* Create a Function object that invokes a public instance method.
* The instance method to invoke is determined by the method name
* and the parameter types.
* <br>
* The first parameter of this Function will be the object to
* invoke the method against.
* @param c the class where the instance method belongs.
* @param name the method name.
* @param param_types the parameter types.
* null indicates a parameter-less method.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. this method is static. <br>
* 3. no public instance method with the specified name and the parameter types. <br>
*/
public static Function instance_method(Class c, String name,
Class[] param_types){
return instance_method(c, name, param_types, false);
}
/**
* Create a Function object that invokes an instance method.
* The instance method to invoke is determined by the method name
* and the parameter types.
* <br>
* The first parameter of this Function will be the object to
* invoke the method against.
* @param c the class where the instance method belongs.
* @param name the method name.
* @param param_types the parameter types.
* @param suppress_security whether to look at non-public ones.
* null indicates a parameter-less method.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not visible. <br>
* 2. this method is static. <br>
* 3. no visible instance method with the specified name and the parameter types. <br>
* 4. the class is not visible.<br>
*/
public static Function instance_method(Class c, String name,
Class[] param_types, boolean suppress_security)
throws IllegalArgumentException{
final Method mtd = ReflectionUtil.getMethod(c, name, param_types,
suppress_security);
return instance_method(c, mtd);
}
/**
* Create a Function object that invokes an instance method.
* <br>
* The first parameter of this Function will be the object to
* invoke the method against.
* @param c the class where the instance method belongs.
* @param mtd the method.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if this method is static. <br>
*/
public static Function instance_method(Class c, Method mtd){
if(Modifier.isStatic(mtd.getModifiers())){
throw new IllegalArgumentException(""+mtd
+" is static");
}
return new FloatingMethodFunction(c, mtd);
}
/**
* Create a Function object that invokes a public method against a given object.
* The class of the object
* should be public and have one and only one public method of this name.
* @param obj the object to run the method against. It cannot be null.
* @param name the method name.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. more than one public method with the specified name. <br>
* 3. no public method with the specified name. <br>
*/
public static Function method(Object obj, String name){
return method(obj, name, false);
}
/**
* Create a Function object that invokes a method against a given object.
* The class of the object
* should have one and only one visible method of this name.
* @param obj the object to run the method against. It cannot be null.
* @param name the method name.
* @param suppress_security whether to look at non-public ones.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not visible. <br>
* 2. more than one public method with the specified name. <br>
* 3. no visible method with the specified name. <br>
*/
public static Function method(Object obj, final String name,
boolean suppress_security){
return method(obj.getClass(), obj, name, suppress_security);
}
/**
* Create a Function object that invokes a public method against a given object.
* The class of the object
* should have one and only one public method of this name.
* @param type the Class object to look up method.
* This parameter can be used when we only want to look up in
* a super type rather than obj.getClass().
* @param obj the object to run the method against.
* @param name the method name.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. more than one public method with the specified name. <br>
* 3. no public method with the specified name. <br>
*/
public static Function method(Class type, Object obj, String name){
return method(type, obj, name, false);
}
/**
* Create a Function object that invokes a method against a given object.
* The class of the object
* should have one and only one visible method of this name.
* @param type the Class object to look up method.
* This parameter can be used when we only want to look up in
* a super type rather than obj.getClass().
* @param obj the object to run the method against.
* @param name the method name.
* @param suppress_security whether to look at non-public ones.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. more than one public method with the specified name. <br>
* 3. no public method with the specified name. <br>
*/
public static Function method(Class type, Object obj, final String name,
boolean suppress_security){
final Method mtd = ReflectionUtil.getMethod(type, name,
suppress_security);
return method(obj, mtd);
}
/**
* Create a Function object that invokes a public method against a given object.
* The method to invoke is determined by the method name
* and the parameter types.
* @param obj the object to run the method against. It cannot be null.
* @param name the method name.
* @param param_types the parameter types.
* null indicates a parameter-less method.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. no public method with the specified name and the parameter types. <br>
*/
public static Function method(Object obj, String name, Class[] param_types){
return method(obj, name, param_types, false);
}
/**
* Create a Function object that invokes a method against a given object.
* The method to invoke is determined by the method name
* and the parameter types.
* @param obj the object to run the method against. It cannot be null.
* @param name the method name.
* @param param_types the parameter types.
* @param suppress_security whether to look at non-public ones.
* null indicates a parameter-less method.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not visible. <br>
* 2. no visible method with the specified name and the parameter types. <br>
*/
public static Function method(Object obj,
String name, Class[] param_types, boolean suppress_security){
return method(obj.getClass(), obj, name, param_types,
suppress_security);
}
/**
* Create a Function object that invokes a public method against a given object.
* The method to invoke is determined by the method name
* and the parameter types.
* @param type the Class object to look up method.
* This parameter can be used when we only want to look up in
* a super type rather than obj.getClass().
* @param obj the object to run the method against. It cannot be null.
* @param name the method name.
* @param param_types the parameter types.
* null indicates a parameter-less method.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not public. <br>
* 2. no public method with the specified name and the parameter types. <br>
*/
public static Function method(Class type, Object obj,
String name, Class[] param_types){
return method(type, obj, name, param_types, false);
}
/**
* Create a Function object that invokes a method against a given object.
* The method to invoke is determined by the method name
* and the parameter types.
* @param type the Class object to look up method.
* This parameter can be used when we only want to look up in
* a super type rather than obj.getClass().
* @param obj the object to run the method against. It cannot be null.
* @param name the method name.
* @param param_types the parameter types.
* null indicates a parameter-less method.
* @param suppress_security whether to look at non-public ones.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. this method is not visible. <br>
* 2. no visible method with the specified name and the parameter types. <br>
*/
public static Function method(Class type, Object obj,
String name, Class[] param_types, boolean suppress_security){
final Method mtd = ReflectionUtil.getMethod(
type, name, param_types, suppress_security);
return method(obj, mtd);
}
/**
* Creates a Function object that invokes a property getter.
* @param bean the bean object.
* @param name the property name.
* @return the Function object.
*/
public static Function getter(Bean bean, String name){
if(bean.getBeanType().getReader(name) == null)
throw new IllegalArgumentException("property getter for "+
bean.getBeanType().getType().getName()+"."+name+" not found.");
return new PropertyReader(bean, name);
}
/**
* Creates a Function object that invokes an indexed property getter.
* @param bean the bean object.
* @param name the property name.
* @param ind the index.
* @return the Function object.
*/
public static Function indexed_getter(Bean bean, String name, int ind){
if(bean.getBeanType().getIndexedReader(name) == null)
throw new IllegalArgumentException("indexed property getter for "
+bean.getBeanType().getType().getName()+"."+name+" not found.");
return new IndexedPropertyReader(bean, name, ind);
}
/**
* Creates a Function object that invokes a property setter.
* @param bean the bean object.
* @param name the property name.
* @return the Function object.
*/
public static Function setter(Bean bean, String name){
final BeanType btype = bean.getBeanType();
if(btype.getWriter(name) == null
&& btype.getIndexedWriter(name)==null){
throw new IllegalArgumentException("property setter for "+
bean.getBeanType().getType().getName()+"."+name+" not found.");
}
else
return new PropertyWriter(bean, name);
}
/**
* Creates a Function object that invokes an indexed property setter.
* @param bean the bean object.
* @param name the property name.
* @param ind the index.
* @return the Function object.
*/
public static Function indexed_setter(Bean bean, String name, int ind){
if(bean.getBeanType().getIndexedWriter(name) == null)
throw new IllegalArgumentException("indexed property setter for "+
bean.getBeanType().getType().getName()+"."+name+" not found.");
return new IndexedPropertyWriter(bean, name, ind);
}
/**
* Create a Function object that reads a public static field.
* @param c the class where the static field belongs.
* @param name the static field name.
* @return the Component object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. field is not found. <br>
* 2. field is not static. <br>
* 3. field is not public. <br>
*/
public static Function static_field(Class c, String name){
return static_field(c, name, false);
}
/**
* Create a Function object that reads a static field.
* @param c the class where the static field belongs.
* @param name the static field name.
* @return the Component object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. field is not found. <br>
* 2. field is not static.
*/
public static Function static_field(Class c, final String name,
boolean suppress_security){
final Field fld = ReflectionUtil.getStaticField(c, name,
suppress_security);
return field(null, fld);
}
/**
* Create a Function object that reads a static field.
* The static field to read is determined by the field name
* and the parameter types.
* @param fld the field.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if this field is not static. <br>
*/
public static Function static_field(Field fld){
if(!Modifier.isStatic(fld.getModifiers())){
throw new IllegalArgumentException(""+fld
+ " is not static");
}
return field(null, fld);
}
/**
* Create a Function object that reads a public instance field.
* <br>
* The first parameter of this Function will be the object to
* read the field from.
* @param c the class where the instance field belongs.
* @param name the instance field name.
* @return the Component object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. field is not found. <br>
* 2. this field is static. <br>
* 3. the field is not public. <br>
*/
public static Function instance_field(Class c, String name){
return instance_field(c, name, false);
}
/**
* Create a Function object that reads an instance field.
* <br>
* The first parameter of this Function will be the object to
* read the field from.
* @param c the class where the instance field belongs.
* @param name the instance field name.
* @param suppress_security whether to look at non-public ones.
* @return the Component object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. field is not found. <br>
* 2. this field is static. <br>
*/
public static Function instance_field(Class c, String name,
boolean suppress_security)
throws IllegalArgumentException{
final Field fld = ReflectionUtil.getInstanceField(c, name,
suppress_security);
return instance_field(c, fld);
}
/**
* Create a Function object that reads an instance field.
* <br>
* The first parameter of this Function will be the object to
* read the field from.
* @param c the class where the instance field belongs.
* @param fld the field.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if this field is static. <br>
*/
public static Function instance_field(Class c, Field fld){
if(Modifier.isStatic(fld.getModifiers())){
throw new IllegalArgumentException(""+fld
+" is static");
}
return new FloatingFieldFunction(c, fld);
}
/**
* Create a Function object that reads a public field from a given object.
* @param obj the object to read the field from. It cannot be null.
* @param name the field name.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. field is not found.<br>
* 2. field is not public.<br>
*/
public static Function field(Object obj, String name){
return field(obj, name, false);
}
/**
* Create a Function object that reads a field from a given object.
* @param obj the object to read the field from. It cannot be null.
* @param name the field name.
* @param suppress_security whether to look at non-public ones.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. field is not found.
*/
public static Function field(Object obj, final String name,
boolean suppress_security){
return field(obj.getClass(), obj, name, suppress_security);
}
/**
* Create a Function object that reads a public field from a given object.
* @param type the Class object to look up field.
* This parameter can be used when we only want to look up in
* a super type rather than obj.getClass().
* @param obj the object to read field from.
* @param name the field name.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. field is not found. <br>
* 2. field is not public. <br>
*/
public static Function field(Class type, Object obj, String name){
return field(type, obj, name, false);
}
/**
* Create a Function object that reads a field from a given object.
* @param type the Class object to look up field.
* This parameter can be used when we only want to look up in
* a super type rather than obj.getClass().
* @param obj the object to read field from.
* @param name the field name.
* @param suppress_security whether to look at non-public ones.
* @return the Function object.
* @throws IllegalArgumentException
* thrown if any of the following conditions is true: <br>
* 1. field is not found. <br>
*/
public static Function field(Class type, Object obj, final String name,
boolean suppress_security){
final Field fld = ReflectionUtil.getField(type, name, suppress_security);
return field(obj, fld);
}
/**
* Adapts a {@link java.lang.reflect.Field} object and the receiver object
* to a Function object.
* @param obj the receiver object to read the field from.
* If the field is static, the object can be null.
* @param fld the field object.
* @return the Function object.
*/
public static Function field(Object obj, Field fld){
return new FieldFunction(canonicalize(obj, fld), fld);
}
}