package eu.stratosphere.util.reflect;
import java.lang.reflect.Array;
/**
* Signature with a number of fixed arguments followed by a variable number of arguments of a specific type.
*
* @author Arvid Heise
*/
public class VarArgSignature extends Signature {
/**
*
*/
private static final long serialVersionUID = -3584806055121932031L;
/**
* Initializes VarArgSignature with the given argument types. In an actual invocation of the associated method, the
* may occur 0 to n instances of the last parameter type.
*
* @param parameterTypes
* the parameter types
*/
public VarArgSignature(final Class<?>[] parameterTypes) {
super(parameterTypes);
}
@Override
public int getDistance(final Signature actualSignature) {
final Class<?>[] actualParamTypes = actualSignature.getParameterTypes();
final int nonVarArgs = this.getParameterTypes().length - 1;
if (nonVarArgs > actualParamTypes.length)
return INCOMPATIBLE;
int distance = 0;
for (int index = 0; index < nonVarArgs; index++) {
final int actualDistance =
ReflectUtil.getDistance(this.getParameterTypes()[index], actualParamTypes[index]);
if (actualDistance < 0)
return INCOMPATIBLE;
distance += actualDistance;
}
if (nonVarArgs < actualParamTypes.length)
if (actualParamTypes.length > nonVarArgs + 1
|| !this.getParameterTypes()[nonVarArgs].isAssignableFrom(actualParamTypes[nonVarArgs])) {
final Class<?> varargType = this.getParameterTypes()[nonVarArgs].getComponentType();
for (int index = nonVarArgs; index < actualParamTypes.length; index++) {
final int actualDistance = ReflectUtil.getDistance(varargType, actualParamTypes[index]);
if (actualDistance < 0)
return INCOMPATIBLE;
distance += actualDistance + 1;
}
}
return distance;
}
@Override
public Object[] adjustParameters(final Object[] params) {
final Class<?>[] parameterTypes = this.getParameterTypes();
final int varArgIndex = parameterTypes.length - 1;
final int varArgCount = params.length - varArgIndex;
if (varArgCount == 1 && parameterTypes[varArgIndex].isInstance(params[varArgIndex]))
return params;
final Object vararg = Array.newInstance(parameterTypes[varArgIndex].getComponentType(), varArgCount);
for (int index = 0; index < varArgCount; index++)
Array.set(vararg, index, params[varArgIndex + index]);
final Object[] actualParams = new Object[parameterTypes.length];
System.arraycopy(params, 0, actualParams, 0, varArgIndex);
actualParams[varArgIndex] = vararg;
return actualParams;
}
}