metaclasshelper.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 985 行 · 第 1/3 页
JAVA
985 行
Class clazz = parameters[i];
if (clazz.isPrimitive()) {
objectDistance+=2;
} else {
while (clazz!=Object.class) {
clazz = clazz.getSuperclass();
objectDistance+=2;
}
}
}
}
long ret = objectDistance;
ret <<= 32;
ret |= interfaceDistance;
return ret;
}
public static String capitalize(String property) {
return property.substring(0, 1).toUpperCase() + property.substring(1, property.length());
}
/**
* @return the method with 1 parameter which takes the most general type of
* object (e.g. Object)
*/
public static Object chooseEmptyMethodParams(List methods) {
for (Iterator iter = methods.iterator(); iter.hasNext();) {
Object method = iter.next();
Class[] paramTypes = getParameterTypes(method);
int paramLength = paramTypes.length;
if (paramLength == 0) {
return method;
}
}
return null;
}
/**
* @return the method with 1 parameter which takes the most general type of
* object (e.g. Object) ignoring primitve types
*/
public static Object chooseMostGeneralMethodWith1NullParam(List methods) {
// lets look for methods with 1 argument which matches the type of the
// arguments
Class closestClass = null;
Object answer = null;
for (Iterator iter = methods.iterator(); iter.hasNext();) {
Object method = iter.next();
Class[] paramTypes = getParameterTypes(method);
int paramLength = paramTypes.length;
if (paramLength == 1) {
Class theType = paramTypes[0];
if (theType.isPrimitive()) continue;
if (closestClass == null || isAssignableFrom(theType, closestClass)) {
closestClass = theType;
answer = method;
}
}
}
return answer;
}
/**
* Coerces a GString instance into String if needed
*
* @return the coerced argument
*/
protected static Object coerceGString(Object argument, Class clazz) {
if (clazz!=String.class) return argument;
if (!(argument instanceof GString)) return argument;
return argument.toString();
}
protected static Object coerceNumber(Object argument, Class param) {
if ((Number.class.isAssignableFrom(param) || param.isPrimitive()) && argument instanceof Number) { // Number types
Object oldArgument = argument;
boolean wasDouble = false;
boolean wasFloat = false;
if (param == Byte.class || param == Byte.TYPE ) {
argument = new Byte(((Number)argument).byteValue());
} else if (param == Double.class || param == Double.TYPE) {
wasDouble = true;
argument = new Double(((Number)argument).doubleValue());
} else if (param == Float.class || param == Float.TYPE) {
wasFloat = true;
argument = new Float(((Number)argument).floatValue());
} else if (param == Integer.class || param == Integer.TYPE) {
argument = new Integer(((Number)argument).intValue());
} else if (param == Long.class || param == Long.TYPE) {
argument = new Long(((Number)argument).longValue());
} else if (param == Short.class || param == Short.TYPE) {
argument = new Short(((Number)argument).shortValue());
} else if (param == BigDecimal.class ) {
argument = new BigDecimal(String.valueOf((Number)argument));
} else if (param == BigInteger.class) {
argument = new BigInteger(String.valueOf((Number)argument));
}
if (oldArgument instanceof BigDecimal) {
BigDecimal oldbd = (BigDecimal) oldArgument;
boolean throwException = false;
if (wasDouble) {
Double d = (Double) argument;
if (d.isInfinite()) throwException = true;
} else if (wasFloat) {
Float f = (Float) argument;
if (f.isInfinite()) throwException = true;
} else {
BigDecimal newbd = new BigDecimal(String.valueOf((Number)argument));
throwException = !oldArgument.equals(newbd);
}
if (throwException) throw new IllegalArgumentException(param+" out of range while converting from BigDecimal");
}
}
return argument;
}
protected static Object coerceArray(Object argument, Class param) {
if (!param.isArray()) return argument;
Class argumentClass = argument.getClass();
if (!argumentClass.isArray()) return argument;
Class paramComponent = param.getComponentType();
if (paramComponent.isPrimitive()) {
if (paramComponent == boolean.class && argumentClass==Boolean[].class) {
argument = DefaultTypeTransformation.convertToBooleanArray(argument);
} else if (paramComponent == byte.class && argumentClass==Byte[].class) {
argument = DefaultTypeTransformation.convertToByteArray(argument);
} else if (paramComponent == char.class && argumentClass==Character[].class) {
argument = DefaultTypeTransformation.convertToCharArray(argument);
} else if (paramComponent == short.class && argumentClass==Short[].class) {
argument = DefaultTypeTransformation.convertToShortArray(argument);
} else if (paramComponent == int.class && argumentClass==Integer[].class) {
argument = DefaultTypeTransformation.convertToIntArray(argument);
} else if (paramComponent == long.class &&
(argumentClass == Long[].class || argumentClass == Integer[].class))
{
argument = DefaultTypeTransformation.convertToLongArray(argument);
} else if (paramComponent == float.class &&
(argumentClass == Float[].class || argumentClass == Integer[].class))
{
argument = DefaultTypeTransformation.convertToFloatArray(argument);
} else if (paramComponent == double.class &&
(argumentClass == Double[].class || argumentClass==Float[].class
|| BigDecimal.class.isAssignableFrom(argumentClass)))
{
argument = DefaultTypeTransformation.convertToDoubleArray(argument);
}
} else if (paramComponent==String.class && argument instanceof GString[]) {
GString[] strings = (GString[]) argument;
String[] ret = new String[strings.length];
for (int i=0; i<strings.length; i++) {
ret[i] = strings[i].toString();
}
argument = ret;
}
return argument;
}
/**
* @return true if a method of the same matching prototype was found in the
* list
*/
public static boolean containsMatchingMethod(List list, MetaMethod method) {
for (Iterator iter = list.iterator(); iter.hasNext();) {
MetaMethod aMethod = (MetaMethod) iter.next();
Class[] params1 = aMethod.getParameterTypes();
Class[] params2 = method.getParameterTypes();
if (params1.length == params2.length) {
boolean matches = true;
for (int i = 0; i < params1.length; i++) {
if (params1[i] != params2[i]) {
matches = false;
break;
}
}
if (matches) {
return true;
}
}
}
return false;
}
/**
* param instance array to the type array
* @param args
*/
public static Class[] convertToTypeArray(Object[] args) {
if (args == null)
return null;
int s = args.length;
Class[] ans = new Class[s];
for (int i = 0; i < s; i++) {
Object o = args[i];
if (o == null) {
ans[i] = null;
} else if (o instanceof Wrapper) {
ans[i] = ((Wrapper) o).getType();
} else {
ans[i] = o.getClass();
}
}
return ans;
}
/**
* @param listenerType
* the interface of the listener to proxy
* @param listenerMethodName
* the name of the method in the listener API to call the
* closure on
* @param closure
* the closure to invoke on the listenerMethodName method
* invocation
* @return a dynamic proxy which calls the given closure on the given
* method name
*/
public static Object createListenerProxy(Class listenerType, final String listenerMethodName, final Closure closure) {
InvocationHandler handler = new ClosureListener(listenerMethodName, closure);
return Proxy.newProxyInstance(listenerType.getClassLoader(), new Class[] { listenerType }, handler);
}
public static Object doConstructorInvoke(Constructor constructor, Object[] argumentArray) {
if (log.isLoggable(Level.FINER)){
logMethodCall(constructor.getDeclaringClass(), constructor.getName(), argumentArray);
}
argumentArray = coerceArgumentsToClasses(argumentArray,constructor.getParameterTypes());
try {
return constructor.newInstance(argumentArray);
} catch (InvocationTargetException e) {
throw new InvokerInvocationException(e);
} catch (IllegalArgumentException e) {
throw createExceptionText("failed to invoke constructor: ", constructor, argumentArray, e, false);
} catch (IllegalAccessException e) {
throw createExceptionText("could not access constructor: ", constructor, argumentArray, e, false);
} catch (Exception e) {
throw createExceptionText("failed to invoke constructor: ", constructor, argumentArray, e, true);
}
}
private static GroovyRuntimeException createExceptionText(String init, Constructor constructor, Object[] argumentArray, Throwable e, boolean setReason) {
throw new GroovyRuntimeException(
init
+ constructor
+ " with arguments: "
+ InvokerHelper.toString(argumentArray)
+ " reason: "
+ e,
setReason?e:null);
}
public static Object[] coerceArgumentsToClasses(Object[] argumentArray, Class[] paramTypes) {
// correct argumentArray's length
if (argumentArray == null) {
argumentArray = EMPTY_ARRAY;
} else if (paramTypes.length == 1 && argumentArray.length == 0) {
if (isVargsMethod(paramTypes,argumentArray))
argumentArray = new Object[]{Array.newInstance(paramTypes[0].getComponentType(),0)};
else
argumentArray = ARRAY_WITH_NULL;
} else if (isVargsMethod(paramTypes,argumentArray)) {
argumentArray = fitToVargs(argumentArray, paramTypes);
}
//correct Type
for (int i=0; i<argumentArray.length; i++) {
Object argument = argumentArray[i];
if (argument==null) continue;
Class parameterType = paramTypes[i];
if (parameterType.isInstance(argument)) continue;
argument = coerceGString(argument,parameterType);
argument = coerceNumber(argument,parameterType);
argument = coerceArray(argument,parameterType);
argumentArray[i] = argument;
}
return argumentArray;
}
private static Object makeCommonArray(Object[] arguments, int offset, Class fallback) {
// arguments.leght>0 && !=null
Class baseClass = null;
for (int i = offset; i < arguments.length; i++) {
if (arguments[i]==null) continue;
Class argClass = arguments[i].getClass();
if (baseClass==null) {
baseClass = argClass;
} else {
for (;baseClass!=Object.class; baseClass=baseClass.getSuperclass()){
if (baseClass.isAssignableFrom(argClass)) break;
}
}
}
if (baseClass==null) {
// all arguments were null
baseClass = fallback;
}
Object result = makeArray(null,baseClass,arguments.length-offset);
System.arraycopy(arguments,offset,result,0,arguments.length-offset);
return result;
}
private static Object makeArray(Object obj, Class secondary, int length) {
Class baseClass = secondary;
if (obj!=null) {
baseClass = obj.getClass();
}
/*if (GString.class.isAssignableFrom(baseClass)) {
baseClass = GString.class;
}*/
return Array.newInstance(baseClass,length);
}
/**
* this method is called when the number of arguments to a method is greater than 1
* and if the method is a vargs method. This method will then transform the given
* arguments to make the method callable
*
* @param argumentArray the arguments used to call the method
* @param paramTypes the types of the paramters the method takes
*/
private static Object[] fitToVargs(Object[] argumentArray, Class[] paramTypes) {
Class vargsClass = autoboxType(paramTypes[paramTypes.length-1].getComponentType());
if (argumentArray.length == paramTypes.length-1) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?