org.aspectj.weaver.TypeVariableReferenceType Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjweaver Show documentation
Show all versions of aspectjweaver Show documentation
The AspectJ weaver introduces advices to java classes
/* *******************************************************************
* Copyright (c) 2005-2012 Contributors.
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://eclipse.org/legal/epl-v10.html
* ******************************************************************/
package org.aspectj.weaver;
import java.util.Map;
/**
* ReferenceType pointing to a type variable. The delegate for this reference type is the upperbound on the type variable (so
* Object if not otherwise specified).
*
* @author Adrian Colyer
* @author Andy Clement
*/
public class TypeVariableReferenceType extends ReferenceType implements TypeVariableReference {
private TypeVariable typeVariable;
public TypeVariableReferenceType(TypeVariable typeVariable, World world) {
super(typeVariable.getGenericSignature(), typeVariable.getErasureSignature(), world);
this.typeVariable = typeVariable;
}
@Override
public boolean equals(Object other) {
if (other instanceof TypeVariableReferenceType) {
return typeVariable==((TypeVariableReferenceType)other).typeVariable;
}
return false;
}
@Override
public int hashCode() {
return typeVariable.hashCode();
}
/**
* For a TypeVariableReferenceType the delegate is the delegate for the first bound.
*/
@Override
public ReferenceTypeDelegate getDelegate() {
if (this.delegate == null) {
ResolvedType resolvedFirstBound = typeVariable.getFirstBound().resolve(world);
BoundedReferenceTypeDelegate brtd = null;
if (resolvedFirstBound.isMissing()) {
brtd = new BoundedReferenceTypeDelegate((ReferenceType) world.resolve(UnresolvedType.OBJECT));
setDelegate(brtd); // set now because getSourceLocation() below will cause a recursive step to discover the delegate
world.getLint().cantFindType.signal(
"Unable to find type for generic bound. Missing type is " + resolvedFirstBound.getName(),
getSourceLocation());
} else {
brtd = new BoundedReferenceTypeDelegate((ReferenceType) resolvedFirstBound);
setDelegate(brtd);
}
}
return this.delegate;
}
@Override
public UnresolvedType parameterize(Map typeBindings) {
UnresolvedType ut = typeBindings.get(getName());
if (ut != null) {
return world.resolve(ut);
}
return this;
}
public TypeVariable getTypeVariable() {
return typeVariable;
}
@Override
public boolean isTypeVariableReference() {
return true;
}
@Override
public String toString() {
return typeVariable.getName();
}
@Override
public boolean isGenericWildcard() {
return false;
}
@Override
public boolean isAnnotation() {
ReferenceType upper = (ReferenceType) typeVariable.getUpperBound();
if (upper.isAnnotation()) {
return true;
}
World world = upper.getWorld();
typeVariable.resolve(world);
ResolvedType annotationType = ResolvedType.ANNOTATION.resolve(world);
UnresolvedType[] ifBounds = typeVariable.getSuperInterfaces();// AdditionalBounds();
for (int i = 0; i < ifBounds.length; i++) {
if (((ReferenceType) ifBounds[i]).isAnnotation()) {
return true;
}
if (ifBounds[i].equals(annotationType)) {
return true; // annotation itself does not have the annotation flag set in Java!
}
}
return false;
}
/**
* return the signature for a *REFERENCE* to a type variable, which is simply: Tname; there is no bounds info included, that is
* in the signature of the type variable itself
*/
@Override
public String getSignature() {
StringBuffer sb = new StringBuffer();
sb.append("T");
sb.append(typeVariable.getName());
sb.append(";");
return sb.toString();
}
/**
* @return the name of the type variable
*/
public String getTypeVariableName() {
return typeVariable.getName();
}
public ReferenceType getUpperBound() {
return (ReferenceType) typeVariable.resolve(world).getUpperBound();
}
/**
* resolve the type variable we are managing and then return this object. 'this' is already a ResolvedType but the type variable
* may transition from a not-resolved to a resolved state.
*/
public ResolvedType resolve(World world) {
typeVariable.resolve(world);
return this;
}
/**
* @return true if the type variable this reference is managing is resolved
*/
public boolean isTypeVariableResolved() {
return typeVariable.isResolved;
}
}