package org.etk.reflect.jlr.metadata;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.etk.reflect.api.definition.ClassKind;
import org.etk.reflect.api.definition.LiteralKind;
import org.etk.reflect.api.definition.TypeKind;
import org.etk.reflect.api.metadata.GenericDeclarationKind;
import org.etk.reflect.api.metadata.TypeMetadata;
public class JLReflectionTypeMetadata implements TypeMetadata<Type> {
private static final Map<Class<?>, LiteralKind> primitiveMap = new HashMap<Class<?>, LiteralKind>();
{
primitiveMap.put(Boolean.class, LiteralKind.BOOLEAN);
primitiveMap.put(boolean.class, LiteralKind.BOOLEAN);
primitiveMap.put(Byte.class, LiteralKind.BYTE);
primitiveMap.put(byte.class, LiteralKind.BYTE);
primitiveMap.put(Short.class, LiteralKind.SHORT);
primitiveMap.put(short.class, LiteralKind.SHORT);
primitiveMap.put(Integer.class, LiteralKind.INT);
primitiveMap.put(int.class, LiteralKind.INT);
primitiveMap.put(Long.class, LiteralKind.LONG);
primitiveMap.put(long.class, LiteralKind.LONG);
primitiveMap.put(Float.class, LiteralKind.FLOAT);
primitiveMap.put(float.class, LiteralKind.FLOAT);
primitiveMap.put(Double.class, LiteralKind.DOUBLE);
primitiveMap.put(double.class, LiteralKind.DOUBLE);
}
public TypeKind getKind(Type type) {
if (type instanceof Class) {
Class classType = (Class)type;
if (classType.isArray()) {
return TypeKind.ARRAY;
} else {
if (classType.isPrimitive()) {
if (classType == void.class) {
return TypeKind.VOID;
} else {
return TypeKind.SIMPLE;
}
} else if (
classType == Boolean.class ||
classType == Float.class ||
classType == Byte.class ||
classType == Short.class ||
classType == Integer.class ||
classType == Long.class ||
classType == Double.class) {
return TypeKind.SIMPLE;
} else if (classType == Void.class) {
return TypeKind.VOID;
} else {
return TypeKind.CLASS;
}
}
} else if (type instanceof ParameterizedType) {
return TypeKind.PARAMETERIZED;
} else if (type instanceof TypeVariable) {
return TypeKind.VARIABLE;
} else if (type instanceof WildcardType) {
return TypeKind.WILDCARD;
} else if (type instanceof GenericArrayType) {
return TypeKind.ARRAY;
} else {
throw new AssertionError();
}
}
public LiteralKind getLiteralType(Type simpleType) {
Class classType = (Class)simpleType;
return primitiveMap.get(classType);
}
public Type getComponentType(Type arrayType) {
if (arrayType instanceof Class) {
return ((Class)arrayType).getComponentType();
} else {
return ((GenericArrayType)arrayType).getGenericComponentType();
}
}
public boolean isPrimitive(Type simpleType) {
Class classType = (Class)simpleType;
return classType.isPrimitive();
}
public Type getEnclosing(Type classType) {
return ((Class<?>)classType).getEnclosingClass();
}
public String getClassName(Type classType) {
return ((Class<?>)classType).getName();
}
public ClassKind getClassKind(Type classType) {
Class tmp = (Class)classType;
if (tmp.isAnnotation()) {
return ClassKind.ANNOTATION;
} else if (tmp.isEnum()) {
return ClassKind.ENUM;
} else if (tmp.isInterface()) {
return ClassKind.INTERFACE;
} else {
return ClassKind.CLASS;
}
}
public Iterable<Type> getInterfaces(Type classType) {
return Arrays.asList(((Class<?>)classType).getGenericInterfaces());
}
public Type getSuperClass(Type classType) {
return ((Class<?>)classType).getGenericSuperclass();
}
public Iterable<Type> getTypeParameters(Type classType) {
ArrayList<Type> typeParameters = new ArrayList<Type>();
for (TypeVariable typeParameter : ((Class)classType).getTypeParameters()) {
typeParameters.add(typeParameter);
}
return typeParameters;
}
public Type getGenericDeclaration(Type typeVariable) {
return (Type)((TypeVariable)typeVariable).getGenericDeclaration();
}
public GenericDeclarationKind getGenericDeclarationKind(Type typeVariable) {
GenericDeclaration genDecl = ((TypeVariable)typeVariable).getGenericDeclaration();
if (genDecl instanceof Type) {
return GenericDeclarationKind.TYPE;
} else if (genDecl instanceof Method) {
return GenericDeclarationKind.METHOD;
} else {
throw new UnsupportedOperationException("Not yet implemented");
}
}
public String getName(Type typeVariable) {
return ((TypeVariable)typeVariable).getName();
}
public Iterable<Type> getBounds(Type typeVariable) {
return Arrays.asList(((TypeVariable)typeVariable).getBounds());
}
public Type getRawType(Type parameterizedType) {
return ((ParameterizedType)parameterizedType).getRawType();
}
public Iterable<Type> getTypeArguments(Type parameterizedType) {
return Arrays.asList(((ParameterizedType)parameterizedType).getActualTypeArguments());
}
public Iterable<Type> getUpperBounds(Type wildcardType) {
Type[] upperBounds = ((WildcardType)wildcardType).getUpperBounds();
return Arrays.asList(upperBounds);
}
public Iterable<Type> getLowerBounds(Type wildcardType) {
return Arrays.asList(((WildcardType)wildcardType).getLowerBounds());
}
}