package net.bytebuddy.description.type; import net.bytebuddy.description.ByteCodeElement; import net.bytebuddy.description.annotation.AnnotationDescription; import net.bytebuddy.description.annotation.AnnotationList; import net.bytebuddy.matcher.ElementMatcher; import java.util.Collections; import java.util.List; /** * A tokenized representation of a type variable. */ public class TypeVariableToken implements ByteCodeElement.Token<TypeVariableToken> { /** * The type variable's symbol. */ private final String symbol; /** * The type variable's upper bounds. */ private final List<? extends TypeDescription.Generic> bounds; /** * The annotations of the type variable. */ private final List<? extends AnnotationDescription> annotations; /** * Creates a new type variable token without annotations. * * @param symbol The type variable's symbol. * @param bounds The type variable's upper bounds. */ public TypeVariableToken(String symbol, List<? extends TypeDescription.Generic> bounds) { this(symbol, bounds, Collections.<AnnotationDescription>emptyList()); } /** * Creates a new type variable token. * * @param symbol The type variable's symbol. * @param bounds The type variable's upper bounds. * @param annotations The annotations of the type variable. */ public TypeVariableToken(String symbol, List<? extends TypeDescription.Generic> bounds, List<? extends AnnotationDescription> annotations) { this.symbol = symbol; this.bounds = bounds; this.annotations = annotations; } /** * Transforms a type variable into a type variable token with its bounds detached. * * @param typeVariable A type variable in its attached state. * @param matcher A matcher that identifies types to detach from the upper bound types. * @return A token representing the detached type variable. */ public static TypeVariableToken of(TypeDescription.Generic typeVariable, ElementMatcher<? super TypeDescription> matcher) { return new TypeVariableToken(typeVariable.getSymbol(), typeVariable.getUpperBounds().accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)), typeVariable.getDeclaredAnnotations()); } /** * Returns the type variable's symbol. * * @return The type variable's symbol. */ public String getSymbol() { return symbol; } /** * Returns the type variable's upper bounds. * * @return The type variable's upper bounds. */ public TypeList.Generic getBounds() { return new TypeList.Generic.Explicit(bounds); } /** * Returns the annotations on this type variable. * * @return The annotations on this variable. */ public AnnotationList getAnnotations() { return new AnnotationList.Explicit(annotations); } @Override public TypeVariableToken accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) { return new TypeVariableToken(symbol, getBounds().accept(visitor), annotations); } @Override public boolean equals(Object other) { if (this == other) return true; if (!(other instanceof TypeVariableToken)) return false; TypeVariableToken that = (TypeVariableToken) other; return symbol.equals(that.symbol) && bounds.equals(that.bounds) && annotations.equals(that.annotations); } @Override public int hashCode() { int result = symbol.hashCode(); result = 31 * result + bounds.hashCode(); result = 31 * result + annotations.hashCode(); return result; } @Override public String toString() { return symbol; } }