/*
* Copyright (c) 2006-2012 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.util;
import java.lang.reflect.*;
import java.util.*;
public final class ParameterReflection
{
static final Class<?>[] NO_PARAMETERS = new Class<?>[0];
static String getParameterTypesDescription(Type[] paramTypes)
{
String paramTypesDesc = Arrays.asList(paramTypes).toString();
return paramTypesDesc.replace("class ", "").replace('[', '(').replace(']', ')');
}
public static Class<?>[] getArgumentTypesFromArgumentValues(Object... args)
{
if (args.length == 0) {
return NO_PARAMETERS;
}
Class<?>[] argTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = getArgumentTypeFromArgumentValue(i, args);
}
return argTypes;
}
private static Class<?> getArgumentTypeFromArgumentValue(int i, Object[] args)
{
Object arg = args[i];
if (arg == null) {
throw new IllegalArgumentException("Invalid null value passed as argument " + i);
}
Class<?> argType;
if (arg instanceof Class<?>) {
argType = (Class<?>) arg;
args[i] = null;
}
else {
argType = GeneratedClasses.getMockedClass(arg);
}
return argType;
}
public static Object[] argumentsWithExtraFirstValue(Object[] args, Object firstValue)
{
Object[] args2 = new Object[1 + args.length];
args2[0] = firstValue;
System.arraycopy(args, 0, args2, 1, args.length);
return args2;
}
static boolean hasMoreSpecificTypes(Class<?>[] currentTypes, Class<?>[] previousTypes)
{
for (int i = 0; i < currentTypes.length; i++) {
Class<?> current = wrappedIfPrimitive(currentTypes[i]);
Class<?> previous = wrappedIfPrimitive(previousTypes[i]);
if (current != previous && previous.isAssignableFrom(current)) {
return true;
}
}
return false;
}
private static Class<?> wrappedIfPrimitive(Class<?> parameterType)
{
return parameterType.isPrimitive() ? AutoBoxing.getWrapperType(parameterType) : parameterType;
}
static boolean acceptsArgumentTypes(Class<?>[] paramTypes, Class<?>[] argTypes, int firstParameter)
{
for (int i = firstParameter; i < paramTypes.length; i++) {
Class<?> parType = paramTypes[i];
Class<?> argType = argTypes[i - firstParameter];
if (isSameTypeIgnoringAutoBoxing(parType, argType) || parType.isAssignableFrom(argType)) {
// OK, move to next parameter.
}
else {
return false;
}
}
return true;
}
static boolean isSameTypeIgnoringAutoBoxing(Class<?> firstType, Class<?> secondType)
{
return
firstType == secondType ||
firstType.isPrimitive() && isWrapperOfPrimitiveType(firstType, secondType) ||
secondType.isPrimitive() && isWrapperOfPrimitiveType(secondType, firstType);
}
private static boolean isWrapperOfPrimitiveType(Class<?> primitiveType, Class<?> otherType)
{
return primitiveType == AutoBoxing.getPrimitiveType(otherType);
}
static int indexOfFirstRealParameter(Class<?>[] mockParameterTypes, Class<?>[] realParameterTypes)
{
int extraParameters = mockParameterTypes.length - realParameterTypes.length;
if (extraParameters == 1) {
//noinspection UnnecessaryFullyQualifiedName
return mockParameterTypes[0] == mockit.Invocation.class ? 1 : -1;
}
else if (extraParameters != 0) {
return -1;
}
return 0;
}
static boolean matchesParameterTypes(Class<?>[] declaredTypes, Class<?>[] specifiedTypes, int firstParameter)
{
for (int i = firstParameter; i < declaredTypes.length; i++) {
Class<?> declaredType = declaredTypes[i];
Class<?> specifiedType = specifiedTypes[i - firstParameter];
if (isSameTypeIgnoringAutoBoxing(declaredType, specifiedType)) {
// OK, move to next parameter.
}
else {
return false;
}
}
return true;
}
}