class TypeUtils {

	public static Type getErasedType(Type type)
	{
		// the erasure of a parameterized type G<T1, ... ,Tn> is |G|
		if (type instanceof ParameterizedType)
		{
			Type rawType = ((ParameterizedType) type).getRawType();
			
			return getErasedType(rawType);
		}
		
		// TODO: the erasure of a nested type T.C is |T|.C
		
		// the erasure of an array type T[] is |T|[]
		if (isArray(type))
		{
			Type componentType = getComponentType(type);
			Type erasedComponentType = getErasedType(componentType);
			
			return getArrayType(erasedComponentType);
		}
		
		// the erasure of a type variable is the erasure of its leftmost bound 
		if (type instanceof TypeVariable<?>)
		{
			Type[] bounds = ((TypeVariable<?>) type).getBounds();
			
			return getErasedType(bounds[0]);
		}
		
		// the erasure of every other type is the type itself
		return type;
	}

	private  TypeUtils();

}