package openmods.reflection;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.reflect.TypeToken;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class TypeUtils {
public static final TypeToken<?> MAP_TOKEN = TypeToken.of(Map.class);
public static final TypeToken<?> SET_TOKEN = TypeToken.of(Set.class);
public static final TypeToken<?> COLLECTION_TOKEN = TypeToken.of(Collection.class);
public static final TypeToken<?> LIST_TOKEN = TypeToken.of(List.class);
public static final TypeToken<?> FUNCTION_TOKEN = TypeToken.of(Function.class);
public static final TypeVariable<?> LIST_VALUE_PARAM;
static {
LIST_VALUE_PARAM = List.class.getTypeParameters()[0];
}
public static final TypeVariable<?> MAP_KEY_PARAM;
public static final TypeVariable<?> MAP_VALUE_PARAM;
static {
TypeVariable<?>[] vars = Map.class.getTypeParameters();
MAP_KEY_PARAM = vars[0];
MAP_VALUE_PARAM = vars[1];
}
public static final TypeVariable<?> SET_VALUE_PARAM;
static {
SET_VALUE_PARAM = Set.class.getTypeParameters()[0];
}
public static final TypeVariable<?> COLLECTION_VALUE_PARAM;
static {
COLLECTION_VALUE_PARAM = Collection.class.getTypeParameters()[0];
}
public static final TypeVariable<?> FUNCTION_A_PARAM;
public static final TypeVariable<?> FUNCTION_B_PARAM;
static {
TypeVariable<?>[] vars = Function.class.getTypeParameters();
FUNCTION_A_PARAM = vars[0];
FUNCTION_B_PARAM = vars[1];
}
public static final BiMap<Class<?>, Class<?>> PRIMITIVE_TYPES_MAP = ImmutableBiMap.<Class<?>, Class<?>> builder()
.put(boolean.class, Boolean.class)
.put(byte.class, Byte.class)
.put(char.class, Character.class)
.put(short.class, Short.class)
.put(int.class, Integer.class)
.put(long.class, Long.class)
.put(float.class, Float.class)
.put(double.class, Double.class)
.put(void.class, Void.class)
.build();
public static Class<?> toObjectType(Class<?> cls) {
return cls.isPrimitive()? PRIMITIVE_TYPES_MAP.get(cls) : cls;
}
public static void isInstance(Object o, Class<?> mainCls, Class<?>... extraCls) {
Preconditions.checkArgument(mainCls.isInstance(o), "%s is not instance of %s", o, mainCls);
for (Class<?> cls : extraCls)
Preconditions.checkArgument(cls.isInstance(o), "%s is not instance of %s", o, cls);
}
public static boolean compareTypes(Class<?> left, Class<?> right) {
if (left.isPrimitive()) left = PRIMITIVE_TYPES_MAP.get(left);
if (right.isPrimitive()) right = PRIMITIVE_TYPES_MAP.get(right);
return left.equals(right);
}
public static TypeToken<?> getTypeParameter(Class<?> intfClass, Class<?> instanceClass, int index) {
final TypeVariable<?>[] typeParameters = intfClass.getTypeParameters();
Preconditions.checkElementIndex(index, typeParameters.length, intfClass + " type parameter index");
TypeVariable<?> arg = typeParameters[index];
TypeToken<?> type = TypeToken.of(instanceClass);
Preconditions.checkArgument(type.getRawType() != Object.class, "Type %s is no fully parametrized", instanceClass);
return type.resolveType(arg);
}
public static TypeToken<?> getTypeParameter(Class<?> intfClass, Class<?> instanceClass) {
return getTypeParameter(intfClass, instanceClass, 0);
}
public static TypeToken<?> resolveFieldType(Class<?> cls, Field field) {
Type fieldType = field.getGenericType();
TypeToken<?> parentType = TypeToken.of(cls);
return parentType.resolveType(fieldType);
}
}