|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.reflect.annotation; |
|
|
|
import java.lang.annotation.*; |
|
import java.lang.reflect.*; |
|
import java.util.ArrayList; |
|
import java.util.Arrays; |
|
import java.util.List; |
|
import java.util.Map; |
|
|
|
import static sun.reflect.annotation.TypeAnnotation.*; |
|
|
|
public final class AnnotatedTypeFactory { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static AnnotatedType buildAnnotatedType(Type type, |
|
LocationInfo currentLoc, |
|
TypeAnnotation[] actualTypeAnnos, |
|
TypeAnnotation[] allOnSameTarget, |
|
AnnotatedElement decl) { |
|
if (type == null) { |
|
return EMPTY_ANNOTATED_TYPE; |
|
} |
|
if (isArray(type)) |
|
return new AnnotatedArrayTypeImpl(type, |
|
currentLoc, |
|
actualTypeAnnos, |
|
allOnSameTarget, |
|
decl); |
|
if (type instanceof Class) { |
|
return new AnnotatedTypeBaseImpl(type, |
|
addNesting(type, currentLoc), |
|
actualTypeAnnos, |
|
allOnSameTarget, |
|
decl); |
|
} else if (type instanceof TypeVariable) { |
|
return new AnnotatedTypeVariableImpl((TypeVariable)type, |
|
currentLoc, |
|
actualTypeAnnos, |
|
allOnSameTarget, |
|
decl); |
|
} else if (type instanceof ParameterizedType) { |
|
return new AnnotatedParameterizedTypeImpl((ParameterizedType)type, |
|
addNesting(type, currentLoc), |
|
actualTypeAnnos, |
|
allOnSameTarget, |
|
decl); |
|
} else if (type instanceof WildcardType) { |
|
return new AnnotatedWildcardTypeImpl((WildcardType) type, |
|
currentLoc, |
|
actualTypeAnnos, |
|
allOnSameTarget, |
|
decl); |
|
} |
|
throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen."); |
|
} |
|
|
|
private static LocationInfo addNesting(Type type, LocationInfo addTo) { |
|
if (isArray(type)) |
|
return addTo; |
|
if (type instanceof Class) { |
|
Class<?> clz = (Class)type; |
|
if (clz.getEnclosingClass() == null) |
|
return addTo; |
|
if (Modifier.isStatic(clz.getModifiers())) |
|
return addNesting(clz.getEnclosingClass(), addTo); |
|
return addNesting(clz.getEnclosingClass(), addTo.pushInner()); |
|
} else if (type instanceof ParameterizedType) { |
|
ParameterizedType t = (ParameterizedType)type; |
|
if (t.getOwnerType() == null) |
|
return addTo; |
|
return addNesting(t.getOwnerType(), addTo.pushInner()); |
|
} |
|
return addTo; |
|
} |
|
|
|
private static boolean isArray(Type t) { |
|
if (t instanceof Class) { |
|
Class<?> c = (Class)t; |
|
if (c.isArray()) |
|
return true; |
|
} else if (t instanceof GenericArrayType) { |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION, |
|
new TypeAnnotation[0], new TypeAnnotation[0], null); |
|
static final AnnotatedType[] EMPTY_ANNOTATED_TYPE_ARRAY = new AnnotatedType[0]; |
|
|
|
private static class AnnotatedTypeBaseImpl implements AnnotatedType { |
|
private final Type type; |
|
private final AnnotatedElement decl; |
|
private final LocationInfo location; |
|
private final TypeAnnotation[] allOnSameTargetTypeAnnotations; |
|
private final Map<Class <? extends Annotation>, Annotation> annotations; |
|
|
|
AnnotatedTypeBaseImpl(Type type, LocationInfo location, |
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, |
|
AnnotatedElement decl) { |
|
this.type = type; |
|
this.decl = decl; |
|
this.location = location; |
|
this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations; |
|
this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations)); |
|
} |
|
|
|
|
|
@Override |
|
public final Annotation[] getAnnotations() { |
|
return getDeclaredAnnotations(); |
|
} |
|
|
|
@Override |
|
public final <T extends Annotation> T getAnnotation(Class<T> annotation) { |
|
return getDeclaredAnnotation(annotation); |
|
} |
|
|
|
@Override |
|
public final <T extends Annotation> T[] getAnnotationsByType(Class<T> annotation) { |
|
return getDeclaredAnnotationsByType(annotation); |
|
} |
|
|
|
@Override |
|
public final Annotation[] getDeclaredAnnotations() { |
|
return annotations.values().toArray(new Annotation[0]); |
|
} |
|
|
|
@Override |
|
@SuppressWarnings("unchecked") |
|
public final <T extends Annotation> T getDeclaredAnnotation(Class<T> annotation) { |
|
return (T)annotations.get(annotation); |
|
} |
|
|
|
@Override |
|
public final <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotation) { |
|
return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotations, annotation); |
|
} |
|
|
|
|
|
@Override |
|
public final Type getType() { |
|
return type; |
|
} |
|
|
|
|
|
final LocationInfo getLocation() { |
|
return location; |
|
} |
|
final TypeAnnotation[] getTypeAnnotations() { |
|
return allOnSameTargetTypeAnnotations; |
|
} |
|
final AnnotatedElement getDecl() { |
|
return decl; |
|
} |
|
} |
|
|
|
private static final class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType { |
|
AnnotatedArrayTypeImpl(Type type, LocationInfo location, |
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, |
|
AnnotatedElement decl) { |
|
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); |
|
} |
|
|
|
@Override |
|
public AnnotatedType getAnnotatedGenericComponentType() { |
|
return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(), |
|
getLocation().pushArray(), |
|
getTypeAnnotations(), |
|
getTypeAnnotations(), |
|
getDecl()); |
|
} |
|
|
|
private Type getComponentType() { |
|
Type t = getType(); |
|
if (t instanceof Class) { |
|
Class<?> c = (Class)t; |
|
return c.getComponentType(); |
|
} |
|
return ((GenericArrayType)t).getGenericComponentType(); |
|
} |
|
} |
|
|
|
private static final class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable { |
|
AnnotatedTypeVariableImpl(TypeVariable<?> type, LocationInfo location, |
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, |
|
AnnotatedElement decl) { |
|
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); |
|
} |
|
|
|
@Override |
|
public AnnotatedType[] getAnnotatedBounds() { |
|
return getTypeVariable().getAnnotatedBounds(); |
|
} |
|
|
|
private TypeVariable<?> getTypeVariable() { |
|
return (TypeVariable)getType(); |
|
} |
|
} |
|
|
|
private static final class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl |
|
implements AnnotatedParameterizedType { |
|
AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location, |
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, |
|
AnnotatedElement decl) { |
|
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); |
|
} |
|
|
|
@Override |
|
public AnnotatedType[] getAnnotatedActualTypeArguments() { |
|
Type[] arguments = getParameterizedType().getActualTypeArguments(); |
|
AnnotatedType[] res = new AnnotatedType[arguments.length]; |
|
Arrays.fill(res, EMPTY_ANNOTATED_TYPE); |
|
int initialCapacity = getTypeAnnotations().length; |
|
for (int i = 0; i < res.length; i++) { |
|
List<TypeAnnotation> l = new ArrayList<>(initialCapacity); |
|
LocationInfo newLoc = getLocation().pushTypeArg((byte)i); |
|
for (TypeAnnotation t : getTypeAnnotations()) |
|
if (t.getLocationInfo().isSameLocationInfo(newLoc)) |
|
l.add(t); |
|
res[i] = buildAnnotatedType(arguments[i], |
|
newLoc, |
|
l.toArray(new TypeAnnotation[0]), |
|
getTypeAnnotations(), |
|
getDecl()); |
|
} |
|
return res; |
|
} |
|
|
|
private ParameterizedType getParameterizedType() { |
|
return (ParameterizedType)getType(); |
|
} |
|
} |
|
|
|
private static final class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType { |
|
private final boolean hasUpperBounds; |
|
AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location, |
|
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations, |
|
AnnotatedElement decl) { |
|
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl); |
|
hasUpperBounds = (type.getLowerBounds().length == 0); |
|
} |
|
|
|
@Override |
|
public AnnotatedType[] getAnnotatedUpperBounds() { |
|
if (!hasUpperBounds()) |
|
return new AnnotatedType[0]; |
|
return getAnnotatedBounds(getWildcardType().getUpperBounds()); |
|
} |
|
|
|
@Override |
|
public AnnotatedType[] getAnnotatedLowerBounds() { |
|
if (hasUpperBounds) |
|
return new AnnotatedType[0]; |
|
return getAnnotatedBounds(getWildcardType().getLowerBounds()); |
|
} |
|
|
|
private AnnotatedType[] getAnnotatedBounds(Type[] bounds) { |
|
AnnotatedType[] res = new AnnotatedType[bounds.length]; |
|
Arrays.fill(res, EMPTY_ANNOTATED_TYPE); |
|
LocationInfo newLoc = getLocation().pushWildcard(); |
|
int initialCapacity = getTypeAnnotations().length; |
|
for (int i = 0; i < res.length; i++) { |
|
List<TypeAnnotation> l = new ArrayList<>(initialCapacity); |
|
for (TypeAnnotation t : getTypeAnnotations()) |
|
if (t.getLocationInfo().isSameLocationInfo(newLoc)) |
|
l.add(t); |
|
res[i] = buildAnnotatedType(bounds[i], |
|
newLoc, |
|
l.toArray(new TypeAnnotation[0]), |
|
getTypeAnnotations(), |
|
getDecl()); |
|
} |
|
return res; |
|
} |
|
|
|
private WildcardType getWildcardType() { |
|
return (WildcardType)getType(); |
|
} |
|
|
|
private boolean hasUpperBounds() { |
|
return hasUpperBounds; |
|
} |
|
} |
|
} |